Memory management in HydraVM

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Memory management in HydraVM

Igor Stasenko
 
Hello list,

until now, i never examined how OS-specific routines sqAllocateMemory,
sqGrowMemoryBy .. working,
and in Hydra everything worked just well, without problems so far for
two images..

Eventually, i tried to find a way how to deallocate the heap for an
interpreter which is no longer running (if image quits, or fatal error
in interpreter, or even on C exception) and found that i can't free
memory for specific interpreter instance, because sqReleaseMemory()
having no arguments. :)

And by getting deeper, i found that memory management must be
completely redesigned, because Hydra will unable to work with
Interpreters > 2..4.
For all platforms, if it supports virtual memory management, an
sqAllocateMemory() function reserves a huge chunk of address space for
a potentially big object memory heap, while reserving initially small
amount of physical memory (enough to fit image in it + some extra
space).
This approach works well for single image, but not for multiple :(

For instance, in win32 port, there is a constant which defines a total
amount of address space reserved for a single heap:
#define MAX_VIRTUAL_MEMORY 512*1024*1024
which means that first image heap takes 512Mb address space,
second one - another 512Mb
and if i remember correctly, in win32 process not allowed to reserve
more than 2Gb address space, which means that when we try to run 3rd
or 4th image, we having high probability that OS will reject to
allocate any more address space. In any way, even if limit is 4Gb (max
32 bit address space), we still have a maximum number of about 8
interpreters.
Not mentioning the address space used for C heap, kernel, many .dlls
etc etc. and inevitable address space segregation.

Also, i found that sqGrowMemoryBy(), sqShrinkMemoryBy(),
sqMemoryExtraBytesLeft() using static variables, and there is high
risk that if VM will use them in both direction (grow/shrink), it
could lead to crash.
This, of course can be fixed easily, by holding a memory state for
each instance of interpreter separately, but this is not a cure for a
problem with address space.

It looks like, that Hydra will require a sophisticated virtual memory
management (since Hydra runs only on systems which supporting threads,
i think we can assume that OS gives us the way to manage virtual
memory as well).

I'd like to hear your advice, what strategy works best for it? Also,
if you know about any tech-docs describing such strategies or
libraries which enable to manage virtual memory efficiently - let me
know.
Shall the memory manager give small address space regions for each
interpreter instance, and then if some image tends to grow bigger -
relocate it into a different memory space with higher number of pages
reserved for it?
Is it safe to relocate an object memory when it is in working state
(not running, because we obviously will request a relocation of object
memory when current heap size will become too small to fit object
memory in it)?
The C code (in primitives/plugins) does not holding direct object
pointers - thanks that we having a moving GC :) So i think it is
doable..

--
Best regards,
Igor Stasenko AKA sig.
Reply | Threaded
Open this post in threaded view
|

Re: Memory management in HydraVM

Andreas.Raab
 
Hi Igor -

The main reason for reserving a large chunk of address space is to avoid
the C allocator to interfere with our need of continuous address space.
This doesn't that the address space has to be used by a single image.

Since all of the object memory are relocatable, it is easy to see that
if necessary an object memory could be relocated to a different
location. I always thought that a Hydra memory managing scheme should
work like here:

As a base rule, recursively divide the address space for any new object
memory. Meaning that with 512MB address space the first image starts at
0, the second at 256k the third 128, the fourth at 384 etc. Obviously,
if that memory is already occupied you move on to the next smaller chunk
(i.e., if the first image needs more than 256 MB you try 384 next, if
that's taken you try 448 and so on). Assuming that there is enough base
memory to load the image (i.e., you aren't trying to load an image into
a fragmented space that doesn't have sufficient memory at the given
location) you will be able to load and start that image.

If an image happens to need more space than currently reserved, move the
adjacent image away. The idea is that you only need to lock and move one
image (instead of all interpreters) if this is the only one you'll be
relocating. If there is no space to move the adjacent image, then some
heuristics needs to be found to figure out what to do. In the early
stages I would just fail the allocation and give up.

I think the above should work well for most cases. It will deal with one
of the most important cases: One big master image and many small worker
images. As the big image grows it will move the smaller images out of
the way.

Cheers,
   - Andreas

Igor Stasenko wrote:

>  
> Hello list,
>
> until now, i never examined how OS-specific routines sqAllocateMemory,
> sqGrowMemoryBy .. working,
> and in Hydra everything worked just well, without problems so far for
> two images..
>
> Eventually, i tried to find a way how to deallocate the heap for an
> interpreter which is no longer running (if image quits, or fatal error
> in interpreter, or even on C exception) and found that i can't free
> memory for specific interpreter instance, because sqReleaseMemory()
> having no arguments. :)
>
> And by getting deeper, i found that memory management must be
> completely redesigned, because Hydra will unable to work with
> Interpreters > 2..4.
> For all platforms, if it supports virtual memory management, an
> sqAllocateMemory() function reserves a huge chunk of address space for
> a potentially big object memory heap, while reserving initially small
> amount of physical memory (enough to fit image in it + some extra
> space).
> This approach works well for single image, but not for multiple :(
>
> For instance, in win32 port, there is a constant which defines a total
> amount of address space reserved for a single heap:
> #define MAX_VIRTUAL_MEMORY 512*1024*1024
> which means that first image heap takes 512Mb address space,
> second one - another 512Mb
> and if i remember correctly, in win32 process not allowed to reserve
> more than 2Gb address space, which means that when we try to run 3rd
> or 4th image, we having high probability that OS will reject to
> allocate any more address space. In any way, even if limit is 4Gb (max
> 32 bit address space), we still have a maximum number of about 8
> interpreters.
> Not mentioning the address space used for C heap, kernel, many .dlls
> etc etc. and inevitable address space segregation.
>
> Also, i found that sqGrowMemoryBy(), sqShrinkMemoryBy(),
> sqMemoryExtraBytesLeft() using static variables, and there is high
> risk that if VM will use them in both direction (grow/shrink), it
> could lead to crash.
> This, of course can be fixed easily, by holding a memory state for
> each instance of interpreter separately, but this is not a cure for a
> problem with address space.
>
> It looks like, that Hydra will require a sophisticated virtual memory
> management (since Hydra runs only on systems which supporting threads,
> i think we can assume that OS gives us the way to manage virtual
> memory as well).
>
> I'd like to hear your advice, what strategy works best for it? Also,
> if you know about any tech-docs describing such strategies or
> libraries which enable to manage virtual memory efficiently - let me
> know.
> Shall the memory manager give small address space regions for each
> interpreter instance, and then if some image tends to grow bigger -
> relocate it into a different memory space with higher number of pages
> reserved for it?
> Is it safe to relocate an object memory when it is in working state
> (not running, because we obviously will request a relocation of object
> memory when current heap size will become too small to fit object
> memory in it)?
> The C code (in primitives/plugins) does not holding direct object
> pointers - thanks that we having a moving GC :) So i think it is
> doable..
>
Reply | Threaded
Open this post in threaded view
|

Re: Memory management in HydraVM

Igor Stasenko
 
2009/2/18 Andreas Raab <[hidden email]>:

>
> Hi Igor -
>
> The main reason for reserving a large chunk of address space is to avoid the
> C allocator to interfere with our need of continuous address space. This
> doesn't that the address space has to be used by a single image.
>
> Since all of the object memory are relocatable, it is easy to see that if
> necessary an object memory could be relocated to a different location. I
> always thought that a Hydra memory managing scheme should work like here:
>
> As a base rule, recursively divide the address space for any new object
> memory. Meaning that with 512MB address space the first image starts at 0,
> the second at 256k the third 128, the fourth at 384 etc. Obviously, if that
> memory is already occupied you move on to the next smaller chunk (i.e., if
> the first image needs more than 256 MB you try 384 next, if that's taken you
> try 448 and so on). Assuming that there is enough base memory to load the
> image (i.e., you aren't trying to load an image into a fragmented space that
> doesn't have sufficient memory at the given location) you will be able to
> load and start that image.
>
> If an image happens to need more space than currently reserved, move the
> adjacent image away. The idea is that you only need to lock and move one
> image (instead of all interpreters) if this is the only one you'll be
> relocating. If there is no space to move the adjacent image, then some
> heuristics needs to be found to figure out what to do. In the early stages I
> would just fail the allocation and give up.
>
> I think the above should work well for most cases. It will deal with one of
> the most important cases: One big master image and many small worker images.
> As the big image grows it will move the smaller images out of the way.
>

aha, you mean that bigger image 'pushing' away smaller ones. But then
if we having, lets say 10 images, where each is 2x bigger than next
one, then if first one demands more address space, we now need to
relocate all 9 images?

Maybe it is better to use different strategy:
allocate the least space for image, then if outage happens - reserve
new address space which size is *2 of previous one and place image
there, and release previously reserved address space back to OS.
A total amount of physical memory required for image relocation could
be minimized, if we copy image in chunks of N pages , and immediately
release N pages in old address space.
The drawback of such approach that it could lead to fragmentation of
address space. But we could limit the minimum amount of address space
for a single interpreter, lets say - 4Mb, so potentially we can afford
about 1024 heaps of size < 4Mb. Which i think is more than enough for
32bit based systems.
In any case, both variants require use of object memory relocation at
some point, its good that VM having this from a very starting, since
loading image into memory sometimes requires relocation if it loaded
into different base address.

As for 64bit systems.. hehe.. i don't think we have to bother with
address space in nearest 10 years.


> Cheers,
>  - Andreas
>

--
Best regards,
Igor Stasenko AKA sig.