问题
When I use GetManifestResourceStream
to retrieve an embedded resource from a .NET assembly, what kind of I/O is involved?
I see two possibilities:
The entire assembly was already put into memory when .NET loaded it, so
GetManifestResourceStream
is just accessing memory.Only the code parts of the assembly were put into memory when the assembly was loaded by .NET, so
GetManifestResourceStream
needs to go back to the.dll
file to extract the embedded resource.
I'm pretty sure the first is the case, especially since assemblies can be loaded dynamically from raw data with Assembly.Load(Byte[])
. But then I wonder what happens if a very large file (say several gigabytes) was embedded - the second option might be more efficient. Does size matter?
Just challenging some long-held assumptions, and not able to find much in the way of reference on this.
回答1:
"Memory" is not a precise enough term on a demand-paged virtual memory operating system like Windows, Linux, MacOS. The CLR maps the assembly into the address space of the process using a memory-mapped file (MMF). Just numbers to the processor, one each for every 4096 bytes. Nothing is read from the file just yet.
That is delayed until the program tries to read from an address inside the address space. First access generates a page fault, the kernel allocates RAM for the page and fills it with the file content. After which the program resumes as though nothing happened. Strongly empowers the "you don't pay for what you don't use" advantage of virtual memory.
There is no "extraction", you are reading the resource data directly from memory, most efficient way it could have been implemented. An embedded resource does not otherwise behave any differently from other data in the file, like the metadata and the MSIL. You likewise don't pay for any code in the assembly that you never call.
Do keep in mind that an embedded resource occupies the same OS resource as the GC heap, it too requires address space. Only real difference is that GC heap address space is backed by the OS paging file and can never be shared with other processes, the assembly data is backed by the assembly file and can be shared. Large resources notably shrink the amount of memory you can allocate in a .NET program, even if you never use them. That matters only in a 32-bit process, a 64-bit process has many terabytes of address space.
Another restriction is that an MMF view can never be larger than 2 GB, even in a 64-bit process, that sets a hard upper limit on the maximum size of a resource. That usually keels over very early, failing the build with CS1566, "Specified argument was out of the range of valid values". Not a great diagnostic btw.
来源:https://stackoverflow.com/questions/43548270/are-embedded-resources-in-a-net-assembly-loaded-from-disk-or-from-memory-at-run