DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Implementation

Mercurial (409f3966645a)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
/* 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/StaticMutex.h"
#include "mozilla/TimeStamp.h"

class nsILoadContextInfo;

namespace mozilla {
namespace net {
namespace CacheFileUtils {

extern const char *kAltDataKey;

already_AddRefed<nsILoadContextInfo>
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<ValidityPair> 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;
    uint32_t mMissCnt;
  };

  // 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, sHitStats and Telemetry::Accumulated() calls.
  static StaticMutex sLock;

  // Counter of samples that is compared against kTotalSamplesReportLimit.
  static uint32_t sRecordCnt;

  // Hit rate statistics for every cache size range.
  static HitRate sHRStats[kNumOfRanges];
};

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];
  static uint32_t sCacheSlowCnt;
  static uint32_t sCacheNotSlowCnt;
};

void
FreeBuffer(void *aBuf);

nsresult
ParseAlternativeDataInfo(const char *aInfo, int64_t *_offset, nsACString *_type);

void
BuildAlternativeDataInfo(const char *aInfo, int64_t aOffset, nsACString &_retval);

} // namespace CacheFileUtils
} // namespace net
} // namespace mozilla

#endif