Could you hire me? Contact me if you like what I’ve done in this article and think I can create value for your company with my skills.

January 26, 2009 / by Zsolt Soczó

.NET teljesítményhangolási tapasztalatok 1.

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? :)

Could you hire me? Contact me if you like what I’ve done in this article and think I can create value for your company with my skills.

LEAVE A COMMENT

2 COMMENTS

  • KRis February 13, 2009

    Hello,

    Ez nem ehhez kapcsolódik?!?
    ——-

    http://blogs.msdn.com/bclteam/archive/2008/11/04/what-s-new-in-the-bcl-in-net-4-0-justin-van-patten.aspx

    ResourceManager Improvements
    The ResourceManager in System.Resources has been improved to respect the user’s preferred UI languages when looking for localized resources, instead of only using the CurrentUICulture’s parent chain. This means if the user has specified that she prefers French and Spanish, the ResourceManager will look for French and Spanish resources before falling back to the neutral resources. This change is present in Silverlight 2 as well as .NET 4.0.

  • Soczó Zsolt February 13, 2009

    De, köszi a pointert.