Learn how easy it is to sync an existing GitHub or Google Code repo to a SourceForge project! See Demo

Close

Problems with graphs in IE Explorer

Help
mesanchez
2007-06-13
2013-01-13
  • mesanchez
    mesanchez
    2007-06-13

    Hello,
       We have built a graphing application using cewolf. It allows the user to select a set of attributes and a time range to graph statistics data. Since it is user driven the amount of data will grow as the time or number of selected attributes increases. Using Mozilla we have not seen a limitation to display the data (besides that a larger set takes longer to graph). However in Internet Explorer at certain number of data points (which varies depending on the machine used and the data set values) the browser is unable to display the graph. When this point is reached the browser looses all images and looses font information.
      We have contacted Microsoft support and they have concluded that the problem is the way the application is graphing the results. This is making an exesive use of GDI objects in the machine and it eventually runs out of memory to process the graph.
       Given the broad usage of cewolf I was wondering if any of the users have experienced this problem before and how has been addressed.
      
       Thanks,
              Maria

    The jsp that we use to generate the graph is:

    .....

    <cewolf:overlaidchart
        id="line"
        title=""
        type="overlaidxy"
        xaxistype="date"
        yaxistype="number"
        xaxislabel="Time"
        yaxislabel="Values"
        showlegend="false" >
        <cewolf:plot type="<%=graphType%>">
                    <cewolf:data>
                            <cewolf:producer id="timeData" />
                    </cewolf:data>
       </cewolf:plot>
       <cewolf:colorpaint  color="#FFFFFF"/>

       <cewolf:chartpostprocessor id="timeData" />
       
    </cewolf:overlaidchart>

    <p>

    <cewolf:img chartid="line" renderer="cewolf" width="700" height="400">
        <cewolf:map linkgeneratorid="timeData"  tooltipgeneratorid="timeData" />
    </cewolf:img>

    <cewolf:legend renderer="cewolf" id="line" border="1" width="700" height="<%=timeLegendHeight%>">
    </cewolf:legend>

    <br>

    <P>

    .....

    The DataGraphProducer is as follows:
    //-----------------------------------
    // ** Package **
    //-----------------------------------

    package exodus.jstatsmon;

    import java.io.Serializable;
    import java.util.*;
    import java.text.*;
    import java.math.BigDecimal;

    import exodus.jflags.*;

    import org.jfree.data.category.*;
    import org.jfree.data.time.*;
    import org.jfree.data.xy.*;
    import org.jfree.chart.plot.*;
    import org.jfree.chart.*;
    import org.jfree.chart.renderer.xy.*;
    import org.jfree.chart.axis.*;

    import de.laures.cewolf.*;
    import de.laures.cewolf.links.*;
    import de.laures.cewolf.tooltips.*;

    public class JStatsDataGraphProducer implements DatasetProducer, XYToolTipGenerator, XYItemLinkGenerator , ChartPostProcessor, Serializable
    {
        private static TraceFlag graphProducerTF = new TraceFlag("graphProducerTF");

        private JStatsSession sessionObj;
        private DataGraph dataGraph;
        private HashMap nameAssignmentById = new HashMap();
        private TimeSeriesCollection dataSet;

        //
        // Need to get the queries and their results to display
        // in the graph
        //
        public final  void setDataGraph( DataGraph dataGraph)
        {
        this.dataGraph = dataGraph;
        }

        public final void setSessionRef(JStatsSession session)
        {
        sessionObj = session;
        }

        //
        // Main method used by cewolf to get the datasets
        //
        public Object produceDataset(Map params)
        throws DatasetProduceException
        {
       
        graphProducerTF.exoTraceLevel(1, "JStatsDataGraphProducer: creating dataSeries for cewolf");

            dataSet = new TimeSeriesCollection();
        SimpleDateFormat sdf = new SimpleDateFormat(JStatsConsts.ParsingDateFormat, Locale.US);

        ArrayList queryList = dataGraph.getQueryList();
        Query tmpQuery = null;
        String[] attributes = null;
        String seriesName;
        String uniqueName;
        ArrayList currentSeries = new ArrayList();
        int counter = 0; // Number of series

        try
        {
            for (int i = 0; i < queryList.size(); i++)
            {
            tmpQuery = (Query) queryList.get(i);
           
            //
            // We cannot graph no numeric values...
            // These queries that we skip here are presented as tables.
            //
            if (tmpQuery.hasNoNumeric())
            {
                continue;
            }

            if (tmpQuery.hasNoTimeAxis())
            {
                //
                // This is a no timeBased query. Not handled in this DataSet producer.
                //
                continue;
            }

            graphProducerTF.exoTraceLevel(2, "JStatsDataGraphProducer: Getting results for " +
                              tmpQuery.getUniqueName());

            ArrayList results = tmpQuery.getResults();
            if (results == null)
            {
                //
                // There is no data to create dataSet.
                //
                graphProducerTF.exoTraceLevel(2, "JStatsDataGraphProducer: Query " +
                              tmpQuery.getUniqueName() + " has no data ");
                continue;
            }
            attributes = tmpQuery.getAttributes();
            TimeSeries series = null;
            String[] values;
            uniqueName = tmpQuery.getUniqueName();
            int records = 0;
            for (int k = 0 ; k < attributes.length ; k++)
            {
                String tmpAttr =  sessionObj.getLogSchema().getAttributeDisplayName(tmpQuery.getTypeName(), tmpQuery.getDataSetName(),attributes[k]);
                seriesName = uniqueName + ":" + tmpAttr;
                series = new TimeSeries(seriesName,FixedMillisecond.class);
                records = results.size();
                graphProducerTF.exoTraceLevel(2, "JStatsDataGraphProducer: Query "+
                              tmpQuery.getUniqueName() + " has " + records + " results");

                for (int j = 0 ; j < records; j++)
                {
                values = (String[]) results.get(j);
                if (values[k+1] != null)
                {
                    if (values[k+1].indexOf(".") < 0)
                    {
                    Long longValue = new Long(values[k+1]);
                    series.addOrUpdate(new FixedMillisecond(sdf.parse(values[0])), longValue.doubleValue());
                    }
                    else
                    {
                    Double dValue = new Double(values[k+1]);
                    series.addOrUpdate(new FixedMillisecond(sdf.parse(values[0])), dValue.doubleValue());
                    }
                }
                }
                if (records>0)
                        {
                dataSet.addSeries(series);
                sessionObj.assignColor(seriesName,counter);
                currentSeries.add(seriesName);
                nameAssignmentById.put(new Integer(counter), seriesName);
                counter++;
                }
            }
            }
            //
            // Got all data for graph. Set update to false. Will not re-read
            // this data until the graph has new data.
            //
            dataGraph.setUpdated(false);
            //
            // Release colors assigned to attributes that are not longer
            // displayed in the graph.
            //
            sessionObj.releaseColors(currentSeries);

            graphProducerTF.exoTraceLevel(1, "JStatsDataGraphProducer: FInished creating dataSeries for cewolf");
            return dataSet;
        }
        catch (ParseException ex)
        {
            throw new DatasetProduceException(ex.toString());
        }
        }

        public final boolean hasExpired(Map params, Date since) {       
        return dataGraph.getUpdated();
        }

        public final String getProducerId() {
        return "JStatsmon DatasetProducer";
        }

        //
        // Required to generate tool-tip
        //
        public String generateToolTip(XYDataset data, int series, int item)
        {
        SimpleDateFormat dateformat = new SimpleDateFormat(JStatsConsts.DisplayDateFormat);
        Date d = new Date(((Long)data.getX(series,item)).longValue());
        String seriesName = (String) nameAssignmentById.get(new Integer(series));

        String yValue = "" + data.getY(series,item);
        if (yValue.indexOf(".0") >= 0)
        {
            yValue = yValue.substring(0, yValue.indexOf("."));
        }
        return seriesName +":::Time=" + dateformat.format(d) + ":::Value="+ yValue;
        }

        //
        // The link associated to a point in the graph
        //
        public String generateLink(Object data, int series, int item)
        {
        //
        // This date format is expected in the javascript function to change
        // time window: "06/12/05 13:02:34"
        //
        SimpleDateFormat dateformat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
        XYDataset dataset = (XYDataset) data;
        Date d = new Date(((Long)dataset.getX(series,item)).longValue());   
        return "javascript:changeTime('" + dateformat.format(d) + "')";
        }

        //
        // This is required to change the colors of the series and apply
        // other post processing to the graph.
        // This is the way I currently have found to access jfreechart features for graph
        // manipulation.
        //
        public void processChart(Object chart, Map params) {
       
        graphProducerTF.exoTraceLevel(1, "JStatsDataGraphProducer: postProcessing the chart");

            XYPlot plot = ((JFreeChart) chart).getXYPlot();
        XYItemRenderer renderer = plot.getRenderer(0);

        for (int i = 0; i < dataSet.getSeriesCount() ; i++)
        {
            renderer.setSeriesPaint(i, java.awt.Color.decode(sessionObj.getColorAssignedForIndex(i)));
        }

        //
        // Set the range for the graph, do not include zero if not necesary.
        //
        ((NumberAxis) plot.getRangeAxis()).setAutoRangeIncludesZero(false);
       
        }

    }

     
    • Brian Fox
      Brian Fox
      2007-06-13

      cewolf generates an image file, so it shouldn't matter how many data points you have, except if you have the tooltips turned on. You could try turning them off to see if that's the problem.

       
      • mesanchez
        mesanchez
        2007-06-14

        Yes I did and the tooltips are the problem. However having the tooltip is a requirement and cannot be removed. Is there any recommendation regarding this problem? Have anybody reported this problem before?
        BTW, this is not a problem in Mozilla. Is there any difference in the way tooltips are generated for IE and Mozilla?

         
        • Brian Fox
          Brian Fox
          2007-06-14

          There is a difference. In mozilla, cewolf uses something called overlay.js to render the tooltips. I've never experienced this particular problem or heard of it before.

           
    • mesanchez
      mesanchez
      2007-06-16

      If the problem is the tooltip generated for each point in a graph, I could limit the number of points with tooltips instead of the number of points in the graph. Say I allow only 3000 tooltips. Since I know the number of total points per serie I could control what points have tooltips and which ones do not have....

      in the DataGraphGenerator I have the method generateToolTip() if this method returns null will it avoid generating the tooltip or creates an empty one?

       
    • Rinke Hoekstra
      Rinke Hoekstra
      2007-06-18

      Interesting discussion, especially since I have an application too, in which users could generate a very long graph filled with tooltips.

      Maria, could you give an indication when this starts becoming a problem? How many tooltips can you create before you machine starts having memory problems (and what is the amount of memory available on the machine - or better: how much memory does 1 tooltip cost?)

      Rinke

       
    • mesanchez
      mesanchez
      2007-06-19

      Rinke,
         What Microsoft support thinks is that it is generating a GDI object per tooltip. I do not know how much memory each one uses. The amount of points varies per machine, as expected, the lowest number we have had is 2000 points, the max points were ~8000 (this after extending the number of GDI objects). The problem is that eventually it can reach the limit. Once this is reached the machine ussually needs to be restarted.

         Thanks,
             Maria