none
Native Images and Shared Memory

    Question

  • Hi all,

        I read in a article that Native images are loaded in a shared memory location which can be shared by other assemblies running in other process. I dont understand how this works.

    I was thinking that all the referenced assemblies (including the framework assemblies) by a .NET application are loaded as In-Process Dll's in the applications App Domain. Is it wrong? Is it possible for a Dll to be loaded in a shared location so that the applications running in different processes can share it? Please share some resources where i can learn about Dll Loading and Memory management.

    Please help...

    Thanks,

    Suresh.

     

     

     

     

     

    Thursday, April 27, 2006 3:15 PM

Answers

  • Suresh, the reason this happens is because a natively compiled image file( your NGEN image) is a typical Win32 PE file. This means that it follows the same rules as a traditional dll file. It can be shared across processes. This is the reason that you see the line: "native images are loaded by the CLR just like any other DLL. This means that the actual memory pages containing the machine code can be shared by the OS between multiple processes. The effect of this is that any app using one of these shared native images is able to use these code pages already loaded into memory and thus reduce the number of new pages committed for that process. "

    This sharing true of any of the NT onward dlls (yes provided there is no rebasing etc etc)

    However for .NET dlls, the case is different. These are MSIL code that is dynamically converted to machine language and this code is private and cannot be shared across processes.

    This is the reason the author talks of ngen reducing the memory footprint of a .net application that uses a dll already loaded by some other app.

     

    Thursday, April 27, 2006 6:39 PM
  • Right -- and I think the confusion here is that you're sharing the code pages, not any writable data.  So if you've got a static field in one assembly, and you write to it, it won't show up in that assembly loaded in a different process (or a different AppDomain for that matter).

    -Shawn

    Thursday, April 27, 2006 8:38 PM
    Moderator
  • This comes into the realm of virtual memory vs physical memory.  You are correct that each process sees a DLL in a seperate address space.  However, under the covers (assuming that the DLL does not need to be rebased), the operating system has only loaded it once.  For instance, if Foo.dll has a load address of 0x20000000.  When it is actually loaded, it might end up at physical address 0x10000000.

    Each process has a table associated with it which maps virtual memory addresses to physical addresses.  In this case, if both process A and B have Foo.dll loaded, they would both have entries in their table mapping virtual address 0x20000000 to physical address 0x10000000.  This way, although they both have Foo.dll in their own seperate address spaces, they're actually sharing the same physical memory -- only one copy of Foo.dll is loaded.

    In the managed world, this doesn't work as well since Foo needs to be JITed.  When we JIT Foo's methods, we allocate pages of memory from the operating system which are not shared between processes to write the actual native code into.  If Foo was a managed assembly, A and B could share the metadata and IL from the DLL, but they would both have seperate copies of the JITed code, meaning two times the physical memory is taken up with what is probably basically the same machine code.

    Now, if you NGEN Foo, we're back into the first situation, since the operating system is loading up sharable code pages once again.

    Does that make sense?

    -Shawn

    Friday, April 28, 2006 3:34 PM
    Moderator

All replies

  • Take a look at this recent article from MSDN Magazine on NGen and the performance gains it offers for some better insights into native images.
    Thursday, April 27, 2006 4:04 PM
    Moderator
  • From this article only i read that native images are loaded in shared pages.These are the words from the article...

    "native images are loaded by the CLR just like any other DLL. This means that the actual memory pages containing the machine code can be shared by the OS between multiple processes. The effect of this is that any app using one of these shared native images is able to use these code pages already loaded into memory and thus reduce the number of new pages committed for that process. "

    Thanks,

    Suresh.

     

    Thursday, April 27, 2006 5:20 PM
  • Suresh, the reason this happens is because a natively compiled image file( your NGEN image) is a typical Win32 PE file. This means that it follows the same rules as a traditional dll file. It can be shared across processes. This is the reason that you see the line: "native images are loaded by the CLR just like any other DLL. This means that the actual memory pages containing the machine code can be shared by the OS between multiple processes. The effect of this is that any app using one of these shared native images is able to use these code pages already loaded into memory and thus reduce the number of new pages committed for that process. "

    This sharing true of any of the NT onward dlls (yes provided there is no rebasing etc etc)

    However for .NET dlls, the case is different. These are MSIL code that is dynamically converted to machine language and this code is private and cannot be shared across processes.

    This is the reason the author talks of ngen reducing the memory footprint of a .net application that uses a dll already loaded by some other app.

     

    Thursday, April 27, 2006 6:39 PM
  • Right -- and I think the confusion here is that you're sharing the code pages, not any writable data.  So if you've got a static field in one assembly, and you write to it, it won't show up in that assembly loaded in a different process (or a different AppDomain for that matter).

    -Shawn

    Thursday, April 27, 2006 8:38 PM
    Moderator
  • Thanks Saravana and Shawn.

    I understand that native images are loaded statically into memory and MSIL code is converted dynamically to native code and put into memory on the fly and I see this as the only difference. Anyhow in both the cases the code is going to be in memory and it is going to fall within a process.

    How does other applications could find the address of a statically loaded native image and not able to find the dynamically generated MSIL-native image ? Since memory addresses are process-relative how it possible for an application to locate and execute a native code loaded in another process?

    If I'm biased completely please let me know some URL's about DLL's,Process and Memory etc., where i can learn about this ...

    Thanks for your help,

    Suresh.

     

    Friday, April 28, 2006 12:10 PM
  • This comes into the realm of virtual memory vs physical memory.  You are correct that each process sees a DLL in a seperate address space.  However, under the covers (assuming that the DLL does not need to be rebased), the operating system has only loaded it once.  For instance, if Foo.dll has a load address of 0x20000000.  When it is actually loaded, it might end up at physical address 0x10000000.

    Each process has a table associated with it which maps virtual memory addresses to physical addresses.  In this case, if both process A and B have Foo.dll loaded, they would both have entries in their table mapping virtual address 0x20000000 to physical address 0x10000000.  This way, although they both have Foo.dll in their own seperate address spaces, they're actually sharing the same physical memory -- only one copy of Foo.dll is loaded.

    In the managed world, this doesn't work as well since Foo needs to be JITed.  When we JIT Foo's methods, we allocate pages of memory from the operating system which are not shared between processes to write the actual native code into.  If Foo was a managed assembly, A and B could share the metadata and IL from the DLL, but they would both have seperate copies of the JITed code, meaning two times the physical memory is taken up with what is probably basically the same machine code.

    Now, if you NGEN Foo, we're back into the first situation, since the operating system is loading up sharable code pages once again.

    Does that make sense?

    -Shawn

    Friday, April 28, 2006 3:34 PM
    Moderator
  • And to add to Shawn's excellent post, my impression is that the reason re-based dlls(the dlls that do not get to load at their preferred base addresses) are not shared are because the code pages are written to as the OS needs to now switch around the various addresses in the code page in terms of the new base address.

    Since JIT code-->machine code is translated at run time, the code pages would actually be written to and come under the same restriction as not sharing dlls that have been re-based.

    A huge disclaimer : "This is just my inference".

     

    Friday, April 28, 2006 5:22 PM
  • Thanks for your wonderful post Shawn.And many thanks to Saravana.

    Its great to know that Dll's are shared by different processes and metadata and IL are shared among different managed applications.

    I think i should read more on windows Virtual Memory architecture and internals to get more on this.

    Thanks again,

    Suresh.

     

     

     

    Tuesday, May 02, 2006 11:41 AM
  • Shawn,

    You had said that a DLL has been loaded once irrespective of the number of processes refering it. Now the CLR is implemented as a dll and it is also loaded once as the normal dll's?

    If so how can the CLR manage multile .NET applications?

    Thanks,

    Suresh.

     

     

    Wednesday, May 17, 2006 7:57 PM