/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef CacheFileUtils__h__ #define CacheFileUtils__h__ #include "nsError.h" #include "nsCOMPtr.h" #include "nsString.h" #include "nsTArray.h" #include "mozilla/Mutex.h" #include "mozilla/StaticMutex.h" #include "mozilla/TimeStamp.h" class nsILoadContextInfo; namespace mozilla { namespace net { namespace CacheFileUtils { extern const char* kAltDataKey; already_AddRefed ParseKey(const nsACString& aKey, nsACString* aIdEnhance = nullptr, nsACString* aURISpec = nullptr); void AppendKeyPrefix(nsILoadContextInfo* aInfo, nsACString& _retval); void AppendTagWithValue(nsACString& aTarget, char const aTag, const nsACString& aValue); nsresult KeyMatchesLoadContextInfo(const nsACString& aKey, nsILoadContextInfo* aInfo, bool* _retval); class ValidityPair { public: ValidityPair(uint32_t aOffset, uint32_t aLen); ValidityPair& operator=(const ValidityPair& aOther) = default; // Returns true when two pairs can be merged, i.e. they do overlap or the one // ends exactly where the other begins. bool CanBeMerged(const ValidityPair& aOther) const; // Returns true when aOffset is placed anywhere in the validity interval or // exactly after its end. bool IsInOrFollows(uint32_t aOffset) const; // Returns true when this pair has lower offset than the other pair. In case // both pairs have the same offset it returns true when this pair has a // shorter length. bool LessThan(const ValidityPair& aOther) const; // Merges two pair into one. void Merge(const ValidityPair& aOther); uint32_t Offset() const { return mOffset; } uint32_t Len() const { return mLen; } private: uint32_t mOffset; uint32_t mLen; }; class ValidityMap { public: // Prints pairs in the map into log. void Log() const; // Returns number of pairs in the map. uint32_t Length() const; // Adds a new pair to the map. It keeps the pairs ordered and merges pairs // when possible. void AddPair(uint32_t aOffset, uint32_t aLen); // Removes all pairs from the map. void Clear(); size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const; ValidityPair& operator[](uint32_t aIdx); private: nsTArray mMap; }; class DetailedCacheHitTelemetry { public: enum ERecType { HIT = 0, MISS = 1 }; static void AddRecord(ERecType aType, TimeStamp aLoadStart); private: class HitRate { public: HitRate(); void AddRecord(ERecType aType); // Returns the bucket index that the current hit rate falls into according // to the given aNumOfBuckets. uint32_t GetHitRateBucket(uint32_t aNumOfBuckets) const; uint32_t Count(); void Reset(); private: uint32_t mHitCnt = 0; uint32_t mMissCnt = 0; }; // Group the hits and misses statistics by cache files count ranges (0-5000, // 5001-10000, ... , 95001- ) static const uint32_t kRangeSize = 5000; static const uint32_t kNumOfRanges = 20; // Use the same ranges to report an average hit rate. Report the hit rates // (and reset the counters) every kTotalSamplesReportLimit samples. static const uint32_t kTotalSamplesReportLimit = 1000; // Report hit rate for a given cache size range only if it contains // kHitRateSamplesReportLimit or more samples. This limit should avoid // reporting a biased statistics. static const uint32_t kHitRateSamplesReportLimit = 500; // All hit rates are accumulated in a single telemetry probe, so to use // a sane number of enumerated values the hit rate is divided into buckets // instead of using a percent value. This constant defines number of buckets // that we divide the hit rates into. I.e. we'll report ranges 0%-5%, 5%-10%, // 10-%15%, ... static const uint32_t kHitRateBuckets = 20; // Protects sRecordCnt, sHRStats and Telemetry::Accumulated() calls. static StaticMutex sLock; // Counter of samples that is compared against kTotalSamplesReportLimit. static uint32_t sRecordCnt MOZ_GUARDED_BY(sLock); // Hit rate statistics for every cache size range. static HitRate sHRStats[kNumOfRanges] MOZ_GUARDED_BY(sLock); }; class CachePerfStats { public: // perfStatTypes in displayRcwnStats() in toolkit/content/aboutNetworking.js // must match EDataType enum EDataType { IO_OPEN = 0, IO_READ = 1, IO_WRITE = 2, ENTRY_OPEN = 3, LAST = 4 }; static void AddValue(EDataType aType, uint32_t aValue, bool aShortOnly); static uint32_t GetAverage(EDataType aType, bool aFiltered); static uint32_t GetStdDev(EDataType aType, bool aFiltered); static bool IsCacheSlow(); static void GetSlowStats(uint32_t* aSlow, uint32_t* aNotSlow); private: // This class computes average and standard deviation, it returns an // arithmetic avg and stddev until total number of values reaches mWeight. // Then it returns modified moving average computed as follows: // // avg = (1-a)*avg + a*value // avgsq = (1-a)*avgsq + a*value^2 // stddev = sqrt(avgsq - avg^2) // // where // avgsq is an average of the square of the values // a = 1 / weight class MMA { public: MMA(uint32_t aTotalWeight, bool aFilter); void AddValue(uint32_t aValue); uint32_t GetAverage(); uint32_t GetStdDev(); private: uint64_t mSum; uint64_t mSumSq; uint32_t mCnt; uint32_t mWeight; bool mFilter; }; class PerfData { public: PerfData(); void AddValue(uint32_t aValue, bool aShortOnly); uint32_t GetAverage(bool aFiltered); uint32_t GetStdDev(bool aFiltered); private: // Contains filtered data (i.e. times when we think the cache and disk was // not busy) for a longer time. MMA mFilteredAvg; // Contains unfiltered average of few recent values. MMA mShortAvg; }; static StaticMutex sLock; static PerfData sData[LAST] MOZ_GUARDED_BY(sLock); static uint32_t sCacheSlowCnt MOZ_GUARDED_BY(sLock); static uint32_t sCacheNotSlowCnt MOZ_GUARDED_BY(sLock); }; void FreeBuffer(void* aBuf); nsresult ParseAlternativeDataInfo(const char* aInfo, int64_t* _offset, nsACString* _type); void BuildAlternativeDataInfo(const char* aInfo, int64_t aOffset, nsACString& _retval); class CacheFileLock final { public: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CacheFileLock) CacheFileLock() = default; mozilla::Mutex& Lock() MOZ_RETURN_CAPABILITY(mLock) { return mLock; } private: ~CacheFileLock() = default; mozilla::Mutex mLock{"CacheFile.mLock"}; }; } // namespace CacheFileUtils } // namespace net } // namespace mozilla #endif