6

I have a 32-bit Delphi application running with /LARGEADDRESSAWARE flag on. This allows to allocate up to 4GB on a 64-bit system.

Am using threads (in a pool) to process files where each task loads a file in memory. When multiple threads are running (multiple files being loaded), at some point the EOutOfMemory hits me.

What would be the proper way to get the available address space so I can check if I have enough memory before processing the next file?

Something like:

if TotalMemoryUsed {from GetMemoryManagerState} + FileSize < "AvailableUpToMaxAddressSpace" then NoOutOfMemory

I've tried using

TMemoryStatusEx.ullAvailVirtual for AvailableUpToMaxAddressSpace

but the results are not correct (sometimes 0, sometimes > than I actually have).

ajitksharma
  • 4,523
  • 2
  • 21
  • 40
Torpedo
  • 185
  • 10

3 Answers3

2

I don't think that you can reasonably and robustly expect to be able to predict ahead of time whether or not memory allocations will fail. At the very least you would probably need to write your own memory allocator that was dedicated to serving your application, and have a very strong understanding of the heap allocation requirements of your process.

Realistically the tractable way forward for you is to break free from the shackles of 32 bit address space. That is your fundamental problem. The way to escape from 32 bit address space is to compile for 64 bit. That requires XE2 or later.

You may need to continue supporting 32 bit versions of your application because you have users that are still on 32 bit systems. The modern versions of Delphi have 32 bit and 64 bit compilers and it is quite simple to write code that will compile and behave correctly under both scenarios.

For your 32 bit versions you are less likely to run into memory problems anyway because 32 bit systems tend to run on older hardware with fewer processors. In turn this means less demand on memory space because your thread pool tends to be smaller.

If you encounter machines with large enough processor counts to cause out of memory problems then one very simple and pragmatic approach is to give the user a mechanism to limit the number of threads used by your application's thread pool.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
1

Since there are more processes running on the target system even if the necessary infrastructure would be available, if would be no use.


There is no guarantee that another process does not allocate the memory after you have checked its availability and before you actually allocate it. The right thing to do is writing code that will fail gracefully and catch the EOutOfMemory exception when it appears. Use it as a sign to stop creating more threads until some of them is already terminated.

mg30rg
  • 1,311
  • 13
  • 24
  • 2
    We are talking about virtual memory and not physical – David Heffernan Oct 14 '14 at 13:06
  • @DavidHeffernan Then I'm wrong here. I see now. I never thought anyone can ever run out of virtual memory. (With a code that isn't directly targeting memory consumption.) But even in that case, my solution would work without problems. – mg30rg Oct 14 '14 at 13:09
  • Running out of virtual memory is a massively real issue. 64 bit code is the way out. – David Heffernan Oct 14 '14 at 13:10
  • @DavidHeffernan: I still need to support 32-bit Windows (XP) – Torpedo Oct 14 '14 at 14:06
  • So have two versions, a 32 bit and a 64 bit version. For the very small number of users of your 32 bit version, they will likely not have many cores on their now ancient machines, and so not fall foul of the problem. Or you just work around the problem by limiting the number of threads in your pool. – David Heffernan Oct 14 '14 at 14:08
  • @DavidHeffernan: yes, makes sense. However limiting the number of threads is what's bothering me: as I cannot be for sure what the number should be since I can have files of various size being processed and the actual order of processing is where the problem originates: depending on the "order" of how they are processed. My idea was to move such "big" files at the end of the queue but I need a way to figure out I am out of address space before trying to process a file and run into EOOM. – Torpedo Oct 14 '14 at 14:18
  • What we did was let the user control how many threads to use. They just pick as large a value as they could get away with. Not really a problem for us any more because 64 bit is so prevalent. – David Heffernan Oct 14 '14 at 14:19
  • @DavidHeffernan - Your solution reminds me of [a blog post on the old new thing](http://blogs.msdn.com/b/oldnewthing/archive/2004/04/26/120193.aspx). :D – mg30rg Oct 14 '14 at 14:51
0

Delphi is 32bit, so you can't allocate memory addresses larger than that.

Take a look at this: What is a safe Maximum Stack Size or How to measure use of stack?

Community
  • 1
  • 1
Drejc
  • 14,196
  • 16
  • 71
  • 106