databájt 2010.11.05. 16:47

How time flies

 Jó napot, jó kódolást! 

Rég nem volt idő arra, hogy kézbe vevén sorsunk alakulását a hatékony kódolásról írjak.

S hogy az idő hogyan repül, mi sem mutatja jobban, hogy míg szeretett Inveniónk keresőmotorjának alapjai felépülnek egy-egy telepítés után, arcunkat megcserzi LCD kijelzőnk gyengécske fénye. 

Nekiláttam hát megnézni, hogyan repülhet el több perc, míg a „search schema generálódik”. 

Az első profile mérést követően ilyesmi fogadott: 

 

A képről jól látható, hogy a legforróbb (jujjdejó! J) kód a MetadataTools.GetAclIdFieldsForCacheTable() metódus hívása, rögtön az első két leglassabb kód dobogós helyezését megkapta.

További nézelődés után kiderült, hogy az említett metódus belseje 9000-nél is többször hívódik, ami tekintve az adatbázis táblák számát azt jelenti, hogy 1-1 táblát legalább 10-szer újra processzálunk. 

Hogyan is szól az ismerős mantra? Cachelni, cachelni, khm... CACHELNI. Lássuk, hol lehet gyorsítani az eljárásunkon! 

Az eredeti kód ez volt:


IEnumerable<TypeContainer> containers = DALProvider.Metadata.TypeContainers.Where(

       t => t.IsMapped && !t.IsInfoContainer && !t.IsInfoBaseContainer && t.TableMapping.SchemaName == baseTableSchema && t.TableMapping.TableName == baseTableName); 

if (containers.Count() > 0)
{
       container = containers.First();
       if (container.SecurityDomains != null)
       {
             foreach (var  item in container.SecurityDomains.Values)
             {
                    if (item is AuthorizationSecuredObjectTypeAttribute)
                    {
                           var securedObjectType = (AuthorizationSecuredObjectTypeAttribute)item;
                            var aclField = new Field(securedObjectType.AclColumnName, Service.GetAclcolumnType, true);
                           aclIdFields.Add(aclField);
                    }
             }
       }
}


 

 

Nosza, ásó-kapa-refaktor gomb, a csúnya lookup részt imígyen faragtam élesebbre egy meglévő, cache-elt lookup-oláshoz készült metódus segítségével:

 


var aclIdFields2 = new List<Field>();
TypeContainer container2 = null;

if (DALProvider.Metadata.TryGetMappedContainer(baseTableSchema, baseTableName, out container2))
{
       if (container2.SecurityDomains != null)
       {
             foreach (var item in container2.SecurityDomains.Values)
             {
                    if (item is AuthorizationSecuredObjectTypeAttribute)
                    {
                            var securedObjectType = (AuthorizationSecuredObjectTypeAttribute)item;
                            var aclField = new Field(securedObjectType.AclColumnName, Service.GetAclcolumnType, true);
                           aclIdFields2.Add(aclField);
                    }
            }
     }
} 


 

Hogy validáljam az egyszerűsítést, mindkét kódblokkot meghagytam egy mérés erejéig, diff-et készítettem a két megoldásról az ellenőrzés végett, és Stopwatch-al kimértem az egyes futási időket.

Ilyen lett a végső metódus: 


internal static List<Field> GetAclIdFieldsForCacheTable(string baseTableSchema, string baseTableName)
{
       var aclIdFields = new List<Field>(); 
       InitializeDalProvider(); 
       TypeContainer container = null;
       //DALProvider.Metadata.TryGetMappedContainer(baseTableSchema, baseTableName, out container); 
       Stopwatch sw1 = Stopwatch.StartNew();
       // DEVNOTE: Do NOT do reverse-lookups like below, there are cached lookup-methods available!
        var containers = DALProvider.Metadata.TypeContainers.Where(t => t.IsMapped && !t.IsInfoContainer && !t.IsInfoBaseContainer && t.TableMapping.SchemaName == baseTableSchema && t.TableMapping.TableName == baseTableName);
       if (containers.Count() > 0)
       {
             container = containers.First();
             if (container.SecurityDomains != null)
             {
                    foreach (var item in container.SecurityDomains.Values)
                    {
                           if (item is AuthorizationSecuredObjectTypeAttribute)
                           {
                                   var securedObjectType = (AuthorizationSecuredObjectTypeAttribute)item;
                                   var aclField = new Field(securedObjectType.AclColumnName, Service.GetAclcolumnType, true);
                                  aclIdFields.Add(aclField);
                           }
                    }
             }
       }
       sw1.Stop();

        var sw2 = Stopwatch.StartNew();
        var aclIdFields2 = new List<Field>();
        var container2 = null;
       if (DALProvider.Metadata.TryGetMappedContainer(baseTableSchema, baseTableName, out container2))
       {
             if (container2.SecurityDomains != null)
             {
                    foreach (var item in container2.SecurityDomains.Values)
                    {
                           if (item is AuthorizationSecuredObjectTypeAttribute)
                           {
                                   var securedObjectType = (AuthorizationSecuredObjectTypeAttribute)item;
                                   var aclField = new Field(securedObjectType.AclColumnName, Service.GetAclcolumnType, true);
                                  aclIdFields2.Add(aclField);
                           }
                    }
             }
       }
       sw2.Stop(); 

       _log.Info("Original lookup took " + sw1.Elapsed.TotalMilliseconds + " ms (" + sw1.Elapsed.Ticks + " ticks), optimized lookup took " + sw2.Elapsed.TotalMilliseconds + " ms (" + sw2.Elapsed.Ticks + " ticks), difference was " + ((100 * ((double)sw1.Elapsed.Ticks / (double)sw2.Elapsed.Ticks)) - 100).ToString() + "%");

       Differencer.AddKeyAccessor(typeof(Field), new Getter(f => ((Field)f).Name), false);
       Diff diff = Differencer.Compare(aclIdFields, aclIdFields2);
       if (diff.Type != DiffType.Unchanged)
       {
             _log.Error("Second lookup of [" + baseTableSchema + "].[" + baseTableName + "] resulted in different AclID field list!");
       }
       return aclIdFields;
} 


 

Ha a százalékszámítást valaki szerint rosszul csináltam, szóljatok rám, azért álljon itt példának okáért néhány bejegyzés a logból: 


2010-11-05 16:21:24,771 [6] INFO  MetadataManager [SearchConfigurationService.CreateSearchStructures CreateMetadataObjects CreateCacheTables] - Original lookup took 4,2451 ms (42451 ticks), optimized lookup took 0,7844 ms (7844 ticks), difference was 441,190719020908%

2010-11-05 16:21:24,774 [6] INFO  MetadataManager [SearchConfigurationService.CreateSearchStructures CreateMetadataObjects CreateCacheTables] - Original lookup took 0,4821 ms (4821 ticks), optimized lookup took 0,0101 ms (101 ticks), difference was 4673,26732673267%

2010-11-05 16:21:24,775 [6] INFO  MetadataManager [SearchConfigurationService.CreateSearchStructures CreateMetadataObjects CreateCacheTables] - Original lookup took 0,5033 ms (5033 ticks), optimized lookup took 0,0074 ms (74 ticks), difference was 6701,35135135135%

2010-11-05 16:21:24,776 [6] INFO  MetadataManager [SearchConfigurationService.CreateSearchStructures CreateMetadataObjects CreateCacheTables] - Original lookup took 0,5063 ms (5063 ticks), optimized lookup took 0,0039 ms (39 ticks), difference was 12882,0512820513%

2010-11-05 16:21:24,777 [6] INFO  MetadataManager [SearchConfigurationService.CreateSearchStructures CreateMetadataObjects CreateCacheTables] - Original lookup took 0,509 ms (5090 ticks), optimized lookup took 0,0039 ms (39 ticks), difference was 12951,2820512821%

2010-11-05 16:21:24,778 [6] INFO  MetadataManager [SearchConfigurationService.CreateSearchStructures CreateMetadataObjects CreateCacheTables] - Original lookup took 0,5591 ms (5591 ticks), optimized lookup took 0,0039 ms (39 ticks), difference was 14235,8974358974%

2010-11-05 16:21:24,779 [6] INFO  MetadataManager [SearchConfigurationService.CreateSearchStructures CreateMetadataObjects CreateCacheTables] - Original lookup took 0,4016 ms (4016 ticks), optimized lookup took 0,0039 ms (39 ticks), difference was 10197,4358974359%

2010-11-05 16:21:24,780 [6] INFO  MetadataManager [SearchConfigurationService.CreateSearchStructures CreateMetadataObjects CreateCacheTables] - Original lookup took 0,5803 ms (5803 ticks), optimized lookup took 0,0039 ms (39 ticks), difference was 14779,4871794872%

2010-11-05 16:21:24,781 [6] INFO  MetadataManager [SearchConfigurationService.CreateSearchStructures CreateMetadataObjects CreateCacheTables] - Original lookup took 0,5314 ms (5314 ticks), optimized lookup took 0,0039 ms (39 ticks), difference was 13525,641025641%

2010-11-05 16:21:24,783 [6] INFO  MetadataManager [SearchConfigurationService.CreateSearchStructures CreateMetadataObjects CreateCacheTables] - Original lookup took 0,5904 ms (5904 ticks), optimized lookup took 0,0096 ms (96 ticks), difference was 6050%

2010-11-05 16:21:24,783 [6] INFO  MetadataManager [SearchConfigurationService.CreateSearchStructures CreateMetadataObjects CreateCacheTables] - Original lookup took 0,5349 ms (5349 ticks), optimized lookup took 0,0035 ms (35 ticks), difference was 15182,8571428571%

2010-11-05 16:21:24,795 [6] INFO  MetadataManager [SearchConfigurationService.CreateSearchStructures CreateMetadataObjects CreateCacheTables] - Original lookup took 0,4725 ms (4725 ticks), optimized lookup took 0,0052 ms (52 ticks), difference was 8986,53846153846%

 


 

Nos igen. 

Ha egy-egy lookup ~4400 helyett 40 tick, az annyi mint... 100-szoros gyorsulás, köbö 1000%. Plusz-mínusz néhány száz %, ahogy elnézem. 

Tanulság 

Röviden a lényeg:

·         A cache-elt lookup-olás, főleg gyakran használt ám sosem/ritkán változó  elemeknél a 21. században nem opció – kötelező!

·         A LINQ query támogatás jó, jó... de nem mindenre.

·         Egymás kódjába belesz@rni nem szép dolog... kivéve, ha 100%-nál nagyobb gyorsulást eredményez változatlan működés mellett.

Szólj hozzá!

A bejegyzés trackback címe:

https://dotnot.blog.hu/api/trackback/id/tr184295562

Kommentek:

A hozzászólások a vonatkozó jogszabályok  értelmében felhasználói tartalomnak minősülnek, értük a szolgáltatás technikai  üzemeltetője semmilyen felelősséget nem vállal, azokat nem ellenőrzi. Kifogás esetén forduljon a blog szerkesztőjéhez. Részletek a  Felhasználási feltételekben és az adatvédelmi tájékoztatóban.

Nincsenek hozzászólások.
süti beállítások módosítása