4

Are there any performance penalties running .NET 4.0 app from shared network folder? I found what app starts slower but didn't noticed any slow down while using it, but not sure about it.

Tomas
  • 17,551
  • 43
  • 152
  • 257
  • May be it is because network access is usually slower then local? – Andrey Nov 29 '11 at 12:08
  • Another reason is that on first launch Windows and .net perform some optimizations and cache results. They might not apply them for app loaded from network. – Andrey Nov 29 '11 at 12:09
  • For what reason would you do that ? IMO this is a security leak. Everyone having access to that folder may substitute your executable with malicious software of himself – Boas Enkler Nov 29 '11 at 12:11
  • 1
    @Boas Enkler one possible reason is to have updates for free, user always get latest version. My guess. – Andrey Nov 29 '11 at 12:12
  • 1
    @BoasEnkler Another reason is that it's a security feature. Everyone having access to an executable on their machine means they could substitute my executable with malicious software – Ian Boyd Nov 29 '11 at 12:24
  • 1
    @Andrey: In that case, ClickOnce would be the better solution. – Thorsten Dittmar Nov 29 '11 at 12:35
  • @ThorstenDittmar: that is not always an option, especially if it is a console application. – user7116 Nov 29 '11 at 14:23
  • I agree to Andrey, concerning updates it is much better when using clickonce. Wheres the problem with console apps ? There are even ideas / solutions &workaround for updating comservers with click once. @Security : isn't right. no one stops you injecting code via manipulating .net CLR assemblies. But having the executable in the lan means, starting a assembly without knowing who has changed it and what has he done... – Boas Enkler Nov 30 '11 at 13:20
  • In my case it is much better to load app from shared network instead of updating app to every PC. We have 10 cloud servers and updating app to every PC would be nightmare. Now we just use the same small app in every cloud server which checks for new main app version on networks share and run new version if needed. – Tomas Dec 01 '11 at 08:30

2 Answers2

4

When running an executable over the network, Windows does not bring the entire application over the network at application startup. This is done to speed startup times (and there's no point is downloading that 700MB embedded AVI resource if you never actually use it).

This means that periodically, as new pages from the executable image are required, Windows will go back to the network to retrieve them.

The method in which this is accomplished is that if your application happens to hit a page of memory that is not present, a standard page fault will trigger, telling Windows it needs to fill that page. If the network happens to be down at that moment, Windows will be unable to satisfy the page-fault. There's no way to recover from this, so Windows throws an EXCEPTION_IN_PAGE_ERROR (0xC0000005).

There are three ways to handle this:

  • do nothing and let the application die. Tell the customer to fix their network
  • trap the error, explaining that the application must be terminated now, and telling the user that their network is to blame
  • set the IMAGE_FILE_NET_RUN_FROM_SWAP PE image option. This will instruct Windows to copy the entire executable over the network at application load time. This will increase network traffic and user wait times (at application launch time), but avoid the error
Ian Boyd
  • 246,734
  • 253
  • 869
  • 1,219
  • i'd go with a combo of #1 & #2 : exit gracefully, tell customer to fix their network ^^ – Alex Nov 29 '11 at 12:56
  • #3 is also excellent of course, but would be a nightmare if going through the usual slow-as-a-crawl VPN... :) – Alex Nov 30 '11 at 08:33
2

Yes, this is heavily optimized in Windows. Loading a .NET assembly does not in fact involve reading the assembly. Much like native code, the CLR creates a memory-mapped file for the assembly file. A chunk of virtual memory that's as large as the file and whose pages are marked as "not yet loaded".

The JIT compiler then goes about its business reading IL and generating machine code for it. Inevitably, it will try to read a memory page that is still in the "not yet loaded" state and that will generate a low-level processor page fault. Windows traps that fault and will then actually read the file content and load it into RAM. The jitter continues as though nothing happened.

Reading that page will be slower when the assembly is located on a network share. But since the jitter only compiles IL when actually needed to execute the program, that slow-down is hard to notice, it only adds a handful of milliseconds to each page fault. It will be most noticeable when your program starts up, the only real time that a lot of IL needs to be compiled before the program can do something like showing its main window.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536