| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- #include "CommonDataStructuresPch.h"
- #if PROFILE_DICTIONARY
- #include "DictionaryStats.h"
- DictionaryType* DictionaryStats::dictionaryTypes = NULL;
- CriticalSection DictionaryStats::dictionaryTypesCriticalSection;
- DictionaryStats* DictionaryStats::Create(const char* name, uint bucketCount)
- {
- if (!Js::Configuration::Global.flags.IsEnabled(Js::ProfileDictionaryFlag) ||
- Js::Configuration::Global.flags.ProfileDictionary < 0)
- return NULL;
- return NoCheckHeapNew(DictionaryStats, name, bucketCount);
- }
- DictionaryStats* DictionaryStats::Clone()
- {
- DictionaryStats* cloned = NoCheckHeapNew(DictionaryStats, pName, initialSize);
- cloned->finalSize = finalSize;
- cloned->countOfEmptyBuckets = countOfEmptyBuckets;
- cloned->countOfResize = countOfResize;
- cloned->itemCount = itemCount;
- cloned->maxDepth = maxDepth;
- cloned->lookupCount = lookupCount;
- cloned->collisionCount = collisionCount;
- cloned->lookupDepthTotal = lookupDepthTotal;
- cloned->maxLookupDepth = maxLookupDepth;
- cloned->pName = pName;
- return cloned;
- }
- DictionaryStats::DictionaryStats(const char* name, uint bucketCount)
- :
- initialSize(bucketCount),
- finalSize(bucketCount),
- countOfEmptyBuckets(bucketCount),
- countOfResize(0),
- itemCount(0),
- maxDepth(0),
- lookupCount(0),
- collisionCount(0),
- lookupDepthTotal(0),
- maxLookupDepth(0),
- pNext(NULL),
- pName(NULL)
- {
- DictionaryStats::dictionaryTypesCriticalSection.Enter();
- DictionaryType* type = NULL;
- // See if we already created instance(s) of this type
- DictionaryType* current = dictionaryTypes;
- while(current)
- {
- if (strncmp(name, current->name, _countof(current->name)-1) == 0)
- {
- type = current;
- break;
- }
- current = current->pNext;
- }
- if (!type)
- {
- // We haven't seen this type before so add a new entry for it
- type = NoCheckHeapNew(DictionaryType);
- type->pNext = dictionaryTypes;
- dictionaryTypes = type;
- type->instancesCount = 0;
- strncpy_s(type->name, name, _countof(type->name)-1);
- type->name[sizeof(type->name)-1]='\0';
- }
- dictionaryTypesCriticalSection.Leave();
- // keep a pointer to the name in case we are asked to clone ourselves
- pName = type->name;
- // Add ourself in the list
- pNext = type->instances;
- type->instances = this;
- ++(type->instancesCount);
- }
- void DictionaryStats::Resize(uint newSize, uint emptyBucketCount)
- {
- finalSize = newSize;
- countOfEmptyBuckets = emptyBucketCount;
- ++countOfResize;
- }
- void DictionaryStats::Insert(uint depth)
- {
- ++itemCount;
- if (maxDepth < depth)
- maxDepth = depth;
- if (depth == 1 && countOfEmptyBuckets > 0)
- --countOfEmptyBuckets;
- }
- void DictionaryStats::Remove(bool isBucketEmpty)
- {
- if (itemCount > 0)
- --itemCount;
- if (isBucketEmpty)
- ++countOfEmptyBuckets;
- }
- void DictionaryStats::Lookup(uint depth)
- {
- // Note, lookup and collision math only works out if depth is 0-based.
- // I.e., depth of 1 means there was 1 collision and the lookup found key at second item in the bucket
- lookupCount += 1;
- lookupDepthTotal += depth;
- if (depth > 0)
- collisionCount += 1;
- if (maxLookupDepth < depth)
- maxLookupDepth = depth;
- }
- void DictionaryStats::OutputStats()
- {
- if (!dictionaryTypes)
- return;
- DictionaryStats::dictionaryTypesCriticalSection.Enter();
- DictionaryType* current = dictionaryTypes;
- Output::Print(_u("PROFILE DICTIONARY\n"));
- Output::Print(_u("%8s %13s %13s %13s %13s %13s %13s %13s %14s %14s %13s %13s %13s %s\n"), _u("Metric"),_u("StartSize"), _u("EndSize"), _u("Resizes"), _u("Items"), _u("MaxDepth"), _u("EmptyBuckets"), _u("Lookups"), _u("Collisions"), _u("AvgLookupDepth"), _u("AvgCollDepth"), _u("MaxLookupDepth"), _u("Instances"), _u("Type"));
- while(current)
- {
- DictionaryType *type = current;
- DictionaryStats *instance = type->instances;
- double size = 0, max_size = 0;
- double endSize = 0, max_endSize = 0;
- double resizes = 0, max_resizes = 0;
- double items = 0, max_items = 0;
- double depth = 0, max_depth = 0;
- double empty = 0, max_empty = 0;
- double lookups = 0, max_lookups = 0;
- double collisions = 0, max_collisions = 0;
- double avglookupdepth = 0, max_avglookupdepth = 0;
- double avgcollisiondepth = 0, max_avgcollisiondepth = 0;
- double maxlookupdepth = 0, max_maxlookupdepth = 0;
- bool dumpInstances = false;
- //if(strstr(type->name, "SimpleDictionaryPropertyDescriptor") != nullptr)
- //{
- // dumpInstances = true;
- //}
- while(instance)
- {
- ComputeStats(instance->initialSize, size, max_size);
- ComputeStats(instance->finalSize, endSize, max_endSize);
- ComputeStats(instance->countOfResize, resizes, max_resizes);
- ComputeStats(instance->itemCount, items, max_items);
- ComputeStats(instance->maxDepth, depth, max_depth);
- ComputeStats(instance->countOfEmptyBuckets, empty, max_empty);
- ComputeStats(instance->lookupCount, lookups, max_lookups);
- ComputeStats(instance->collisionCount, collisions, max_collisions);
- if (instance->lookupCount > 0)
- {
- ComputeStats((double)instance->lookupDepthTotal / (double)instance->lookupCount, avglookupdepth, max_avglookupdepth);
- }
- if (instance->collisionCount > 0)
- {
- ComputeStats((double)instance->lookupDepthTotal / (double)instance->collisionCount, avgcollisiondepth, max_avgcollisiondepth);
- }
- ComputeStats(instance->maxLookupDepth, maxlookupdepth, max_maxlookupdepth);
- if(dumpInstances)
- {
- double avgld = 0.0;
- double avgcd = 0.0;
- if (instance->lookupCount > 0)
- {
- avgld = (double)instance->lookupDepthTotal / (double)instance->lookupCount;
- avgcd = (double)instance->lookupDepthTotal / (double)instance->collisionCount;
- }
- Output::Print(_u("%8s %13d %13d %13d %13d %13d %13d %13d %14d %14.2f %13.2f %13d \n"),
- _u("INS:"),
- instance->initialSize, instance->finalSize, instance->countOfResize,
- instance->itemCount, instance->maxDepth, instance->countOfEmptyBuckets,
- instance->lookupCount, instance->collisionCount, avgld, avgcd,
- instance->maxLookupDepth);
- }
- instance = instance->pNext;
- }
- if (max_depth >= Js::Configuration::Global.flags.ProfileDictionary)
- {
- Output::Print(_u("%8s %13.0f %13.0f %13.2f %13.0f %13.2f %13.0f %13.0f %14.0f %14.2f %13.2f %13.2f %13d %S\n"), _u("AVG:"),
- size/type->instancesCount, endSize/type->instancesCount, resizes/type->instancesCount, items/type->instancesCount,
- depth/type->instancesCount, empty/type->instancesCount, lookups/type->instancesCount, collisions/type->instancesCount,
- avglookupdepth/type->instancesCount, avgcollisiondepth/type->instancesCount, maxlookupdepth/type->instancesCount, type->instancesCount, type->name);
- Output::Print(_u("%8s %13.0f %13.0f %13.2f %13.0f %13.2f %13.0f %13.0f %14.0f %14.2f %13.2f %13.2f %13d %S\n\n"), _u("MAX:"),
- max_size, max_endSize, max_resizes, max_items, max_depth, max_empty, max_lookups, max_collisions, max_avglookupdepth,
- max_avgcollisiondepth, max_maxlookupdepth, type->instancesCount, type->name);
- }
- current = current->pNext;
- }
- Output::Print(_u("====================================================================================\n"));
- ClearStats();
- DictionaryStats::dictionaryTypesCriticalSection.Leave();
- }
- void DictionaryStats::ComputeStats(uint input, double &total, double &max)
- {
- total += input;
- if (input > max)
- max = input;
- }
- void DictionaryStats::ComputeStats(double input, double &total, double &max)
- {
- total += input;
- if (input > max)
- max = input;
- }
- void DictionaryStats::ClearStats()
- {
- // Clear the collection since we already reported on what we already collected
- DictionaryType* current = dictionaryTypes;
- while(current)
- {
- DictionaryType *type = current;
- DictionaryStats *pNext = type->instances;
- while(pNext)
- {
- DictionaryStats *pCurrent = pNext;
- pNext = pNext->pNext;
- NoCheckHeapDelete(pCurrent);
- }
- current = current->pNext;
- NoCheckHeapDelete(type);
- }
- dictionaryTypes = NULL;
- }
- #endif
|