Search code examples
vb.netmemory-managementmemory-leaksgarbage-collectionilnumerics

Unexpected OutOfMemoryException in ILNumerics


The following VB .net code gives me an out of memory exception. Does anybody knows why?

Dim vArray As ILArray(Of Double) = ILMath.rand(10000000)

Using ILScope.Enter(vArray)
   For i As Integer = 1 To 100
     vArray = ILMath.add(vArray, vArray)
   Next
End Using

Thank you very much.


Solution

  • In this toy example you can simply remove the artificial scope and it will run fine:

    Dim vArray As ILArray(Of Double) = ILMath.rand(10000000)
    
    For i As Integer = 1 To 100
        vArray = ILMath.add(vArray, vArray)
    Next
    Console.WriteLine("OK: " + vArray(0).ToString())
    Console.ReadKey()
    

    However, in a more serious situation, ILScope will be your friend. As stated on the ILNumerics page an artificial scope ensures a deterministic memory management:

    All arrays created inside the scope are disposed once the block was left.

    Otherwise one had to rely on the GC for cleanup. And, as you know, this involves a gen 2 collection for large objects – with all disadvantages in terms of performance.

    In order to be able to dispose the arrays they need to be collected and tracked somehow. Whether or not this qualifies for the term 'memory leak' is rather a philosophical question. I will not go into it here. The deal is: after the instruction pointer runs out of the scope these arrays are taken care of: their memory is put into the memory pool and will be reused. As a consequence, no GC will be triggered.

    The scheme is especially useful for long running operations and for large data. Currently, the arrays are released only AFTER the scope block was left. So if you create an algorithm/ loop which requires more memory than available on your machine you need to clean up DURING the loop already:

        Dim vArray As ILArray(Of Double) = ILMath.rand(10000000)
    
        For i As Integer = 1 To 100
            Using ILScope.Enter
                vArray.a = ILMath.add(vArray, vArray)
                ' ... 
            End Using
        Next
    

    Here, the scope cleans up the memory after each iteration of the loop. This affects all local arrays assigned within the loop body. If we want an array value to survive the loop iteration we can assign to its .a property as shown with vArray.a.