Hello Nick!
> I've installed a number of assemblies into the GAC (using gacutil)
> and then used nGen on them (nGen install) but can see no change in
[quoted text clipped - 3 lines]
> machine as the same user and using Process Explorer to display the
> Working Set and Virtual Size of the applications.
When a dll is loaded into the (virtual) Address-Space of a process, and than
into another process, from the process the virtual memory starting at the
Base-Address (HINSTANCE) looks like any other (private) Memory. When the
process would write into this (shared) Memory (maybe because of relocation),
the Memory Manager by itself would create copies of the modified pages that
can no longer be shared (copy on write).
AFAIK the "WorkingSet" and "VM Size" Counters of the Task-Manager are not
able to reflect this behaviour, because they do not care if memory is shared
or not. Im not 100% sure on this, but I think that I have observered this
behavior some time ago.
So the WorkingSet or Virtual Size will increase for each process, even if
the underlying pages are shared by the Memory Manager.
But remember that each Dll should have its own Base-Address set, otherwise
the nessersary Relocations would make many pages to be written by the
Loader. This would result in not-sharable pages! So check your Base-Address
settings (Project Properties/Build Tab).
> The assemblies I'm testing with are not large. Combined they are
> about 600K in size (size of the DLL files).
Because Processes execution managed code have a higher memory footprint
"by-design", most likely the difference will not be very big.
> Is there some overhead in
> using nGen which increases memory usage by about the same amount as
> I'm saving in this case or something?
Maybe. Maschine-Code is usually greater in size than IL. Of cause the JIT
Compiler (for example system.dll = 3.018.752, system.ni=8.093.696).
When a process loads the managed system.dll, the _virtual_ memory will
increase for the size of the system.dll (there is actualy no phyisical
memory needed for this, because the memory-region is backed by the image
itself; only memory the pages that are accesses will be loaded from the
image into physical memory). When you call a method of the system.dll (the
JIT Compiler works on method-basis), it will compile the IL "in-place",
which forces the OS to copy the affected Page(s) into the Paging-File (it
can no longer be shared).
When a process loads the native image system.il, the _virtuel_ memory will
also increase for the size of the image. But when no relocation (or
rebinding) is needed, this pages can be shared accross processes.
In both cases the _virtual_ memory will increase. The _virtual_ memory
needed to load the native image will be bigger that the virtual memory that
is required to load the managed assembly. But the physical memory needed
(eigher in "real" RAM, or paging file), will be higher when no native image
is used.
So: When you really want to analyse this in detail, Task-Manager may be not
the right tool for this job. You should least use a tool that is able to
provide better details about memory-allocation.
GP
Nick John - 02 Jul 2007 00:35 GMT
Gunter,
thanks for your reply.
> So the WorkingSet or Virtual Size will increase for each process, even if
> the underlying pages are shared by the Memory Manager.
Thanks for pointing out the obvious about virtual memory, I'm not sure how I
managed to overlook that.
I switched to looking at the WS Private value (using Process Explorer) and
you are right I did see an improvement as long as I rebased them (my
DLLs/assemblies) before putting them in the GAC and NGen'ing them.
Thanks.
Process Explorer -
http://www.microsoft.com/technet/sysinternals/utilities/ProcessExplorer.mspx
Cheers,
Nick
> Hello Nick!
>
[quoted text clipped - 63 lines]
>
> GP