2 Replies Latest reply on Jan 25, 2011 10:28 AM by Ducci1012

    large range on LinearAxis causes error

    beckerb4
      I found that if your data has very large values like 10^16, then your scatter or bubble plot will spin its wheels and use up a lot of memeory until you eventually get an error like:

      Error: Error #1502: A script has executed for longer than the default timeout period of 15 seconds.
      at mx.charts::AxisLabel$iinit()
      at mx.charts::LinearAxis/mx.charts:LinearAxis::buildLabelCache()
      at mx.charts.chartClasses::NumericAxis/getLabels()
      at mx.charts::AxisRenderer/::measureLabels()
      at mx.charts::AxisRenderer/::calcRotationAndSpacing()
      at mx.charts::AxisRenderer/adjustGutters()
      at mx.charts.chartClasses::CartesianChart/::updateAxisLayout()
      at mx.charts.chartClasses::CartesianChart/mx.charts.chartClasses:CartesianChart::updateDispl ayList()
      at mx.core::UIComponent/validateDisplayList()
      at mx.managers::LayoutManager/::validateDisplayList()
      at mx.managers::LayoutManager/::doPhasedInstantiation()
      at Function/ http://adobe.com/AS3/2006/builtin::apply()
      at mx.core::UIComponent/::callLaterDispatcher2()
      at mx.core::UIComponent/::callLaterDispatcher()

      I looked at the code in LinearAxis and it appears to be creating a few trillion Label objects in a for loop.
      Here is a simple test case to help you reproduce the problem:

      <?xml version="1.0" encoding="utf-8"?>
      <mx:Application
      xmlns:mx=" http://www.adobe.com/2006/mxml"
      layout="absolute" pageTitle="Experiments in Flex Charting"
      width="100%" height="100%" >

      <mx:Script> <![CDATA[
      import mx.formatters.NumberFormatter;
      import mx.collections.*;
      import mx.charts.*

      [Bindable]
      private var expenses:ArrayCollection = new ArrayCollection([
      {Month: "Jan", Profit: 240, Expenses: 100000250007087990, Amount: 1450},
      {Month: "Feb", Profit: 160, Expenses: 100000250007087980, Amount: 1600},
      {Month: "Mar", Profit: 90, Expenses: 100000250007087970, Amount: 2700}
      ]);
      ]]>
      </mx:Script>

      <mx:HBox height="100%" width="100%">
      <mx:BubbleChart id="scatter2" paddingLeft="5" height="100%" width="100%"
      paddingRight="5" dataProvider="{expenses}" showDataTips="true">
      <mx:horizontalAxis>
      <mx:LinearAxis baseAtZero="false" title="Profit" />
      </mx:horizontalAxis>
      <mx:verticalAxis>
      <mx:LinearAxis baseAtZero="false" title="Expenses"/>
      </mx:verticalAxis>
      <mx:series>
      <mx:Array>
      <mx:PlotSeries xField="Expenses" yField="Profit" name="Expenses/Profit" displayName="Profit2" />
      </mx:Array>
      </mx:series>
      </mx:BubbleChart>
      </mx:HBox>
      </mx:Application>
        • 1. Re: large range on LinearAxis causes error
          beckerb4 Level 1
          A very similar thing happens if your data contains very small values like 10^-12.
          It exists after pegging the CPU for a minute with this error:
          Error: Error #1503: A script failed to exit after 30 seconds and was terminated.
          at mx.managers::FocusManager/::deactivateHandler()

          Here is a simple example to demonstrate:

          <?xml version="1.0" encoding="utf-8"?>
          <mx:Application
          xmlns:mx=" http://www.adobe.com/2006/mxml"
          layout="absolute" pageTitle="Experiments in Flex Charting"
          width="100%" height="100%" >

          <mx:Script> <![CDATA[
          import mx.formatters.NumberFormatter;
          import mx.collections.*;
          import mx.charts.*

          // test case to show flex performance problem and crash of IE

          [Bindable]
          private var expenses:ArrayCollection = new ArrayCollection([
          {Month: "Jan", Profit: 2400, Expenses: .00000000000250007087980, Amount: 1450},
          {Month: "Feb", Profit: 1600, Expenses: .000000000001600098798, Amount: 1600},
          {Month: "Mar", Profit: 1900, Expenses: .0000000000020009987987, Amount: 2700}
          ]);
          ]]>
          </mx:Script>

          <mx:HBox height="100%" width="100%">
          <mx:BubbleChart id="scatter2" paddingLeft="5" height="100%" width="100%"
          paddingRight="5" dataProvider="{expenses}" showDataTips="true">
          <mx:horizontalAxis>
          <mx:LinearAxis baseAtZero="false" title="Profit" />
          </mx:horizontalAxis>
          <mx:verticalAxis>
          <mx:LinearAxis baseAtZero="false" title="Expenses"/>
          </mx:verticalAxis>
          <mx:series>
          <mx:Array>
          <mx:PlotSeries xField="Expenses" yField="Profit" name="Expenses/Profit" displayName="Profit2" />
          </mx:Array>
          </mx:series>
          </mx:BubbleChart>
          </mx:HBox>
          </mx:Application>
          • 2. Re: large range on LinearAxis causes error
            Ducci1012

            I know this is an old topic, but I'm posting my findings for those still using Flex 2 (like me) that may stumble upon this.  Not sure if these are great fixes, but I'm pretty sure I've pinpointed both problems.  The case with small values seems to be a quick fix, but the one for large values I'm not quite sure what the correct fix is.

             

            For small values, you'll notice that in LinearAxis.as, buildMinorTickCache(), line 451 (again, Flex 2) has the line:

             

            var labelTop:Number = computedMaximum + 0.000001;

             

            I do not know why the "+ 0.000001" portion is there.  Is there a valid reason?  It seems to be a pretty major assumption about what kind of data is coming in.  This breaks the axis BIG TIME.  We had values around 2.23e-26, and the interval was calculated as an equally tiny value using these values.  Right before the function loops to build the axis cache, it DRASTICALLY changes that value by adding the .000001, which leads to the axis cache looping infinitely.  Our top value goes from the 2.23e-26 range up to about 1.4e-6.  Looping from 2.23 up to 1.4e-6 using a tiny increment, it needed to loop trillions of times, and store that many values in an array!   Simply copying this function and removing that small addition in an override fixes the issue completely.  I am able to chart the above example case without issue, and have handled all of our extremely small values (we're also only using 32-bit float values, so plenty of precision in the Number class).  I cannot figure out why that value is added on...

             

            For the case of large values example above, I'm still not sure what the best approach is.  It appears to be a problem with the Flex Number class.  You'll notice that in buildLabelCache() in either of the for loops at line 353 or 366 will loop infinitely.  The labelBase value is calculated as 100000250007087968, a labelTop value of 100000250007087984 (not high enough), and an interval of 2 (should be fine).  However, we will loop infinitely.  Why?  Because the labelBase value doesn't get incremented by the value of 2 due to what I imagine is some sort of large value precision issue.  Not much of a workaround for that other than to somehow detect that the value stays the same and abort...

             

            We did have issues with our larger values (again, 32-bit) which was pretty similar to the small value issue.  Overriding NumericAxis' guardMinMax() function and setting the (min==max) case to return values +/- 10% has all of our large values working.  Because we're using 32-bit float our large values get represented almost as the same, but not overrriding guardMinMax caused it to try to scale from 0 up to the really large value.  This override solves that issue, as well as some weird issues where the axis tries to use 0-100 in cases where it's not entirely appropriate (for example, try charting a couple points, all just -5).  We're not generally using values this large so we're not too concerned, but we can it being totally possible to run into the loop problem as above in special cases.