15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/disk_cache/blockfile/stats.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/format_macros.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/metrics/bucket_ranges.h"
10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/metrics/histogram.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram_samples.h"
12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/metrics/sample_vector.h"
13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/metrics/statistics_recorder.h"
145e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h"
155e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/stringprintf.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int32 kDiskSignature = 0xF01427E0;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct OnDiskStats {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 signature;
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int size;
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int data_sizes[disk_cache::Stats::kDataSizesLength];
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 counters[disk_cache::Stats::MAX_COUNTER];
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)COMPILE_ASSERT(sizeof(OnDiskStats) < 512, needs_more_than_2_blocks);
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the "floor" (as opposed to "ceiling") of log base 2 of number.
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int LogBase2(int32 number) {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int value = static_cast<unsigned int>(number);
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const unsigned int mask[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000};
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const unsigned int s[] = {1, 2, 4, 8, 16};
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int result = 0;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 4; i >= 0; i--) {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (value & mask[i]) {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      value >>= s[i];
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result |= s[i];
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return static_cast<int>(result);
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// WARNING: Add new stats only at the end, or change LoadStats().
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char* kCounterNames[] = {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "Open miss",
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "Open hit",
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "Create miss",
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "Create hit",
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "Resurrect hit",
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "Create error",
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "Trim entry",
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "Doom entry",
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "Doom cache",
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "Invalid entry",
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "Open entries",
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "Max entries",
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "Timer",
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "Read data",
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "Write data",
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "Open rankings",
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "Get rankings",
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "Fatal error",
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "Last report",
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "Last report timer",
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "Doom recent entries",
6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  "unused"
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)COMPILE_ASSERT(arraysize(kCounterNames) == disk_cache::Stats::MAX_COUNTER,
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               update_the_names);
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace disk_cache {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool VerifyStats(OnDiskStats* stats) {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (stats->signature != kDiskSignature)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't want to discard the whole cache every time we have one extra
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // counter; we keep old data if we can.
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (static_cast<unsigned int>(stats->size) > sizeof(*stats)) {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(stats, 0, sizeof(*stats));
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    stats->signature = kDiskSignature;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (static_cast<unsigned int>(stats->size) != sizeof(*stats)) {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t delta = sizeof(*stats) - static_cast<unsigned int>(stats->size);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(reinterpret_cast<char*>(stats) + stats->size, 0, delta);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    stats->size = sizeof(*stats);
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)Stats::Stats() {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Stats::~Stats() {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool Stats::Init(void* data, int num_bytes, Addr address) {
10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  OnDiskStats local_stats;
10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  OnDiskStats* stats = &local_stats;
10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!num_bytes) {
10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    memset(stats, 0, sizeof(local_stats));
10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    local_stats.signature = kDiskSignature;
10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    local_stats.size = sizeof(local_stats);
10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else if (num_bytes >= static_cast<int>(sizeof(*stats))) {
10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    stats = reinterpret_cast<OnDiskStats*>(data);
11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (!VerifyStats(stats))
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return false;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  storage_addr_ = address;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  memcpy(data_sizes_, stats->data_sizes, sizeof(data_sizes_));
11990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  memcpy(counters_, stats->counters, sizeof(counters_));
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Clean up old value.
12290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SetCounter(UNUSED, 0);
12390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return true;
12490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
12590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void Stats::InitSizeHistogram() {
127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Only generate this histogram for the main cache.
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static bool first_time = true;
129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!first_time)
130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  first_time = false;
133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int min = 1;
134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int max = 64 * 1024;
135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int num_buckets = 75;
136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::BucketRanges ranges(num_buckets + 1);
137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::Histogram::InitializeBucketRanges(min, max, &ranges);
138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::HistogramBase* stats_histogram = base::Histogram::FactoryGet(
140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      "DiskCache.SizeStats2", min, max, num_buckets,
141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::HistogramBase::kUmaTargetedHistogramFlag);
142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::SampleVector samples(&ranges);
144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (int i = 0; i < kDataSizesLength; i++) {
145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // This is a good time to fix any inconsistent data. The count should be
146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // always positive, but if it's not, reset the value now.
147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (data_sizes_[i] < 0)
148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      data_sizes_[i] = 0;
149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    samples.Accumulate(GetBucketRange(i) / 1024, data_sizes_[i]);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  stats_histogram->AddSamples(samples);
15390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)int Stats::StorageSize() {
15690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // If we have more than 512 bytes of counters, change kDiskSignature so we
15790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // don't overwrite something else (LoadStats must fail).
15890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  COMPILE_ASSERT(sizeof(OnDiskStats) <= 256 * 2, use_more_blocks);
15990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return 256 * 2;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Stats::ModifyStorageStats(int32 old_size, int32 new_size) {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We keep a counter of the data block size on an array where each entry is
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the adjusted log base 2 of the size. The first entry counts blocks of 256
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // bytes, the second blocks up to 512 bytes, etc. With 20 entries, the last
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // one stores entries of more than 64 MB
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int new_index = GetStatsBucket(new_size);
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int old_index = GetStatsBucket(old_size);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (new_size)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_sizes_[new_index]++;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (old_size)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_sizes_[old_index]--;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Stats::OnEvent(Counters an_event) {
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(an_event >= MIN_COUNTER && an_event < MAX_COUNTER);
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  counters_[an_event]++;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Stats::SetCounter(Counters counter, int64 value) {
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(counter >= MIN_COUNTER && counter < MAX_COUNTER);
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  counters_[counter] = value;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int64 Stats::GetCounter(Counters counter) const {
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(counter >= MIN_COUNTER && counter < MAX_COUNTER);
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return counters_[counter];
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Stats::GetItems(StatsItems* items) {
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::pair<std::string, std::string> item;
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kDataSizesLength; i++) {
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item.first = base::StringPrintf("Size%02d", i);
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item.second = base::StringPrintf("0x%08x", data_sizes_[i]);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    items->push_back(item);
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = MIN_COUNTER; i < MAX_COUNTER; i++) {
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item.first = kCounterNames[i];
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item.second = base::StringPrintf("0x%" PRIx64, counters_[i]);
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    items->push_back(item);
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int Stats::GetHitRatio() const {
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetRatio(OPEN_HIT, OPEN_MISS);
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int Stats::GetResurrectRatio() const {
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetRatio(RESURRECT_HIT, CREATE_HIT);
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Stats::ResetRatios() {
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetCounter(OPEN_HIT, 0);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetCounter(OPEN_MISS, 0);
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetCounter(RESURRECT_HIT, 0);
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetCounter(CREATE_HIT, 0);
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int Stats::GetLargeEntriesSize() {
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int total = 0;
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // data_sizes_[20] stores values between 512 KB and 1 MB (see comment before
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // GetStatsBucket()).
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int bucket = 20; bucket < kDataSizesLength; bucket++)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    total += data_sizes_[bucket] * GetBucketRange(bucket);
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return total;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)int Stats::SerializeStats(void* data, int num_bytes, Addr* address) {
23390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  OnDiskStats* stats = reinterpret_cast<OnDiskStats*>(data);
23490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (num_bytes < static_cast<int>(sizeof(*stats)))
23590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return 0;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  stats->signature = kDiskSignature;
238558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  stats->size = sizeof(*stats);
23990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  memcpy(stats->data_sizes, data_sizes_, sizeof(data_sizes_));
24090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  memcpy(stats->counters, counters_, sizeof(counters_));
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  *address = storage_addr_;
24390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return sizeof(*stats);
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int Stats::GetBucketRange(size_t i) const {
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (i < 2)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return static_cast<int>(1024 * i);
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (i < 12)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return static_cast<int>(2048 * (i - 1));
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (i < 17)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return static_cast<int>(4096 * (i - 11)) + 20 * 1024;
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int n = 64 * 1024;
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (i > static_cast<size_t>(kDataSizesLength)) {
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    i = kDataSizesLength;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  i -= 17;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  n <<= i;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return n;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The array will be filled this way:
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  index      size
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    0       [0, 1024)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    1    [1024, 2048)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    2    [2048, 4096)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    3      [4K, 6K)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//      ...
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   10     [18K, 20K)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   11     [20K, 24K)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   12     [24k, 28K)
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//      ...
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   15     [36k, 40K)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   16     [40k, 64K)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   17     [64K, 128K)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   18    [128K, 256K)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//      ...
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   23      [4M, 8M)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   24      [8M, 16M)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   25     [16M, 32M)
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   26     [32M, 64M)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   27     [64M, ...)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int Stats::GetStatsBucket(int32 size) {
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (size < 1024)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 10 slots more, until 20K.
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (size < 20 * 1024)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return size / 2048 + 1;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 5 slots more, from 20K to 40K.
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (size < 40 * 1024)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return (size - 20 * 1024) / 4096 + 11;
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // From this point on, use a logarithmic scale.
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int result =  LogBase2(size) + 1;
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  COMPILE_ASSERT(kDataSizesLength > 16, update_the_scale);
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result >= kDataSizesLength)
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = kDataSizesLength - 1;
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int Stats::GetRatio(Counters hit, Counters miss) const {
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 ratio = GetCounter(hit) * 100;
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ratio)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ratio /= (GetCounter(hit) + GetCounter(miss));
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return static_cast<int>(ratio);
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace disk_cache
320