Announcement

Collapse
No announcement yet.

GlobalAlloc...

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Florent Heyworth
    replied
    Hi Semen

    I tested the Heap* functions and CoTaskMem* functions on my
    PII 400 MHz 256MB Ram and got interesting results. CoTaskMem*
    is faster than the Heap* functions using allocation of 1024 bytes
    for allocations larger than 1024 bytes.

    Interestingly the results are identical using allocations of
    512 bytes until 8Kb - 32Kb is allocated where CoTaskMemAlloc
    is faster. It leads me to think that CoTaskMemAlloc does use
    the HeapFunctions for smaller allocations. However CoTaskMemAlloc
    probably uses pooled virtual memory for larger allocations
    (see the results for 16Kb and 32Kb with 512 byte allocation).

    CoTaskMemAlloc seems to be very efficient. I'll post some tests
    using CoGetMalloc as soon as I get the time.

    Here are the results but they are to be taken with a pinch of salt
    since a series of timing runs shows large fluctuations across
    calls - it depends on the state of the system.

    Addendum: I forgot to mention that the Heap* functions were tested with
    %HEAP_ZERO_MEMORY OR %HEAP_NO_SERIALIZE so the comparison only is
    only valid for that combination.

    1024 byte allocation granularity results
    ---------------------------------------------------------------------
    Heap:
    Size = 1 Kb: 39.062500 ms per 1000 HeapAlloc/Free; total 1280 ms
    Size = 2 Kb: 74.218750 ms per 1000 HeapAlloc/Free; total 1216 ms
    Size = 4 Kb: 46.875000 ms per 1000 HeapAlloc/Free; total 384 ms
    Size = 8 Kb: 46.875000 ms per 1000 HeapAlloc/Free; total 192 ms
    Size = 16 Kb: 562.500000 ms per 1000 HeapAlloc/Free; total 1152 ms
    Size = 32 Kb: 437.500000 ms per 1000 HeapAlloc/Free; total 448 ms
    Size = 64 Kb: 625.000000 ms per 1000 HeapAlloc/Free; total 320 ms

    CoTaskMemAlloc:
    Size = 1 Kb: 66.406250 ms per 1000 CoTaskMemAlloc/Free; total 2176 ms
    Size = 2 Kb: 74.218750 ms per 1000 CoTaskMemAlloc/Free; total 1216 ms
    Size = 4 Kb: 31.250000 ms per 1000 CoTaskMemAlloc/Free; total 256 ms
    Size = 8 Kb: 31.250000 ms per 1000 CoTaskMemAlloc/Free; total 128 ms
    Size = 16 Kb: 468.750000 ms per 1000 CoTaskMemAlloc/Free; total 960 ms
    Size = 32 Kb: 187.500000 ms per 1000 CoTaskMemAlloc/Free; total 192 ms
    Size = 64 Kb: 125.000000 ms per 1000 CoTaskMemAlloc/Free; total 64 ms

    512 byte allocation granularity results
    -------------------------------------------------------------------
    Heap:
    Size = 512 b: 15.625000 ms per 1000 HeapAlloc/Free; total 256 ms
    Size = 1 Kb: 15.625000 ms per 1000 HeapAlloc/Free; total 128 ms
    Size = 2 Kb: 31.250000 ms per 1000 HeapAlloc/Free; total 128 ms
    Size = 4 Kb: 0.000000 ms per 1000 HeapAlloc/Free; total 0 ms
    Size = 8 Kb: 250.000000 ms per 1000 HeapAlloc/Free; total 256 ms
    Size = 16 Kb: 250.000000 ms per 1000 HeapAlloc/Free; total 128 ms
    Size = 32 Kb: 250.000000 ms per 1000 HeapAlloc/Free; total 64 ms


    CoTaskMemAlloc
    Size = 512 b: 15.625000 ms per 1000 CoTaskMemAlloc/Free; total 256 ms
    Size = 1 Kb: 15.625000 ms per 1000 CoTaskMemAlloc/Free; total 128 ms
    Size = 2 Kb: 15.625000 ms per 1000 CoTaskMemAlloc/Free; total 64 ms
    Size = 4 Kb: 31.250000 ms per 1000 CoTaskMemAlloc/Free; total 64 ms
    Size = 8 Kb: 0.000000 ms per 1000 CoTaskMemAlloc/Free; total 0 ms
    Size = 16 Kb: 125.000000 ms per 1000 CoTaskMemAlloc/Free; total 64 ms
    Size = 32 Kb: 0.000000 ms per 1000 CoTaskMemAlloc/Free; total 0 ms



    [This message has been edited by Florent Heyworth (edited October 04, 2000).]

    Leave a comment:


  • Semen Matusovski
    replied
    Lance --
    it's enough strange.
    I can imagine only that you have less physical/virtual memory than I.
    Try to reduce nn and/or For i1 = 1 To 7 (to 6 5 4)



    ------------------
    E-MAIL: [email protected]

    Leave a comment:


  • Lance Edmonds
    replied
    Semen, I've not debugged it, but your code does a GPF for me (under Windows 2000).



    ------------------
    Lance
    PowerBASIC Support
    mailto:[email protected][email protected]</A>

    Leave a comment:


  • Semen Matusovski
    replied
    I made a little test. Results (under Win2000, P-III-550) fully satisfied me.
    80-150 ms (depends of chunks) to allocate/free 32 Mb.
    Code:
        #Compile Exe
        #Register None
        #Dim All
        #Include "win32api.inc"
        Declare Function CoTaskMemAlloc Lib "ole32.dll" Alias "CoTaskMemAlloc" (ByVal Dword) As Dword
        Declare Sub CoTaskMemFree Lib "ole32.dll" Alias "CoTaskMemFree" (ByVal Dword Ptr)
        Function PbMain
           Local i1 As Long, i2 As Long, s As Long, n As Long, sPtr As Dword, t1 As Single, t2 As Single, w As String
           s = 1
           t1 = GetTickCount
           %nn = 16 ' (* 2) Mb
           For i1 = 1 To 7
              n = %nn * 1024& / s ' 32 ( * 2) Mb
              ReDim aPtr(1 To n) As Dword
              For i2 = 1 To n
                 ' Two steps forward, one behind
                 sPtr = CoTaskMemAlloc(1024& * s)
                 aPtr(i2) = CoTaskMemAlloc(1024& * s)
                 CoTaskMemFree sPtr
              Next
              For i2 = 1 To n
                 CoTaskMemFree aPtr(i2)
              Next
              t2 = GetTickCount
              w$ = w$ + $CRLF + "Size =" + Str$(s) + " Kb: " + _
                 Format$(1000# * (t2 - t1) / (2# * n), "#.######") + _
                 " ms per 1000 CoTaskMemAlloc/Free; total " + Format$(t2 - t1, "# ms")
              t1 = t2: s = s * 2
            Next
            MsgBox w$, ,  "Allocate/Free" + Str$(%nn) + " Mb (twice)"
        End Function
    Florent, what about Heap ?

    PS. As I understand, allocated memory is thread-safety automatic.
    Or I'm wrong ?

    ------------------
    E-MAIL: [email protected]

    Leave a comment:


  • Semen Matusovski
    replied
    James --

    I beleive that by design the central part of COM interface should be enough effective, not less than Heap (probably, they are based on the same code).
    And MSDN talks “The CoTaskMemAlloc function has the advantage of working well in either C, C++, or Visual Basic. It is also the only way to share memory in a COM-based application, since MIDL uses CoTaskMemAlloc and CoTaskMemFree to marshal memory”.

    Now main argument: I am too old and lazy to remember Heap functions with a lot of parameters .

    PS. Fragmentation - yes, exist (but virtual <> physical)
    Not initialized -- For me it's rather plus (anyway there is FillMemory)




    ------------------
    E-MAIL: [email protected]

    Leave a comment:


  • Florent Heyworth
    replied
    Hi James

    the CoTaskMem* functions are used by COM (IMalloc::Alloc) to
    allocate memory (but you knew that).

    Since COM objects can cross process boundaries and travel across
    the network as well as be used by different languages it was necessary
    to design a unified allocation scheme which is used by the underlying COM
    implementation.

    I may be wrong but I believe that the CoTaskMem* functions use the
    Heap functions to implement memory allocation so I would not expect
    them to be more efficient (the only sure way would be to benchmark).


    Cheers

    Florent

    ------------------

    Leave a comment:


  • jcfuller
    replied
    First I want to mention that I'm not arguing about Heap vs Ole, I'm trying to
    discover what are the advantages(if any) of using ole. I figure if
    Semen uses it it must have some merits that I'm missing .

    From the ole help file I see that the memory is not initialized where with
    HeapAlloc you can have it zeroed out. I prefer the block initialized.

    With HeapAlloc fragmentation is always a worry.
    Do the ole functions suffer from this?

    James

    ------------------


    [This message has been edited by jcfuller (edited October 03, 2000).]

    Leave a comment:


  • Tom Hanlin
    replied
    With GMEM_FIXED (or one of the flag sets that includes this bit),
    GlobalAlloc returns a pointer, not a handle. 16-bit Windows
    required handles because memory management had to be done in
    software, so there had to be a mechanism for disassociating the
    memory location with the handle. 32-bit Windows gets to use CPU
    hardware features to remap a pointer to point to different
    memory areas without needing to change the pointer itself, so
    handles are no longer required.

    I don't think this applies without the GMEM_FIXED qualifier, but
    it's been quite a while since I've looked at it.

    ------------------
    Tom Hanlin
    PowerBASIC Staff

    Leave a comment:


  • Semen Matusovski
    replied
    James --
    I tested under Win2000 only.
    Yes, memory is automatic freed also.
    Almost sure that it will be the same results in another OSes.




    ------------------
    E-MAIL: [email protected]

    Leave a comment:


  • jcfuller
    replied
    Semen,
    I do have the ole2 help file so I know it's usage but not the details.

    What happens if one forgets to call CoTaskMemFree?

    With the heap functions the memory used is automatically freed when the application
    terminates.

    James



    ------------------

    Leave a comment:


  • Semen Matusovski
    replied
    james --
    this is a "wrapper" for imalloc interface.
    advantage (for me) - very easy in use.
    you can find a sample in http://www.powerbasic.com/support/pb...ad.php?t=14863

    ------------------
    e-mail: [email protected]

    Leave a comment:


  • jcfuller
    replied
    Originally posted by Semen Matusovski:
    Guys --
    What do you think about CoTaskMemAlloc/Free ?

    Semen,
    I don't have any literature ( or if I do, I can't find it ) on CoTaskMemAlloc /Free.
    What is it primarily used for?
    Advantages / Disadvanatges vs HeapAlloc?

    James


    ------------------

    Leave a comment:


  • Edwin Knoppert
    replied
    I make use of heapalloc a while now.
    Pretty easy.

    Use "ByVal hMem", the hmem param is "AS ANY" !

    I also exp. a problem while realloc > 200x a small amount of mem.
    It crashes while i actually fill it (when > 200)
    It looks an incorrect address, don't know yet.
    I solved it by using a 'steady' mem but it's no solution.

    Anyone?


    ------------------
    [email protected]

    Leave a comment:


  • Michael Mattias
    replied
    I guess I should have read my MSDN and discovered that GlobalAlloc is quasi-obsolete now:

    From MSDN Library:

    The GlobalAlloc function allocates the specified number of bytes from the heap. Win32 memory management does not provide a separate local heap and global heap.

    Note The global functions are slower than other memory management functions and do not provide as many features. Therefore, new applications should use the heap functions. However, the global functions are still used with DDE and the clipboard functions.
    ...
    Return Values
    If the function succeeds, the return value is a handle to the newly allocated memory object.
    I think that "the handle=the address" is coincidence.

    And yes, this is leftover from Win/16

    MCM

    Leave a comment:


  • Peter P Stephensen
    replied
    jcfuller --

    You are right...(and very clever)

    Regards
    Peter

    ------------------

    Leave a comment:


  • jcfuller
    replied
    Correct me if I'm wrong but I believe GlobalAlloc is left over from 16bit.

    I personally use HeapAlloc.

    James


    ------------------


    [This message has been edited by jcfuller (edited October 02, 2000).]

    Leave a comment:


  • Don Dickinson
    replied
    Below is the code I use. Note that since I use the %GMEM_FIXED parameter is specified, the return value is the actual pointer to the memory not a handle.
    Best Regards,
    Don

    Code:
    '
    '  pb_mem.bas
    '
    '  Power Basic memory allocation routines.
    '  By Don Dickinson
    '  [email protected]
    '  Sept, 2000
    '
    '  Hereby public domain. Use as you see fit. 
    '
    #If Not %def(%PB_MEM_BAS)
    %PB_MEM_BAS = 1
    
    '- I assume that if %GMEM_FIXED isn't defined, then
    '  none of the windows api is included (win32api.inc)
    '  so I declare everything that's needed by this module.
    '
    #if not %def(%GMEM_FIXED)
       %GMEM_FIXED                                  = &H0
       %GMEM_MOVEABLE                               = &H2
       %GMEM_NOCOMPACT                              = &H10
       %GMEM_NODISCARD                              = &H20
       %GMEM_ZEROINIT                               = &H40
       %GMEM_MODIFY                                 = &H80
       %GMEM_DISCARDABLE                            = &H100
       %GMEM_NOT_BANKED                             = &H1000
       %GMEM_SHARE                                  = &H2000
       %GMEM_DDESHARE                               = &H2000
       %GMEM_NOTIFY                                 = &H4000
       %GMEM_LOWER                                  = %GMEM_NOT_BANKED
       %GMEM_VALID_FLAGS                            = &H7F72
       %GMEM_INVALID_HANDLE                         = &H8000
       Declare Function GlobalAlloc Lib "KERNEL32.DLL" Alias "GlobalAlloc" _
             ( ByVal wFlags As Long, ByVal dwBytes As Long) As Long
       Declare Function GlobalFree Lib "KERNEL32.DLL" Alias "GlobalFree" _
             ( ByVal hMem As Long) As Long
    
    #endif         
    
    '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    '  GetMem
    '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Function GetMem(ByVal iBytes As Long) As Long
    
       Function = GlobalAlloc(%GMEM_FIXED or %GMEM_ZEROINIT, iBytes)
    
    End Function
    
    
    '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    '  FreeMem
    '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Sub FreeMem(ByVal ptrMem As Long)
       If ptrMem Then
          GlobalFree ptrMem
       End If
    End Sub
    
    #endif

    [This message has been edited by Don Dickinson (edited October 02, 2000).]

    Leave a comment:


  • Peter P Stephensen
    replied
    Originally posted by Michael Mattias:

    Note that you must leave the memory locked (well, under Win/32 you really don't but you should) if you want to use the array elements, otherwise PB will be trying to acces memory no longer owned by the application, which, of course, means a GPF.
    Why should i if i dont have to?

    Regards
    Peter

    ------------------


    [This message has been edited by Peter P Stephensen (edited October 02, 2000).]

    Leave a comment:


  • Semen Matusovski
    replied
    Guys --
    What do you think about CoTaskMemAlloc/Free ?

    ------------------
    E-MAIL: [email protected]

    Leave a comment:


  • Michael Mattias
    replied
    GlobalAlloc does not return an address to DIM .. AT. It returns a handle.

    You get the address by executing GlobalLock(handle).

    After you DIM .. AT address, you can use PB to manipulate the array elements.

    When you are done, you can use GlobalUnlock and GlobalFree to return the memory to the system pool.

    Note that you must leave the memory locked (well, under Win/32 you really don't but you should) if you want to use the array elements, otherwise PB will be trying to acces memory no longer owned by the application, which, of course, means a GPF.

    MCM


    Leave a comment:

Working...
X