.NET teljesítményhangolási tapasztalatok 4.
Óvakodj az enumtól, mert lassú lészen az - áll a .NET bibliában.
Ártatlan kis jószágnak néz ki ez az enum, mégis sokszor láttam már, hogy miatta lassul be egy rendszer. Mi a lassú rajta? Minden. A Parsolás pl. De ez még érthető is. De hogy a ToString() is tetű, az már kevésbé. Sajnos azonban reflectiont használ ezekhez a műveletekhez, ami köztudottan lassú.
Szerencsére elég könnyű segíteni a baján. Ha Parsolni kell, azaz egy string alapján kell egy enum értéket megszülni, akkor ezt egyszerűen meg lehet oldani egy Dictionary-vel, ami string kulcsokkal és az konkrét enum értékekkel van feltöltve.
Most a másik oldalt mutatom meg, a turbó ToString()-et.
Egyszerű demó enumunk:
public enum TradeDirection
{
Short,
Long
}
Ebből tehát ha van egy példányunk amin ToString()-et hívunk, az lassú lesz. Hozzunk létre egy Dictionary-t, ami segít az enum-string asszociációban.
private static Dictionary<TradeDirection, string> tradeDirectionNames = new Dictionary<TradeDirection, string>();
Ezt kellene felölteni értékekkel. A C# generikus dolgaival szépen meg lehet ezt általánosan is fogalmazni, így mindenféle enumra működni fog:
tradeDirectionNames.FillEnumCache();
public static void FillEnumCache<T>(this Dictionary<T, string> enumNames)
{
foreach (T enumValue in Enum.GetValues(typeof(T)))
{
enumNames.Add(enumValue, enumValue.ToString());
}
}
Mivel extension methodként írtam meg olyan, mintha a Dictionary tudná ezt a funkciót, a T típusparamétert meg kitalálja a compiler, így nem kell kiírjam a teljes alakot:
tradeDirectionNames<TradeDirection>.FillEnumCache();
Hogy jogos-e erre az extension method az objektumorientált szempontból erősen vitatható, de nekem így kézre esett.
A generizálhatóság viszont szenzációs. Ezért imádom a C#-ot.
Miután a fenti megoldással gyorsítottam a rendszeren kiderült (profilerrel, mi mással), hogy egy összetett típusban ami két enumból állt lassú volt a GetHashCode implementációm, ami így nézett ki:
public override int GetHashCode()
{
return dir.GetHashCode() + zone.GetHashCode();
}
A dir és a zone egy-egy enum.
A gyorsításhoz így írtam át:
public override int GetHashCode()
{
return (int)dir << 4 + (int)zone;
}
Ez nem csak gyorsabb, de jobban is szór, mint az előző.
February 8th, 2009 at 10:44 pm
Nekem azért furcsa ez, mert nekem pont ez tetszett annó a .NET-ben a Java-hoz képest, hogy rengeteg enum-ot használ!
Ennek hatására kezdtem el én is erőteljesen használni Java-ban az enum-okat.
Ezek után ha akad egy kis időm, majd én is ránézek profilerrel.
February 8th, 2009 at 11:51 pm
Kíváncsi vagyok mit látsz. Nekem ez már nem az első eset, hogy belefutok.
February 10th, 2009 at 4:43 pm
Hello,
Ennek az éremnek is két, de lehet hogy több, oldala van.
Hányszor hallottam hogy fúúúúj string + string… helyette string.format, meg stringbuilder…
Persze… igaz ha 1 millioszor kell ciklusban napi 100x ezt csinálni, vagy életek múlnak rajta…
De ha nem akkor nem kell bit szintre lemenni…
Ez a c# és a fejlett nyelvek lényege!!! Absztrakció… A problémával foglalkozunk, és nem a tényleges technikai megvalósítással.
Tehát nem kell most rohanni és minden enum-t azonnal átírni, és a következő projektekben elő sem venni.
Fel kell mérni, a helyzetet, és a szerint dolgozni. Mert lássuk be: az enumok megkönnyítik az életet : egyszerűsítenek, átláthatóbbá teszik a kódot, érthetőbbek, beszédesek…
Ettől persze igaza van Socinak a fenti példában.
De ilyet találunk minden mérnöki területen: követelmény-kényszer ill. fizikai/technikai ellentmondások területen…
Kicsi legyen a telefonom bírja sokáig az aksi (nagyobb kell)
Ez a szép… át kell hidalni :)
Üdv,
KRis
February 10th, 2009 at 5:08 pm
Persze, ettől még nem dobtam ki én se az enumot, csak körbeprogramoztam ott, ahol lassú volt.
February 13th, 2009 at 4:04 pm
Már majdnem azt hittem, hogy egy fricskát elengedhetek, hogy minek leprogramozni azt, amit a MS már megcsinált egyszer… ;-)
De aztán rácsodálkoztam, hogy a System.ComponentModel.EnumConverter nem chache-el… :-( Pedig mindene megvan hozzá…
February 13th, 2009 at 4:05 pm
Természetesen: chache=cache vagy magyarosan: kessel
January 8th, 2010 at 4:49 pm
[...] hogy az enum-sztring konverzió elég lassúcska, teljesítményérzékeny alkalmazásokban néha rá kell programoznunk, ha nem akarunk odaborostásodni a gép [...]