Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/md/bcache/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 6 kB image not shown  

Quelle  stats.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
/*
 * bcache stats code
 *
 * Copyright 2012 Google, Inc.
 */


#include "bcache.h"
#include "stats.h"
#include "btree.h"
#include "sysfs.h"

/*
 * We keep absolute totals of various statistics, and addionally a set of three
 * rolling averages.
 *
 * Every so often, a timer goes off and rescales the rolling averages.
 * accounting_rescale[] is how many times the timer has to go off before we
 * rescale each set of numbers; that gets us half lives of 5 minutes, one hour,
 * and one day.
 *
 * accounting_delay is how often the timer goes off - 22 times in 5 minutes,
 * and accounting_weight is what we use to rescale:
 *
 * pow(31 / 32, 22) ~= 1/2
 *
 * So that we don't have to increment each set of numbers every time we (say)
 * get a cache hit, we increment a single atomic_t in acc->collector, and when
 * the rescale function runs it resets the atomic counter to 0 and adds its
 * old value to each of the exported numbers.
 *
 * To reduce rounding error, the numbers in struct cache_stats are all
 * stored left shifted by 16, and scaled back in the sysfs show() function.
 */


static const unsigned int DAY_RESCALE  = 288;
static const unsigned int HOUR_RESCALE  = 12;
static const unsigned int FIVE_MINUTE_RESCALE = 1;
static const unsigned int accounting_delay = (HZ * 300) / 22;
static const unsigned int accounting_weight = 32;

/* sysfs reading/writing */

read_attribute(cache_hits);
read_attribute(cache_misses);
read_attribute(cache_bypass_hits);
read_attribute(cache_bypass_misses);
read_attribute(cache_hit_ratio);
read_attribute(cache_miss_collisions);
read_attribute(bypassed);

SHOW(bch_stats)
{
 struct cache_stats *s =
  container_of(kobj, struct cache_stats, kobj);
#define var(stat)  (s->stat >> 16)
 var_print(cache_hits);
 var_print(cache_misses);
 var_print(cache_bypass_hits);
 var_print(cache_bypass_misses);

 sysfs_print(cache_hit_ratio,
      DIV_SAFE(var(cache_hits) * 100,
        var(cache_hits) + var(cache_misses)));

 var_print(cache_miss_collisions);
 sysfs_hprint(bypassed, var(sectors_bypassed) << 9);
#undef var
 return 0;
}

STORE(bch_stats)
{
 return size;
}

static void bch_stats_release(struct kobject *k)
{
}

static struct attribute *bch_stats_attrs[] = {
 &sysfs_cache_hits,
 &sysfs_cache_misses,
 &sysfs_cache_bypass_hits,
 &sysfs_cache_bypass_misses,
 &sysfs_cache_hit_ratio,
 &sysfs_cache_miss_collisions,
 &sysfs_bypassed,
 NULL
};
ATTRIBUTE_GROUPS(bch_stats);
static KTYPE(bch_stats);

int bch_cache_accounting_add_kobjs(struct cache_accounting *acc,
       struct kobject *parent)
{
 int ret = kobject_add(&acc->total.kobj, parent,
         "stats_total");
 ret = ret ?: kobject_add(&acc->five_minute.kobj, parent,
     "stats_five_minute");
 ret = ret ?: kobject_add(&acc->hour.kobj, parent,
     "stats_hour");
 ret = ret ?: kobject_add(&acc->day.kobj, parent,
     "stats_day");
 return ret;
}

void bch_cache_accounting_clear(struct cache_accounting *acc)
{
 acc->total.cache_hits = 0;
 acc->total.cache_misses = 0;
 acc->total.cache_bypass_hits = 0;
 acc->total.cache_bypass_misses = 0;
 acc->total.cache_miss_collisions = 0;
 acc->total.sectors_bypassed = 0;
}

void bch_cache_accounting_destroy(struct cache_accounting *acc)
{
 kobject_put(&acc->total.kobj);
 kobject_put(&acc->five_minute.kobj);
 kobject_put(&acc->hour.kobj);
 kobject_put(&acc->day.kobj);

 atomic_set(&acc->closing, 1);
 if (timer_delete_sync(&acc->timer))
  closure_return(&acc->cl);
}

/* EWMA scaling */

static void scale_stat(unsigned long *stat)
{
 *stat =  ewma_add(*stat, 0, accounting_weight, 0);
}

static void scale_stats(struct cache_stats *stats, unsigned long rescale_at)
{
 if (++stats->rescale == rescale_at) {
  stats->rescale = 0;
  scale_stat(&stats->cache_hits);
  scale_stat(&stats->cache_misses);
  scale_stat(&stats->cache_bypass_hits);
  scale_stat(&stats->cache_bypass_misses);
  scale_stat(&stats->cache_miss_collisions);
  scale_stat(&stats->sectors_bypassed);
 }
}

static void scale_accounting(struct timer_list *t)
{
 struct cache_accounting *acc = timer_container_of(acc, t, timer);

#define move_stat(name) do {      \
 unsigned int t = atomic_xchg(&acc->collector.name, 0);  \
 t <<= 16;       \
 acc->five_minute.name += t;     \
 acc->hour.name += t;      \
 acc->day.name += t;      \
 acc->total.name += t;      \
while (0)

 move_stat(cache_hits);
 move_stat(cache_misses);
 move_stat(cache_bypass_hits);
 move_stat(cache_bypass_misses);
 move_stat(cache_miss_collisions);
 move_stat(sectors_bypassed);

 scale_stats(&acc->total, 0);
 scale_stats(&acc->day, DAY_RESCALE);
 scale_stats(&acc->hour, HOUR_RESCALE);
 scale_stats(&acc->five_minute, FIVE_MINUTE_RESCALE);

 acc->timer.expires += accounting_delay;

 if (!atomic_read(&acc->closing))
  add_timer(&acc->timer);
 else
  closure_return(&acc->cl);
}

static void mark_cache_stats(struct cache_stat_collector *stats,
        bool hit, bool bypass)
{
 if (!bypass)
  if (hit)
   atomic_inc(&stats->cache_hits);
  else
   atomic_inc(&stats->cache_misses);
 else
  if (hit)
   atomic_inc(&stats->cache_bypass_hits);
  else
   atomic_inc(&stats->cache_bypass_misses);
}

void bch_mark_cache_accounting(struct cache_set *c, struct bcache_device *d,
          bool hit, bool bypass)
{
 struct cached_dev *dc = container_of(d, struct cached_dev, disk);

 mark_cache_stats(&dc->accounting.collector, hit, bypass);
 mark_cache_stats(&c->accounting.collector, hit, bypass);
}

void bch_mark_cache_miss_collision(struct cache_set *c, struct bcache_device *d)
{
 struct cached_dev *dc = container_of(d, struct cached_dev, disk);

 atomic_inc(&dc->accounting.collector.cache_miss_collisions);
 atomic_inc(&c->accounting.collector.cache_miss_collisions);
}

void bch_mark_sectors_bypassed(struct cache_set *c, struct cached_dev *dc,
          int sectors)
{
 atomic_add(sectors, &dc->accounting.collector.sectors_bypassed);
 atomic_add(sectors, &c->accounting.collector.sectors_bypassed);
}

void bch_cache_accounting_init(struct cache_accounting *acc,
          struct closure *parent)
{
 kobject_init(&acc->total.kobj,  &bch_stats_ktype);
 kobject_init(&acc->five_minute.kobj, &bch_stats_ktype);
 kobject_init(&acc->hour.kobj,  &bch_stats_ktype);
 kobject_init(&acc->day.kobj,  &bch_stats_ktype);

 closure_init(&acc->cl, parent);
 timer_setup(&acc->timer, scale_accounting, 0);
 acc->timer.expires = jiffies + accounting_delay;
 add_timer(&acc->timer);
}

Messung V0.5
C=99 H=98 G=98

¤ Dauer der Verarbeitung: 0.13 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.