Volt egy munkám, amiben egy bonyolult formokat dinamikusan, xml leírásból megjelenítő üzleti alkalmazást kellett optimalizálni.
A probléma az volt vele, hogy a formokat nagyon lassan generálta le, 10-20 mp is kellett egy bonyolultabbhoz. Ezeken már több száz vezérlő volt, de akkor is, nem kell annak ilyen lassúnak lenni.
A szűk keresztmetszetek felderítéséhez a korábbi bejegyzésben említett VSTS profilert használtam.
A következő általánosítható tapasztalatokról számolhatok be. Mivel nagyon sok érdekes eredménye volt a kutatásnak, több részben osztom ezeket meg veletek.
Ha nem használjuk ki a ResourceManager lokalizálási lehetőségeit, csak arra használunk erőforrásokat, hogy a kódból kiemeljünk egyes, később esetleg módosítandó stringeket, akkor sokat sprórolhatunk az erőforrások betöltésekor.
Példaképpen nézzünk egy sima WinForms alkalmazást, amihez hozzáadtunk egy erőforrást (.resx). A resxhez generálnak nekünk egy típusos elérő osztályt is, így a következő sorral egyszerűen elérhetjük az erőforrásként tárolt Teszt nevű kulcsot:
MessageBox.Show(Resource1.Teszt);
Mit is csinál a generált kód?
internal static string Teszt
{
get
{
return ResourceManager.GetString(“Teszt”, resourceCulture);
}
}
Ahol a ResourceManager egy System.Resources.ResourceManager példány.
Az ő feladata, hogy megpróbáljon lokalizált erőforrásokat keresni, ha vannak, azokat betölteni. Hol laknak ezek? Processz Explorerrel megnézve kiderül:
CultureTest.exe FAST IO DISALLOWED C:\szemet\CultureTest\bin\Debug\en-US\CultureTest.resources.dll CultureTest.exe PATH NOT FOUND C:\szemet\CultureTest\bin\Debug\en-US\CultureTest.resources.dll CultureTest.exe FAST IO DISALLOWED C:\szemet\CultureTest\bin\Debug\en-US\CultureTest.resources\CultureTest.resources.dll CultureTest.exe PATH NOT FOUND C:\szemet\CultureTest\bin\Debug\en-US\CultureTest.resources\CultureTest.resources.dll CultureTest.exe FAST IO DISALLOWED C:\szemet\CultureTest\bin\Debug\en-US\CultureTest.resources.exe CultureTest.exe PATH NOT FOUND C:\szemet\CultureTest\bin\Debug\en-US\CultureTest.resources.exe CultureTest.exe FAST IO DISALLOWED C:\szemet\CultureTest\bin\Debug\en-US\CultureTest.resources\CultureTest.resources.exe CultureTest.exe PATH NOT FOUND C:\szemet\CultureTest\bin\Debug\en-US\CultureTest.resources\CultureTest.resources.exe CultureTest.exe FAST IO DISALLOWED C:\Windows\Microsoft.NET\Framework\v2.0.50727\en-US\mscorrc.dll CultureTest.exe PATH NOT FOUND C:\Windows\Microsoft.NET\Framework\v2.0.50727\en-US\mscorrc.dll CultureTest.exe FAST IO DISALLOWED C:\Windows\Microsoft.NET\Framework\v2.0.50727\en-US\mscorrc.dll CultureTest.exe PATH NOT FOUND C:\Windows\Microsoft.NET\Framework\v2.0.50727\en-US\mscorrc.dll CultureTest.exe FAST IO DISALLOWED C:\Windows\Microsoft.NET\Framework\v2.0.50727\en-US\mscorrc.dll.DLL CultureTest.exe PATH NOT FOUND C:\Windows\Microsoft.NET\Framework\v2.0.50727\en-US\mscorrc.dll.DLL CultureTest.exe FAST IO DISALLOWED C:\Windows\Microsoft.NET\Framework\v2.0.50727\en\mscorrc.dll CultureTest.exe NAME NOT FOUND C:\Windows\Microsoft.NET\Framework\v2.0.50727\en\mscorrc.dll CultureTest.exe FAST IO DISALLOWED C:\Windows\Microsoft.NET\Framework\v2.0.50727\en\mscorrc.dll CultureTest.exe NAME NOT FOUND C:\Windows\Microsoft.NET\Framework\v2.0.50727\en\mscorrc.dll CultureTest.exe FAST IO DISALLOWED C:\Windows\Microsoft.NET\Framework\v2.0.50727\en\mscorrc.dll.DLL CultureTest.exe NAME NOT FOUND C:\Windows\Microsoft.NET\Framework\v2.0.50727\en\mscorrc.dll.DLL CultureTest.exe FAST IO DISALLOWED C:\Windows\Microsoft.NET\Framework\v2.0.50727\mscorrc.dll CultureTest.exe SUCCESS C:\Windows\Microsoft.NET\Framework\v2.0.50727\mscorrc.dll
Szép lista, mi? És nem is mindig ilyen rövid a lista, sok assembly és több alkönyvtár is be szokott jönni a képbe. Szóval ő keresgélt keményen, mire a végén rájött (ez nem látszik az előbbiből), hogy a fő assemblyben, a CultureTest.exe-ben van, amiért küzd. Ez a fallback location.
Mellesleg a rémségek kicsiny tárháza nem merül ki ennyiben. Nézzük meg, mi történt a registryben:
2 CultureTest.exe RegOpenKey NAME NOT FOUND Desired Access: Read HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\Managed\S-1-5-21-1912844993-3366795750-3477756003-1000\Installer\Assemblies\C:|szemet|CultureTest|bin|Debug|CultureTest.exe
3 CultureTest.exe RegOpenKey NAME NOT FOUND Desired Access: Read HKCU\Software\Microsoft\Installer\Assemblies\C:|szemet|CultureTest|bin|Debug|CultureTest.exe
4 CultureTest.exe RegOpenKey NAME NOT FOUND Desired Access: Read HKCR\Installer\Assemblies\C:|szemet|CultureTest|bin|Debug|CultureTest.exe
5 CultureTest.exe RegOpenKey NAME NOT FOUND Desired Access: Read HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\Managed\S-1-5-21-1912844993-3366795750-3477756003-1000\Installer\Assemblies\Global
6 CultureTest.exe RegOpenKey SUCCESS Desired Access: Read HKCU\Software\Microsoft\Installer\Assemblies\Global
7 CultureTest.exe RegEnumValue SUCCESS Index: 0, Name: System.Data.Entity,version=”3.5.0.0″,publicKeyToken=”b77a5c561934e089″,processorArchitecture=”MSIL”,fileVersion=”3.5.21015.1″,culture=”neutral”, Type: REG_MULTI_SZ, Length: 126, Data: C3OujdJLp9NfYy,t(d,[DP_EntityFramework_F>XQM@Z1Phc9}TW]UlV1Ni HKCU\Software\Microsoft\Installer\Assemblies\Global
8 CultureTest.exe RegEnumValue SUCCESS Index: 1, Name: System.Data.Entity.Design,version=”3.5.0.0″,publicKeyToken=”b77a5c561934e089″,processorArchitecture=”MSIL”,fileVersion=”3.5.21015.1″,culture=”neutral”, Type: REG_MULTI_SZ, Length: 126, Data: C3OujdJLp9NfYy,t(d,[DP_EntityFramework_F>rl{^k~VBe8%[-9p_{$g7 HKCU\Software\Microsoft\Installer\Assemblies\Global
9 CultureTest.exe RegEnumValue SUCCESS Index: 2, Name: System.Windows.Forms.DataVisualization,version=”3.5.0.0″,publicKeyToken=”31bf3856ad364e35″,processorArchitecture=”MSIL”,fileVersion=”3.5.30729.116″,culture=”neutral”, Type: REG_MULTI_SZ, Length: 112, Data: O`X&9fQNo8q+=[WOk(@QChart_Feature>v’=bOR[V[A!n0Y5w^}Hc HKCU\Software\Microsoft\Installer\Assemblies\Global
10 CultureTest.exe RegEnumValue SUCCESS Index: 3, Name: System.Windows.Forms.DataVisualization.Design,version=”3.5.0.0″,publicKeyToken=”31bf3856ad364e35″,processorArchitecture=”MSIL”,fileVersion=”3.5.30729.116″,culture=”neutral”, Type: REG_MULTI_SZ, Length: 112, Data: O`X&9fQNo8q+=[WOk(@QChart_Feature>i_^,7P9r9@brsnF$’^Sq HKCU\Software\Microsoft\Installer\Assemblies\Global
11 CultureTest.exe RegEnumValue SUCCESS Index: 4, Name: System.Web.DataVisualization,version=”3.5.0.0″,publicKeyToken=”31bf3856ad364e35″,processorArchitecture=”MSIL”,fileVersion=”3.5.30729.116″,culture=”neutral”, Type: REG_MULTI_SZ, Length: 112, Data: O`X&9fQNo8q+=[WOk(@QChart_Feature>Wh{mN1!@0AM{uwUXeK*Y HKCU\Software\Microsoft\Installer\Assemblies\Global
12 CultureTest.exe RegEnumValue SUCCESS Index: 5, Name: System.Web.DataVisualization.Design,version=”3.5.0.0″,publicKeyToken=”31bf3856ad364e35″,processorArchitecture=”MSIL”,fileVersion=”3.5.30729.116″,culture=”neutral”, Type: REG_MULTI_SZ, Length: 112, Data: O`X&9fQNo8q+=[WOk(@QChart_Feature>)s9`q)4`i?zUn`)KOc8c HKCU\Software\Microsoft\Installer\Assemblies\Global
13 CultureTest.exe RegEnumValue NO MORE ENTRIES Index: 6, Length: 4,168 HKCU\Software\Microsoft\Installer\Assemblies\Global
14 CultureTest.exe RegCloseKey SUCCESS HKCU\Software\Microsoft\Installer\Assemblies\Global
15 CultureTest.exe RegOpenKey SUCCESS Desired Access: Read HKCR\Installer\Assemblies\Global
16 CultureTest.exe RegEnumValue SUCCESS Index: 0, Name: Microsoft.VisualStudio.VSContentInstaller,Version=”8.0.0.0″,PublicKeyToken=”b03f5f7f11d50a3a”,Culture=”neutral”,FileVersion=”8.0.50727.42″,ProcessorArchitecture=”MSIL”, Type: REG_MULTI_SZ, Length: 404, Data: Du!zKukZ[8DDoq4qr00M>IEJ5Ceoex8F3H%MC+Ga*, gKH-=4wv49{b[v2]HUCqDEXPLORE>IEJ5Ceoex8F3H%MC+Ga*, UvOAm{qpx?)oAC’mF&N`VSTA_IDE>IEJ5Ceoex8F3H%MC+Ga*, ^Sd&qu_%!Ajz=c-67LgzVS_Baseline_Shell>IEJ5Ceoex8F3H%MC+Ga* HKCR\Installer\Assemblies\Global
17 CultureTest.exe RegEnumValue SUCCESS Index: 1, Name: Microsoft.VisualStudio.Zip,Version=”8.0.0.0″,PublicKeyToken=”b03f5f7f11d50a3a”,Culture=”neutral”,FileVersion=”8.0.50727.42″,ProcessorArchitecture=”MSIL”, Type: REG_MULTI_SZ, Length: 708, Data: Du!zKukZ[8DDoq4qr00M>gOxADwX’$9kl’.`[S7hE, Du!zKukZ[8DDoq4qr00M>O%ZhVgKv@A4B`u_Z?tGQ, gKH-=4wv49{b[v2]HUCqDEXPLORE>gOxADwX’$9kl’.`[S7hE, gKH-=4wv49{b[v2]HUCqDEXPLORE>O%ZhVgKv@A4B`u_Z?tGQ, UvOAm{qpx?)oAC’mF&N`VSTA_IDE_Resources>gOxADwX’$9kl’.`[S7hE, UvOAm{qpx?)oAC’mF&N`VSTA_IDE>O%ZhVgKv@A4B`u_Z?tGQ, ^Sd&qu_%!Ajz=c-67LgzVS_Baseline_Shell>gOxADwX’$9kl’.`[S7hE HKCR\Installer\Assemblies\Global
18 CultureTest.exe RegEnumValue SUCCESS Index: 2, Name: Microsoft.VisualStudio.CommonIDE,Version=”8.0.0.0″,PublicKeyToken=”b03f5f7f11d50a3a”,Culture=”neutral”,FileVersion=”8.0.50727.42″,ProcessorArchitecture=”MSIL”, Type: REG_MULTI_SZ, Length: 286, Data: Du!zKukZ[8DDoq4qr00M>vpAcaJ2Wn@5ip,X!wCW!, gKH-=4wv49{b[v2]HUCqDEXPLORE>vpAcaJ2Wn@5ip,X!wCW!, UvOAm{qpx?)oAC’mF&N`VSTA_IDE>vpAcaJ2Wn@5ip,X!wCW! HKCR\Installer\Assemblies\Global
19 CultureTest.exe RegEnumValue SUCCESS Index: 3, Name: EnvDTE,Version=”8.0.0.0″,PublicKeyToken=”b03f5f7f11d50a3a”,Culture=”neutral”,FileVersion=”8.0.50727.42″, Type: REG_MULTI_SZ, Length: 404, Data: Du!zKukZ[8DDoq4qr00M>@,s,oxU@??Bf~_96IfEk, gKH-=4wv49{b[v2]HUCqDEXPLORE>@,s,oxU@??Bf~_96IfEk, UvOAm{qpx?)oAC’mF&N`VSTA_IDE>@,s,oxU@??Bf~_96IfEk, ^Sd&qu_%!Ajz=c-67LgzVS_Baseline_Shell>@,s,oxU@??Bf~_96IfEk HKCR\Installer\Assemblies\Global
20 CultureTest.exe RegEnumValue SUCCESS Index: 4, Name: EnvDTE80,Version=”8.0.0.0″,PublicKeyToken=”b03f5f7f11d50a3a”,Culture=”neutral”,FileVersion=”8.0.50727.42″, Type: REG_MULTI_SZ, Length: 404, Data: Du!zKukZ[8DDoq4qr00M>t’fLj76Px?g%5Lxn)q8x, gKH-=4wv49{b[v2]HUCqDEXPLORE>t’fLj76Px?g%5Lxn)q8x, UvOAm{qpx?)oAC’mF&N`VSTA_IDE>t’fLj76Px?g%5Lxn)q8x, ^Sd&qu_%!Ajz=c-67LgzVS_Baseline_Shell>t’fLj76Px?g%5Lxn)q8x HKCR\Installer\Assemblies\Global
21 CultureTest.exe RegEnumValue SUCCESS Index: 5, Name: Microsoft.VisualStudio.Shell,Version=”2.0.0.0″,PublicKeyToken=”b03f5f7f11d50a3a”,Culture=”neutral”,FileVersion=”2.0.50727.42″,ProcessorArchitecture=”MSIL”, Type: REG_MULTI_SZ, Length: 386, Data: Du!zKukZ[8DDoq4qr00M>66^Wy*2E=9qqd?H3c$dl, gKH-=4wv49{b[v2]HUCqDEXPLORE>66^Wy*2E=9qqd?H3c$dl, UvOAm{qpx?)oAC’mF&N`VSTA_IDE>66^Wy*2E=9qqd?H3c$dl, UvOAm{qpx?)oAC’mF&N`VSTA_IDE>=f^c@WH_u9~OIp_cDln1 HKCR\Installer\Assemblies\Global
…
1114 CultureTest.exe RegEnumValue SUCCESS Index: 1,098, Name: Policy.11.0.Microsoft.Office.Interop.Word,fileVersion=”12.0.4518.1014″,version=”12.0.0.0000000″,culture=”neutral”,publicKeyToken=”71E9BCE111E9429C”, Type: REG_MULTI_SZ, Length: 102, Data: w_1^VV!!!!!!!!!MKKSkWord_PIA>$c5^P,b`F=p4x$@{SnSa HKCR\Installer\Assemblies\Global
1115 CultureTest.exe RegEnumValue SUCCESS Index: 1,099, Name: Microsoft.Vbe.Interop,Version=”11.0.0.0000″,Culture=”neutral”,PublicKeyToken=”71e9bce111e9429c”,FileVersion=”11.0.8161.0″, Type: REG_MULTI_SZ, Length: 120, Data: (f’^Vn-}f(ZXfeAR6.jiVSCommonPIAHidden>X.2kG@=8r=omnVtBlW4t HKCR\Installer\Assemblies\Global
1116 CultureTest.exe RegEnumValue NO MORE ENTRIES Index: 1,100, Length: 4,168 HKCR\Installer\Assemblies\Global
Mivel nem akarok senkivel kitolni kivágtam ezer sort a kimenetből. Ráadásul az előbb 2x is lefut a registryben. Mi a fene ez?
A .NET betöltője (fusion) ha nem tud betölteni egy assembly-t a probing folyamat során, akkor végső kétségbeesésében arra gondol, biztos ott van az, csak letörölték. Elő hát az MSI installerrel -ha van neki- és állítsuk vissza azt telepítésből – gondolja, és így is tesz. Átnézi a fenti több mint ezer bejegyzést, hátha. De nem. Sajnos ezen hiábavaló próbálkozás elég sok időt elvisz, akár 1-2 mp-cel is lassabbá teheti a program elindulását.
Számomra ez egy igen bosszantó, okoskodó fícsör, írtam is Junfeng Zhang-nak, ki lehet-e kapcsolni, de sajnos nem kaptam választ.
Mi mégis a megoldás? Meg kell akadályozni a keresgélést, ha nincs szükségünk erre a szolgáltatásra.
Tegyük fel nem szeretném lokalizálni az appot egyelőre, azaz számomra teljesen felesleges ez a keresgélés. Hogyan lehet megmondani, hogy az erőforrásokat csak a fő assemblyben keresse?
Egyszerű, a Main() elejére:
Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.InvariantCulture;
Ezek után már egyáltalán nem keresgél a lemezen és a registryben sem. Semennyire. Egyszerű? Tetszik? :)