Hi,
based on question for help and analysis that I received from my friend, I think I have to report critical bug in (I think) COM API:
Element class does not release memory when not used, so MicroStation consumes more and more memory until it crashes.
Test case:
Simple 2D design file with a lot of elements, I used an array 1000 x 1000 circles (too big to be shared, but simple to create).
Symptoms:
When active model is iterated (see code below), MicroStation allocates some memory (about 0.5 GB in my test case and VBA code) and this memory is never released (e.g. when macro ends or even when the file is closed). The only way is to close MicroStation and start again.
When Interop assembly is used from C#, the problem is the same, but amount of used memory seems to be higher (I did not do any exact benachmark).
When the same VBA code is run at V8i (SELECTseries 4), no problem with memory exists. In fact, Task Manager does not show any memory increase.
I tested 2 variants of VBA code and 1 version of C# code. VBA V1 is closer to problem inside application we analyzed, because Element IDs are used a lot, so GetElementById is used often.
VBA V1
Public Sub MemoryBenchmark() Dim ee As ElementEnumerator Set ee = ActiveModelReference.Scan Dim i As Integer For i = 1 To 10 Do While ee.MoveNext Dim el As Element Set el = ActiveModelReference.GetElementByID(ee.Current.ID) Loop Next End Sub
VBA V2
Public Sub MemoryBenchmark2() Dim ee As ElementEnumerator Set ee = ActiveModelReference.Scan For i = 1 To 10 Do While ee.MoveNext Dim el As Element Set el = ee.Current Loop Next End Sub
Based on comparing of VBA V1 and VBA V2 results in Task Manager it seems in VBA 2 the increase is about a half of VBA 1. So I assume the problem is in Element class, because in VBA 2 one extra Element instance is allocated in every iteration.
In C# the code is (namespaces used explicitly):
public void StartBenchmark2() { Bentley.Interop.MicroStationDGN.ModelReference modelIn = Bentley.MstnPlatformNET.InteropServices.Utilities.ComApp.ActiveModelReference; Bentley.Interop.MicroStationDGN.ElementEnumerator elementEnumerator = modelIn.Scan(); for (int i = 0; i < 10; i++) { while (elementEnumerator.MoveNext()) { Element interopEle = modelIn.GetElementByID64(elementEnumerator.Current.ID64); } elementEnumerator.Reset(); } }
In C#, I am able to exhaust all available memory easily (Windows 10 running with 32GB RAM).
When the code was rewritten to use DgnPlatformNET, it works fine, no memory increase reported.
Summary:
In a context of analyzed application (but is valid generally) this issue is critical, because it's "migration blocker".
Because of application complexity to rewrite the application to do not use Elements from Interop would probably requires several months plus extra time for extensive testing, so it's not the solution that can be used quickly.
May I ask for testing by somebody else to (not) confirm the problem?
With regards,
Jan
Hi Jan Šlegr,
Do you mind sharing exactly which Task Manager (memory) fields you are providing this feedback on? I am not discounting what you have provided, but we need to be certain what memory statistic is of concern since Windows Task manager at times does not provide an accurate indication of how application memory is used, consumed and released in various memory consumption (context) models.
Thank you in advance and I will take a look,Bob
Hi Bob,
thanks for your quick reaction.
In this "first analysis iteration" I used Processes tab in Windows Task Manager and I did not any more advanced memory profiling (later maybe I will check what e.g. RedGate memory profiler tells about running process).
I am aware (and I remember some detail blogs about this topic) memory reported by Task Manager is not exact what the application consumes, moreover the overall "memory allocation" is complex today ;-)
But regardless this a bit primitive measurement, I was able to crash MicroStation (and Windows complained a lot) because exhausting all memory, using repeatedly run C# Interop code (and I assume I would be able to do the same using VBA code too).
Bentley Accredited Developer: iTwin Platform - AssociateLabyrinth Technology | dev.notes() | cad.point
Hi Jan,
Are you using just and only the Memory column, or are there others you have enabled and using to monitor (if so I would like to know which ones) so we are on the same page (no pun intended but fine if you like).
Thank you,Bob
Robert Hook said:Are you using just and only the Memory column
Yes:
But I also captured some details also (sorry for Czech GUI):
When DGN with 1000x1000 elements array is opened:
After VBA 1 is finished (a lot of memory allocated):
When the file is closed and backstage is active (the most of memory is still not freed):
When it would help, I can create memory dumps, but I think you should see similar behavior also.
I wanted to make sure we identify the correct patient and I will queue this up to review asap and let you know.
Jan Šlegr said:Element class does not release memory when not used Public Sub MemoryBenchmark2() Dim ee As ElementEnumerator Set ee = ActiveModelReference.Scan For i = 1 To 10 Do While ee.MoveNext Dim el As Element Set el = ee.Current Loop Next End Sub
Does it make any difference if you explicitly free memory?
Public Sub MemoryBenchmark2() Dim ee As ElementEnumerator Set ee = ActiveModelReference.Scan For i = 1 To 10 Do While ee.MoveNext Dim el As Element Set el = ee.Current ' Free memory Set el = Nothing Loop Next End Sub
Regards, Jon Summers LA Solutions
Hi Jon,
no, nothing change (I tried it already).
From outside, without any knowledge what is "inside COM code", it seems like memory is allocated and never released, even when VBA project is unloaded or the design file is closed (in such case, it looks like only the memory holding the file content is released).
Thanks a lot.
Using this link (time expiration set) it's possible to download DGN file I use for testing.
Regards,
BTW Another "safe method" how to exhaust memory or crash MicroStation soon is to use the file I shared and to select all elements several times.
I have to appreciate (I guess it's Sunand Sandurkar team effort) MicroStation is able to select 1 mil. of elements now, even with Properties dialog opened (but it requires long time).
When I select all elements and deselect again and repeat this step, MicroStation consumes more and more memory. It's (again) not freed even when the file is closed in backstage. The difference with and without Properties dialog opened is only in amount of memory added to already used (and with Properties dialog it takes much longer).
I am not sure whether it is related internally to my original problem, but it's another issue with memory allocation I found during my testing.
this issue is reproducible and is a regression from V8i. Each assignment of an element object let grow the amount of used memory, so a file with just one single element and repeated assignment can be used to reproduce this issue.
We have filed Defect 1104232 with High priority to address this issue.
Best regards,Artur
Answer Verified By: Jan Šlegr