Page 1 of 1

AvailableMemory()

Posted: Wed Sep 09, 2009 5:17 am
by Rescator
I have no idea what the Linux and MacOS equivalents are but I'm sure they exist.

PS! Reason for the Ex is due to the official MDSN stating that the non Ex might not be reliable on 4GB+ systems, so the Ex is preferred when available.

The reason I want this is that, at least on Windows Vista (Win7 and XP as well?) it is possible to allocate so much memory that the system basically locks up.
Take for example just moments ago here, I allocated about 8GB, but I only have 4GB physical memory. I have Vista x64, the compiled program was also x64. My page file is around 8GB.

The allocation went fine (4+8GB virtual mem I guess?), but when I was to use FillMemory() the system slowed to a crawl as Windows tried to page out ALL memory, including OS memory and some kernel memory.
It took several minutes too open Task manager, several minutes to select, several minutes to wait for the kill box, several minutes after confirming, several minutes for the system to get responsive again.
(For those unaware, the memory is reserved but not really allocated until it's first used. So just because the allocation went ok does not mean the system won't kneel when you start using that memory)

Ideally AllocateMemory() should have a Check parameter that defaults to true, but since there is no way to atomically check available mem and then allocate that's out of the question I guess.
But a AvailableMemory() makes sense, which reports the memory available for allocation that will not cause a major issue for the OS or other applications.

I'll definitely from now on use this when allocating very large or user defined memory sizes, because as I found out, even a triple core CPU with Vista x64 can be brought to it's knees, which surprised me, because with 3 cores, even if a program went into a death loop it's still have 2x33% cpu power, so opening task manager has never been an issue unlike on single core CPU's.

So if a AvailableMemory() is added to a future PureBasic release I'm sure more than just me would be very happy :)

Example implementation on windows:

Code: Select all

Procedure.q AvailableMemory()
 Protected result.q,memorystatusex.MEMORYSTATUSEX,memorystatus.MEMORYSTATUS,*GlobalMemoryStatusEx,dll.i
 dll=OpenLibrary(#PB_Any,"kernel32.dll")
 If dll
  *GlobalMemoryStatusEx=GetFunction(dll,"GlobalMemoryStatusEx")
 EndIf
 If *GlobalMemoryStatusEx
  memorystatusex\dwLength=sizeof(MEMORYSTATUSEX)
  CallFunctionFast(*GlobalMemoryStatusEx,memorystatusex)
  result=memorystatusex\ullAvailPhys
 Else
  GlobalMemoryStatus_(memorystatus)
  result=memorystatus\dwAvailPhys
 EndIf
 If dll
  CloseLibrary(dll)
 EndIf
 ProcedureReturn result
EndProcedure

Re: AvailableMemory()

Posted: Wed Sep 09, 2009 9:48 am
by UserOfPure
Rescator wrote:on Windows Vista (Win7 and XP as well?) it is possible to allocate so much memory that the system basically locks up.
Damn. You'd think Microsoft would've prevented such behavior by now. I mean, why can't they just NOT let apps allocate too much memory? They should always make it so that (for example) 640 KB is always free for the OS, no matter what the app wants. So if the app wants 2 GB but there's only 2 GB free, it should allocate all but 640 KB instead. And then if other apps want to allocate some after that, they get denied. Fair enough to me. It's how I'd do it if I ran Microsoft. :)

Why 640 KB? Because 640 KB should be enough for everybody. ;)

Posted: Wed Sep 09, 2009 12:15 pm
by freak
Limiting memory allocation to only the available physical memory is too restrictive because the system can easily handle more by paging things out.

Yeah, available virtual memory, I know.

Posted: Thu Sep 10, 2009 7:39 am
by Rescator
But a AvailableMemory() like above that returns the largest allocatable memory that does not include page memory is very important IMO.
To put it another way, if somebody uses AvailableMemory() as implemented above, and does not think that's enough memory for their program,
then it's a special program with special requirements, as far as I know, all such if properly implemented uses their own temp files while working.

For example using AvailableMemory()>>1 to allocate a huge work buffer should be fine on most systems,
if anyone knows how to do a Linux and MacOS variant of AvailableMemory() above I'd be very happy :)

PS! Fix an issue with the code, x86 also needs quad, as it returned 3GB here (actually -1.2GB since the old code uses .i oops)

Re: AvailableMemory()

Posted: Thu Sep 10, 2009 9:27 am
by remi_meier
Linux:

Code: Select all

pgs = getpagesize_()
free_pg = get_avphys_pages_()
Debug "Without HD cache:"
Debug "Pagesize: "+Str(pgs)
Debug "Free pages: "+Str(free_pg)
Debug "Free Mem (MB): "+StrF(pgs * free_pg / 1024 / 1024)



Structure sysinfo
  uptime.i
  loads.i[3]
  totalram.i
  freeram.i
  sharedram.i
  bufferram.i
  totalswap.i
  freeswap.i
  procs.w
  _f.a[22]
EndStructure
ImportC ""
  sysinfo(*sysinfo)
EndImport



sys_info.SYSINFO
sysinfo(@sys_info)

Debug "Sysinfo:"
Debug "Free Ram (MB): " + Str(sys_info\freeram / 1024 / 1024)
Debug "Buffer Ram (MB): " + Str(sys_info\bufferram / 1024 / 1024)
Debug "Kinda free ram (MB): " + Str((sys_info\freeram + sys_info\bufferram) / 1024 / 1024)
But I'm not really sure if it is correct for 64bit as I cannot test..

Re: Yeah, available virtual memory, I know.

Posted: Fri Sep 11, 2009 12:31 am
by freak
Rescator wrote:But a AvailableMemory() like above that returns the largest allocatable memory that does not include page memory is very important IMO.
To put it another way, if somebody uses AvailableMemory() as implemented above, and does not think that's enough memory for their program,
then it's a special program with special requirements, as far as I know, all such if properly implemented uses their own temp files while working.
I don't really get why you would need that still. You allocate the amount of memory you need (and only that). Why would you allocate a potentially large amount of memory without knowing wether you need it it or not ? Either you really need an amount of memory, then just ask for it. Or you don't need it then do not allocate it (even if you can). If a program grabs all my available physical memory just because it can it will be off my system very quickly.
Rescator wrote:For example using AvailableMemory()>>1 to allocate a huge work buffer should be fine on most systems,
if anyone knows how to do a Linux and MacOS variant of AvailableMemory() above I'd be very happy :)
And if AvailableMemory() sais there is not the amount you need ? Do you throw an "out of memory" error ? This will be very annoying to the user because a system _can_ provide much more virtual memory than its physical memory.

I'm not saying a function like that has no uses, but what you want to use it for is not a very good coding style in my opinion.

Re: AvailableMemory()

Posted: Fri Sep 11, 2009 12:54 am
by Rescator
Imagine this:

The user (directly or indirectly) wants to use x amount of memory for work buffers. (video encoding, audio processing, image processing, data compression, simulations, rendering, whatever)
The programs could just do a AllocateMemory() and throw a error message to the user if it fails,
but if it doesn't... (which it didn't in my tests) the system grinds to a halt, almost impossible to kill, and if you got a single core system... good luck trying to get task manager to open to kill the damn program.

But if AvailableMemory() was used first then the user could be shown a pre-warning and "Are you sure?" confirmation.
Or the program would only allocate as much as AvailableMemory() returned, or the program might have a table of sizes it chooses from depending on what AvailableMemory() returned.

Why should AvailableMemory() return the available physical memory? Because physical memory is lightning fast compared to anything paged to disk.
I guess a matching AvailableVirtualMemory() would be cool too though.

AvailableMemory() makes it possible to be a even "nicer" system and user friendly programmer, not a worse one! :)

The example function above returns an amount of memory that you can safely allocate without Windows suddenly starting to swap other software out of memory,
as stated in the MSDN documentation it lets you figure out how much memory you can use without impacting other processes running.

It would also be possible to do a: "You only have 3GB memory free, this program/task needs 12G RAM, either close other programs or install more RAM."
Which is way nicer than suddenly grinding the system to a halt because the programmer didn't check how much physical memory was free :)

A cross platform AvailableMemory() returning the free physical memory should be possible AFAIK, as remi_meier showed above, Linux shouldn't be so hard, and thus hopefully not Mac either.

Re: AvailableMemory()

Posted: Fri Sep 11, 2009 1:23 am
by freak
See thats why i said there are valid uses for the function. :) Helping the user make an informed decision about something is a good thing. But the final allocation step should not be affected by whatever AvailableMemory() sais because in the end its the user's decision which should be honored. You made it sound like you want to just grab whatever is available automatically which isn't such a good thing.

Maybe there could be a "System" library in the future which returns such rather informative values like free disk space, memory info and the like.

Re: AvailableMemory()

Posted: Fri Sep 11, 2009 1:43 am
by Rescator
Hmm! Good point, but looking at the manual right now, something like that might fit in the Process library.
Ooh and free disk space yeah, that's another one of those "great to have" functions :)

And for some reason I ended up looking at the Misc lib as well (it's never never made any sense unlike the others).
Wouldn't ElapsedMilliseconds() and OSVersion() and Delay() fit in the Process library too?
And Random() and RandomSeed() kinda fit in the Chiper lib. (CRC32 is there already).
And Blue(),Green(),Red(),RGB() etc. kinda fit under Sprite & Screen which is kinda the allround graphics lib.
And voila, Misc can be removed...Bah I went way offtopic, but anyway... :P