ASE Home Page Products Download Purchase Support About ASE
ChartDirector Support
Forum HomeForum Home   SearchSearch

Message ListMessage List     Post MessagePost Message

  ASP.NET - System.OutOfMemoryException
Posted by Jake on Jun-14-2010 17:47
Over the past couple of days I'm seeing this memory exception appear a LOT when drawing the graphs


Exception Details: System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.



The offending line of code is:
     WebChartViewer0.Image = c.makeWebImage(Chart.PNG);



and the full stack trace is

[OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.]
   ChartDirector.DrawArea.e(Int32 A_0, Int32 A_1, Int32 A_2) +77
   ChartDirector.DrawArea.setSize(Int32 newWidth, Int32 newHeight, Int32 bgColor) +67
   ChartDirector.BaseChart.a() +45
   ChartDirector.BaseChart.b() +21
   ChartDirector.BaseChart.layoutLegend() +23
   ChartDirector.BaseChart.layout() +25
   ChartDirector.BaseChart.c() +61
   ChartDirector.BaseChart.makeChart(Int32 format) +16
   ChartDirector.BaseChart.makeChart2(Int32 format) +10
   ChartDirector.BaseChart.makeWebImage(Int32 imgFormat, Int32 timeout) +243
   ChartDirector.BaseChart.makeWebImage(Int32 imgFormat) +12
   Index.DisplayGraph() in e:\\htdocs\\index.aspx.cs:478
   Index.Page_Load(Object sender, EventArgs e) in e:\\htdocs\\index.aspx.cs:255
   System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) +14
   System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +35
   System.Web.UI.Control.OnLoad(EventArgs e) +99
   System.Web.UI.Control.LoadRecursive() +50
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +627




the chart generated is 24kbyte showing 3 line graphs. 650x680px.


help?!

  Re: ASP.NET - System.OutOfMemoryException
Posted by Peter Kwan on Jun-14-2010 19:36
Hi Jake,

The line that produces the error is allocated width * height * 4 bytes of memory (4 bytes per pixel to store the ARGB). If you chart is 650 x 680 px, then it is allocating 650 x 680 x 4 = 1768000 bytes of memory (around 1.7MB).

The OutOfMemoryException means your system cannot allocate the requested amount of memory. Some common reasons are:


(a) Your code are using a huge chart size (say 65000 x 68000 px). This will require huge amount of memory, and can cause the error. This may be due to a mistake in the code that creates the chart. (Are you chart size hard coded to 650 x 680, or are you using variables?

(b) Your system, for some reason, is using a lot of memory (eg. a memory leak exists somewhere in your system), and there is insufficient memory left. Because ChartDirector is a graphics library, and it uses more memory that text based HTML code, so if there is insufficient memory, ChartDirector usually will be the first to throw exceptions. (You seldom see a piece of text requiring 1.7MB, but a chart requiring 1.7MB is common.)

Because the .NET system uses garbage collection, it is not easy to leak memory. The most common way to leak memory is that the code stores objects in many Application or Session variables (instead of reusing existing Session variables). For example, if your code is using a unique session variable name for each chart (the name you use when you called makeSession), and you are using memory to store session variables, and the session does not break, then the system will eventually run out of memory. Similarly, if your system never breaks sessions (the session timeout is infinite), it will eventually run out of memory.

(c) Your system is having too many application pools/sessions and too little memory. (This usually happens in "shared hosting", in which a server can host a few hundreds to a few thousand sites.) The memory may be too little to support graphics application like ChartDirector.


To trouble-shoot memory problems, you may consider to hard code to chart size. This makes sure the error is not related to errors in chart size when creating the XYChart. You may monitor your ASP.NET memory usage. This can help to determine if there is  memory leaking. See:

http://msdn.microsoft.com/en-us/library/ms972959.aspx

Hope this can help.

Regards
Peter Kwan

  Re: ASP.NET - System.OutOfMemoryException
Posted by Jake on Jun-14-2010 19:42
- the graph size is hardcoded to that size and i dont consider it a "huge" graph.
- im not storing any large objects in session variables, just user ids
- it IS a shared host

I'm a bit concerned that it requires 1.7mb of memory just for one graph. Would this memory be immediately cleared after the graph is displayed?

I can just imagine that if I had say 1000 active users then this would be ~2gb of RAM used...

I guess possibly its the host thats struggling, but I'm a bit disappointed as it may mean I need to use other Graphic technology that isn't as memory intensive :-(

  Re: ASP.NET - System.OutOfMemoryException
Posted by Peter Kwan on Jun-14-2010 20:08
Hi Jake,

ChartDirector is already a graphics technology that is not memory intensive. It uses only very little memory. It is not easy to find graphics technology using less memory than ChartDirector. (The 1.7MB of memory is very small considering it is a graphics of size 650 x 680 pixels.)

The memory is allocated during "makeWebChart", and is released when your script ends (which should be milliseconds later). It is unlikely there will be 1000 users within milliseconds, so it should not be a concern.

There are many types of shared hosting. From my experience, high end shared hosting may put a few hundreds of web sites on a server. Low end shared hosting may put a few thousands sites on a web server. Some hosting companies may limit the RAM usage for each web site to a few MB. This may be sufficient for text based application, but insufficient for graphics based application.

Regards
Peter Kwan

  Re: ASP.NET - System.OutOfMemoryException
Posted by Lenin on Mar-07-2013 20:40

Hi,
Please note the code behind
[
public XYChart SetXYChart(int chartWidth, int chartHeight, int plotX, int plotY, int plotWidth, int plotHeight, bool legendPos)
            {
            XYChart c = new XYChart(chartWidth, chartHeight);

            c.setPlotArea(plotX, plotY, plotWidth, plotHeight, Chart.CColor(Color.White), Chart.CColor(Color.White), Chart.Transparent, c.dashLineColor(Chart.CColor(Color.Black), Chart.DashLine), c.dashLineColor(Chart.CColor(Color.White), Chart.DotLine))
if (legendPos)
                {
                c.addLegend(plotX, plotY - 800, false, "Arial Bold Italic", 50).setBackground(Chart.Transparent);
                } else
                {
                c.addLegend(plotX, plotHeight + 800, false, "Arial Bold Italic", 50).setBackground(Chart.Transparent);
                }
        }
]

[
generating chart uses below dynamically
c.getDrawArea().getWidth() =10000
c.getDrawArea().getHeight()=5500
]

[
get this error with chart director 4.1
Error Type:
System.OutOfMemoryExceptionError Message:
Exception of type 'System.OutOfMemoryException' was thrown.Stack Trace:
   at ChartDirector.DrawArea.setSize(Int32 newWidth, Int32 newHeight, Int32 bgColor)
   at ChartDirector.BaseChart.a()
   at ChartDirector.BaseChart.layoutLegend()
   at ChartDirector.BaseChart.layout()
   at ChartDirector.BaseChart.b()
   at ChartDirector.BaseChart.makeChart(Int32 format)
   at ChartDirector.BaseChart.makeChart2(Int32 format)
   at ChartDirector.BaseChart.makeWebImage(Int32 imgFormat, Int32 timeout)
   at ChartDirector.BaseChart.makeWebImage(Int32 imgFormat)
]

[
image is pasted to crystal report as
byte[] pImage = xyCHart.makeWebImage(Chart.PNG).image;
]

[
Question
Please do let me know if the memory disposal can be forced after makeWebImage()?
also if i constraint to increase website RAM space ,how to resolved this issue?
Please advice further?
]

  Re: ASP.NET - System.OutOfMemoryException
Posted by Peter Kwan on Mar-08-2013 00:13
Hi Lenin,

For your case, the out of memory occurs during makeWebImage, so freeing memory after makeWebImage would not solve the problem. The chart size in your case is 10000 x 5500 pixels, and the raw image itself requries 220 Mbytes of RAM (4 bytes per pixel). There are also other overhead (such as memory requires to handle 50 points fonts, and memory required to compress the 220 Mbytes into PNG in realtime). I suspect even after the overhead, the peak memory required would not exceed 500 Mbytes RAM. The peak memory is only required if the XYChart exist.

If your system has sufficient memory to complete the makeWebImage method call, and  what you need is just the pImage (the compressed PNG image), you can discarding the XYChart and the .NET system will garbage collect the memory. In the .NET system, discarding an object means removing all references to the XYChart. If in your code, the local variable "c" is the only reference to the XYChart, then the XYChart would be discard when "c" is out of scope. Note that the .NET system garbage collector may not immediately reclaim the memory. If you want the .NET garbage collector to run immediately, you would need to call GC.Collect yourself.

Hope this can help.

Regards
Peter Kwan

  Re: ASP.NET - System.OutOfMemoryException
Posted by Lenin on Mar-08-2013 16:14
Hi,
[
I have 32 crystal report renders as pdf on which i have 14 report created out of chart director embedded as image byte.The memory used for 14 chart director report as
10000*500*4*(1) = 220MB [1report]
2000*3000*4*(13) =312MB [13 report]
and calculated total is 632MB ,with 3 people using at max my consumption could be 1896MB but my website memory is 2000MB.
Is there a way to calculate exact memory required for the above requirement and how to project it with all addition charting/image information/metadata that could eat up memory apart from 1896MB?

if i generate only 28 report without chart director ,then there are no memory issue and hence all other object disposal is intact and suspect the chart director is consume all the space as shown above
]

[
Hence forced GC,but did not help

GC.Collect();
GC.WaitForPendingFinalizers();
before and afte calling makeWebImage()

byte[] pImage = xyCHart.makeWebImage(Chart.PNG).image;
xyCHart=null;
GC.Collect();
GC.WaitForPendingFinalizers();
]

Please advice futher.

  Re: ASP.NET - System.OutOfMemoryException
Posted by Peter Kwan on Mar-09-2013 02:59
Attachments:
Hi Lenin,

I have just performed a test using the attached ASPX. It creates an image 10000 x 5500 in size, obtain the PNG, then get the memory usage using GC.GetTotalMemory. After that, it dereference the chart, call GC.Collect, and get the memory usage again. It then displays the memory results.

In our machine, it finds that before GC.Collect(), the total memory consumed is around 277.7MB. After GC.Collect(), it consumes 2.28MB only. So the GC.Collect() frees over 275MB of memory, which is consistent with the fact that the XYChart itself should have been released.

For your case, please try my attach code to see if you obtain similar result. This can confirm if the GC works similarly in your machine.

Then you may use similar method to confirm if the memory used in the XYChart is in fact released in your actual code. If the memory is not released, is it possible you still maintain a reference to the XYChart somewhere?

If the memory is in fact released, but your system is still using a lot of memory, is it possible the memory is not used by ChartDirector? For example, if the crystal report of PDF generator somehow need to decompress the PNG back to the original image in order to create the PDF, then it would need similar amount of memory as ChartDirector.

As far as I know, there is no practical way to calculate "exact" memory requirement. Every chart is different, with different style, data, color, text, and compress to different size. It is also not known what is the overhead of the ASP.NET itself, or the overhead of the Windows font system or file system. As a rough estimation, we usually assume the pixels consume the bulk of the memory, and we assume 5 bytes per pixel. (Each pixel consume 4 bytes, and we add 1 as the overhead.)

Regards
Peter Kwan
simplebar.aspx
simplebar.aspx

1.27 Kb

  Re: ASP.NET - System.OutOfMemoryException
Posted by Lenin on Mar-11-2013 14:25
Hi Peter Kwan,
Thank for your reply.Please could you help to know if the heap can be compacted based on heap trace generator below for the application with chart director 3.1

[
Warning Detected symptoms of high fragmentation in the following heaps in w3wp.exe__EPIC__PID__4948__Date__03_08_2013__Time_09_55_27AM__820__Manual Dump.dmp


0x13900000 (netchartdir310!runMethod+1004212 - 77.30% Fragmented) Heap fragmentation is often caused by one of the following two reasons

1. Small heap memory blocks that are leaked (allocated but never freed) over time
2. Mixing long lived small allocations with short lived long allocations

Both of these reasons can prevent the NT heap manager from using free memory effeciently since they are spread as small fragments that cannot be used as a single large allocation


Heap Name   netchartdir310!runMethod+1004212
Heap Description   This heap is used by netchartdir310
Reserved memory   511.13 MBytes
Committed memory   3.55 MBytes (0.69% of reserved)
Uncommitted memory   507.57 MBytes (99.31% of reserved)
Number of heap segments   10 segments
Number of uncommitted ranges   65 range(s)
Size of largest uncommitted range   115.20 MBytes
Calculated heap fragmentation   77.30%
]

Regards,
Lenin

  Re: ASP.NET - System.OutOfMemoryException
Posted by Peter Kwan on Mar-11-2013 16:40
Hi Lenin,

I see what might be the cause of the problem now.

The ChartDirector version you are using is version 3.1, which was released 9 years ago. For that version, the code is not 100% managed code (it contains native code), and it uses unmanaged memory.

What happens is that the .NET system thinks it still have some memory left, so it does not automatically perform garbage collection to free memory. When ChartDirector requests a large block of memory (because of the huge chart size your code is using), the .NET system should see that it has insufficient memory, and will perform garbage collection to free the memory and "defragment" the memory, so your system should not run out of memory.

However, in ChartDirector 3.1, the memory requested is unmanaged. It means the .NET system cannot "see" the memory allocation of deallocation. At the operating system level, it sees that the .NET system is not freeing memory, but ChartDirector requests a large block of memory, so it runs out of memory. The .NET system also cannot "defragmenting" unmanaged memory, so sometimes even there is memory left, the operating system still cannot allocate the memory.

To solve the problem, I suggest you to upgrade to the latest version of ChartDirector, which is using fully managed code and all memory are fully managed by the .NET system. The .NET garbage collector should then automatically free and defragment the memory when necessary.

Please kindly let me know if the above can solve the problem.

Regards
Peter Kwan