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.

February 5, 2009 / by Zsolt Soczó

.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 tradeDirectionNames = new Dictionary();

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(this Dictionary 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.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; } [/source] Ez nem csak gyorsabb, de jobban is szór, mint az előző.

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

7 COMMENTS

  • Sipos Tamás February 8, 2009

    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.

  • Soczó Zsolt February 8, 2009

    Kíváncsi vagyok mit látsz. Nekem ez már nem az első eset, hogy belefutok.

  • KRis February 10, 2009

    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

  • Soczó Zsolt February 10, 2009

    Persze, ettől még nem dobtam ki én se az enumot, csak körbeprogramoztam ott, ahol lassú volt.

  • SebDani February 13, 2009

    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á…

  • SebDani February 13, 2009

    Természetesen: chache=cache vagy magyarosan: kessel