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.
Thanks a lot.
Using this link (time expiration set) it's possible to download DGN file I use for testing.
Regards,