| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- #pragma once
- #ifdef PROFILE_STRINGS
- namespace Js
- {
- enum ConcatType
- {
- ConcatType_Unknown,
- ConcatType_CompoundString,
- ConcatType_ConcatTree,
- ConcatType_BufferString
- };
- class StringProfiler
- {
- private:
- ArenaAllocator allocator;
- ThreadContextId mainThreadId;
- uint discardedWrongThread; // If called on the wrong thread, then statistics are inaccurate
- // Profiling strings records the frequency of each length of string.
- // It also records whether the characters in the string may be encoded
- // as 7-bit ASCII, 8-bit ASCII or if they really require 16bit encoding
- enum RequiredEncoding
- {
- ASCII7bit,
- ASCII8bit,
- Unicode16bit
- };
- struct StringMetrics
- {
- uint count7BitASCII;
- uint count8BitASCII;
- uint countUnicode;
- void Accumulate( RequiredEncoding encoding )
- {
- switch(encoding)
- {
- case ASCII7bit:
- this->count7BitASCII++;
- break;
- case ASCII8bit:
- this->count8BitASCII++;
- break;
- case Unicode16bit:
- this->countUnicode++;
- break;
- }
- }
- uint Total() const
- {
- return this->count7BitASCII +
- this->count8BitASCII +
- this->countUnicode;
- }
- void Accumulate(StringMetrics& rhs)
- {
- this->count7BitASCII += rhs.count7BitASCII;
- this->count8BitASCII += rhs.count8BitASCII;
- this->countUnicode += rhs.countUnicode;
- }
- };
- struct ConcatMetrics
- {
- uint compoundStringCount;
- uint concatTreeCount;
- uint bufferStringBuilderCount;
- uint unknownCount;
- ConcatMetrics() {}
- ConcatMetrics(ConcatType concatType)
- : compoundStringCount(0), concatTreeCount(0), bufferStringBuilderCount(0), unknownCount(0)
- {
- this->Accumulate(concatType);
- }
- void Accumulate(ConcatType concatType)
- {
- switch(concatType)
- {
- case ConcatType_CompoundString:
- this->compoundStringCount++;
- break;
- case ConcatType_ConcatTree:
- this->concatTreeCount++;
- break;
- case ConcatType_BufferString:
- this->bufferStringBuilderCount++;
- break;
- case ConcatType_Unknown:
- this->unknownCount++;
- break;
- }
- }
- uint Total() const
- {
- return this->compoundStringCount +
- this->concatTreeCount +
- this->bufferStringBuilderCount +
- this->unknownCount;
- }
- };
- uint embeddedNULChars; // Total number of embedded NUL chars in all strings
- uint embeddedNULStrings; // Number of strings with at least one embedded NUL char
- uint emptyStrings; // # of requests for zero-length strings (literals or BufferStrings)
- uint singleCharStrings; // # of requests for single-char strings (literals of BufferStrings)
- JsUtil::BaseDictionary<uint, StringMetrics, ArenaAllocator> stringLengthMetrics;
- struct UintUintPair
- {
- uint first;
- uint second;
- bool operator==(UintUintPair const& other) const
- {
- return this->first == other.first && this->second == other.second;
- }
- operator uint() const
- {
- return this->first | (this->second << 16);
- }
- };
- JsUtil::BaseDictionary< UintUintPair, ConcatMetrics, ArenaAllocator, PrimeSizePolicy > stringConcatMetrics;
- bool IsOnWrongThread() const;
- static RequiredEncoding GetRequiredEncoding( const char16* sz, uint length );
- static uint CountEmbeddedNULs( const char16* sz, uint length );
- class HistogramIndex
- {
- UintUintPair* index; // index of "length" and "frequency"
- uint count;
- public:
- HistogramIndex( ArenaAllocator* allocator, uint size );
- void Add( uint len, uint freq );
- void SortDescending();
- uint Get( uint i ) const;
- uint Count() const;
- private:
- static int __cdecl CompareDescending( const void* lhs, const void* rhs );
- };
- static void BuildIndex( unsigned int len, StringMetrics metrics, HistogramIndex* histogram, uint* total );
- static void PrintOne( unsigned int len, StringMetrics metrics, uint totalCount );
- static void PrintUintOrLarge( uint val );
- static void PrintOneConcat( UintUintPair const& key, const ConcatMetrics& metrics);
- void RecordNewString( const char16* sz, uint length );
- void RecordConcatenation( uint lenLeft, uint lenRight, ConcatType type);
- static const uint k_MaxConcatLength = 20; // Strings longer than this are just "large"
- public:
- StringProfiler(PageAllocator * pageAllocator);
- void PrintAll();
- static void RecordNewString( ScriptContext* scriptContext, const char16* sz, uint length );
- static void RecordConcatenation( ScriptContext* scriptContext, uint lenLeft, uint lenRight, ConcatType type = ConcatType_Unknown);
- static void RecordEmptyStringRequest( ScriptContext* scriptContext );
- static void RecordSingleCharStringRequest( ScriptContext* scriptContext );
- };
- } // namespace Js
- #endif
|