mem1 & mem2 management questions

romain
Posts: 3
Joined: Fri Sep 13, 2013 6:21 pm

mem1 & mem2 management questions

Post by romain » Fri Sep 13, 2013 6:54 pm

Hello everybody.

Maybe in a next message i'l talk and ask some questions about the GX wich is quite interresting.

For now i have just some question about the MEM1 and the MEM2 management. My wish is to understand what to do to have the 2 heap separatly and manage them simply by something like

mem1alloc / mem1align / mem1free
mem2alloc / mem2align / mem2free

Looking for some documentation and sample code on google didn't help me so much. But i've found some talk about it but not so much and I clearly don't understand all (i'm not a native english so i have difficulties sometime to understand).

Please discard/confirm if you know the answer to these questions:

- MEM1 is slightly better than MEM2 in term of speed/transfer rate.
- libogc use MEM1 first, then if not enought memory, use MEM2, but this make the memory fragmented a bit.
- if i want to make my own memory manager, i have to wrap some low level functions like real_malloc or somethings (because of new/malloc ?) and use the lwp_heap functions <- this is out of my knowledge for now (i don't understand well what to override/reprogram)


Please forgive my broken english. If it's unreadable please tell me and i will try to use a better english.

romain
Posts: 3
Joined: Fri Sep 13, 2013 6:21 pm

Re: mem1 & mem2 management questions

Post by romain » Sun Sep 15, 2013 5:45 pm

I did not found an edit button, so I post a new message to answer myquestion above.
romain wrote:- MEM1 is slightly better than MEM2 in term of speed/transfer rate.
wrong. Regarding (link denied.), MEM1 bandwidth is 3.9Gb/s and MEM2 4.0Gb/s.
romain wrote:- libogc use MEM1 first, then if not enought memory, use MEM2, but this make the memory fragmented a bit.
Looking at srbk.c the memory is allocated to MEM1, then if MEM1 become full or doesn't fit the next operation, the memory is allocated to MEM2. If you free some datas in MEM1, but the MEM2 is not totally free the space is free but "lost" until MEM2 is totally unused (or the allocation will continue in MEM2).
romain wrote:- if i want to make my own memory manager, i have to wrap some low level functions like real_malloc or somethings (because of new/malloc ?) and use the lwp_heap functions <- this is out of my knowledge for now (i don't understand well what to override/reprogram)
I have finally taken the mem2 manager from wiiexplorer svn (link denied.) and modified it a bit. No wrap is needed in my case. The svn source code is quite interresting.


I hope i'm not totally wrong :)

*link denied: url i can't write because of the anti spam system. even trought the bbcode url

WinterMute
Site Admin
Posts: 1859
Joined: Tue Aug 09, 2005 3:21 am
Location: UK
Contact:

Re: mem1 & mem2 management questions

Post by WinterMute » Wed Sep 25, 2013 1:11 pm

romain wrote:I did not found an edit button, so I post a new message to answer myquestion above.
romain wrote:- MEM1 is slightly better than MEM2 in term of speed/transfer rate.
wrong. Regarding (link denied.), MEM1 bandwidth is 3.9Gb/s and MEM2 4.0Gb/s.
MEM1 is in fact faster than MEM2 since the latter is shared with the arm7 processor and subject to bus arbitration. In practice there's very little point worrying about the difference.
romain wrote:- libogc use MEM1 first, then if not enought memory, use MEM2, but this make the memory fragmented a bit.
Looking at srbk.c the memory is allocated to MEM1, then if MEM1 become full or doesn't fit the next operation, the memory is allocated to MEM2. If you free some datas in MEM1, but the MEM2 is not totally free the space is free but "lost" until MEM2 is totally unused (or the allocation will continue in MEM2).
It's not quite that simple. sbrk allocates RAM from the heap to the memory manager in newlib. When you release memory using free it becomes available through malloc regardless of where the heap pointer might be. The only memory that gets "lost" is the gap at the end of MEM1 when moving to MEM2.
romain wrote:- if i want to make my own memory manager, i have to wrap some low level functions like real_malloc or somethings (because of new/malloc ?) and use the lwp_heap functions <- this is out of my knowledge for now (i don't understand well what to override/reprogram)
I have finally taken the mem2 manager from wiiexplorer svn (link denied.) and modified it a bit. No wrap is needed in my case. The svn source code is quite interesting.
Assuming you mean "interesting" in the sense used by engineers when they see something constructed in a really peculiar way ;)

As far as I can tell there's no discernible benefit to that application having it's own memory manager and, being honest, it's very rare to find any scenario where a custom memory manager has any significant benefit over the newlib allocator. In most cases the same benefit can be achieved by rethinking how and when memory is allocated for a particular purpose.
*link denied: url i can't write because of the anti spam system. even trought the bbcode url
Sorry. Unfortunately without that we get bombarded with incoherent adverts for pervert pills, porn, kitchens & fake designer goods.
Help keep devkitPro toolchains free, Donate today

Personal Blog

romain
Posts: 3
Joined: Fri Sep 13, 2013 6:21 pm

Re: mem1 & mem2 management questions

Post by romain » Thu Sep 26, 2013 8:23 am

Hello

Thanks for all the explanation. That clarify a bit my understanding of the WII hw, and I realize that I have not the need of a MEM2 manager!

romain wrote:Assuming you mean "interesting" in the sense used by engineers when they see something constructed in a really peculiar way
I like the WII hw. Programming is my hobby, I do it everyday (but I'm not good as I wish). My target is demo/intro, "old school style", not the AAA one, but the funny one. I like reading the gx.h header, agin and again to find an unused function and try to make a unseen effect.

Maybe I'll not release any new demo on WII (often I never release.. because I never finish once the effect is done) but if I write some code on it, I donn't know why, I must use a MEM2 manager :) Plus I like a lot the idea to have the MEM1 for code / critical resource & MEM2 for GX resource (audio buffer, textures, vertex arrays, and not critical resource) even if it's not necessary.

I'm a kind of freak ^^

Sorry for the broken english as usual. I'm late to go to work, so, I have to go ^^
No worries about the link problems and time to publish the messages. Have a good day

tueidj
Posts: 40
Joined: Thu Dec 10, 2009 9:26 am

Re: mem1 & mem2 management questions

Post by tueidj » Sat Oct 12, 2013 5:45 pm

WinterMute wrote:It's not quite that simple. sbrk allocates RAM from the heap to the memory manager in newlib. When you release memory using free it becomes available through malloc regardless of where the heap pointer might be. The only memory that gets "lost" is the gap at the end of MEM1 when moving to MEM2.
Unfortunately that lost memory can be quite substantial (imagine the first malloc in your program is for a 20MB texture cache and MEM1 only has 18MB - all that memory is lost permanently). It would have been much better to configure two separate mspaces for MEM1 and MEM2, allowing separate malloc_mem1/malloc_mem2 functions for the cases where they're needed and make the generic malloc try one and then the other.
Alternatively implementing mmap instead of sbrk would also be a solution since mmap isn't required to allocate blocks consecutively (which would also fix the memory statistic functions including the hole between MEM1 and MEM2 in their calculations).

Eke
Posts: 64
Joined: Sat Mar 01, 2008 11:01 am

Re: mem1 & mem2 management questions

Post by Eke » Fri Jan 03, 2014 10:29 pm

Hi,

I have recently been trying to log MEMx usage in my application to look for memory leaks using SYS_GetArenaXSize functions but I noticed that MEM1 free size will always get locked as soon as you "go" into MEM2, even after freeing allocated objects.

I too thought initially that it was due to how sbrk is implemented is libogc ,i.e if we desallocate objects which were previously allocated in MEM1 while there are still objects allocated in MEM2, MEM1 Low Arena pointer will remain stuck and MEM2 Low Arena pointer might be moved back to an address which is already allocated (or sbrk return an error when the size allocated in MEM2 is not enough)

Note that, in my GUI implementation, objects are freed in the same order as they were allocated so anything that was allocated in MEM1 will be freed before objects that are eventually allocated in MEM2.

But from what you are saying, malloc and free does not care about the heap pointer managed by sbrk ? I am not sure to understand : how does the memory manager in newlib knows what memory address is free to use ? And how could I check the remaining free memory size then ?

Eke
Posts: 64
Joined: Sat Mar 01, 2008 11:01 am

Re: mem1 & mem2 management questions

Post by Eke » Fri Jan 03, 2014 11:50 pm

ok, i have been reading more on how malloc and free generally work regarding heap allocation (not sure about newlib's exact implementation though) and now understand that they generally use linked list and that sbrk will only be called when more heap memory is needed or when released memory is at the end of the heap.

i am still wondering why the MEM Low Arena pointers get stuck however?

I have noticed that sbrk would return an error if the size passed as parameter is negative and larger than the heap size in MEM2 (i.e when trying to go below MEM2 startaddress). But isn't it possible for the "free" function to call sbrk with a negative value larger than the size of the disallocated object (at the end of the heap), for example when "free" was called for adjacent blocks (within the heap) ? What if those blocks were allocated in MEM1 ? Shouldn't sbrk implementation in libogc treat MEM1 and MEM2 as two contiguous memory areas and release all heap memory in MEM2 then remaining memory in MEM1 in this case (thus updating both Low Arena pointers) ? This would actually explain what i am experimenting, i.e Low Arena pointers getting stuck.

tueidj
Posts: 40
Joined: Thu Dec 10, 2009 9:26 am

Re: mem1 & mem2 management questions

Post by tueidj » Sat Jan 11, 2014 2:38 am

You're right. DevkitPPC uses dlmalloc for its malloc implementation, from memory it has a "trim" function that releases memory back to sbrk when a certain amount is unallocated (in this case it must be at the "top"). Unfortunately it's configured to treat all sbrk'd memory as contiguous so it does try to jump back directly in mem1 from mem2... meaning there is practically no way to reclaim the wasted space in mem1. So much for "it's very rare to find any scenario where a custom memory manager has any significant benefit over the newlib allocator."

BTW: the difference in speed between mem1 and mem2 is not due to being "shared with the arm7 processor and subject to bus arbitration." Mem1 is also shared by both CPUs and other hardware, the difference is it's simply a faster type of RAM (1T SRAM vs. GDDR3). Due to the nature of GDDR3, if your app is performing a lot of CPU<->MEM2 work (perhaps while using mem1 mainly for static textures) you can get a good performance improvement by calling L2Enhance() at the start of your app to activate 64-byte fetches for the L2 cache.

Eke
Posts: 64
Joined: Sat Mar 01, 2008 11:01 am

Re: mem1 & mem2 management questions

Post by Eke » Wed Jan 15, 2014 11:04 am

tueidj wrote:You're right. DevkitPPC uses dlmalloc for its malloc implementation, from memory it has a "trim" function that releases memory back to sbrk when a certain amount is unallocated (in this case it must be at the "top"). Unfortunately it's configured to treat all sbrk'd memory as contiguous so it does try to jump back directly in mem1 from mem2... meaning there is practically no way to reclaim the wasted space in mem1. So much for "it's very rare to find any scenario where a custom memory manager has any significant benefit over the newlib allocator."
Thanks for confirming.

I have been trying to use my own sbrk implementation by replacing this in original __libogc_sbrk_r:

Code: Select all

} else if ((heap_end+incr) < mem2_start) {
			// trying to sbrk() back below the MEM2 start barrier
			ptr->_errno = EINVAL;
			prev_heap = (char *)-1;
by:

Code: Select all

} else if ((heap_end+incr) < mem2_start) {
			// trying to sbrk() back below the MEM2 start barrier
			// free remaining memory in MEM2
			SYS_SetArena2Lo((void*)(mem2_start));
			incr += (heap_end - mem2_start);

			// we are back in MEM1
			prev_heap = SYS_GetArena1Lo();
			SYS_SetArenaLo((void*)(prev_heap+incr));
then attempt to register it as default syscall with:

Code: Select all

__syscalls.sbrk_r = __my_sbrk_r;
which is copied from what is done in SYS_Init() by libogc

...but it does not seem to work (MEM1 Low Arena pointer still locked after releasing memory from MEM2)

What am I doing wrong ?

tueidj
Posts: 40
Joined: Thu Dec 10, 2009 9:26 am

Re: mem1 & mem2 management questions

Post by tueidj » Sat Jan 18, 2014 1:46 pm

Do you also reset mem2_start to NULL?

Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot] and 50 guests