The Pedigree Project 0.1
LoadAverage.h
1/* Copyright (c) 2026, Pedigree Developers. */
2#ifndef PEDIGREE_LOAD_AVERAGE_H
3#define PEDIGREE_LOAD_AVERAGE_H
4
5#include "pedigree/kernel/processor/types.h"
6
9 public:
10 static constexpr uint64_t PeriodNanoseconds = 5000000000ULL;
11 static constexpr uint64_t Scale = 65536;
12
13 void update(uint64_t now, uint32_t active) {
14 if (now < m_LastSample)
15 return;
16 const uint64_t periods = (now - m_LastSample) / PeriodNanoseconds;
17 if (!periods)
18 return;
19 m_LastSample += periods * PeriodNanoseconds;
20 // Rounded exp(-5 / tau) for one, five and fifteen minutes, in 16.16 units.
21 const uint32_t decay[] = {60296, 64453, 65173};
22 for (size_t i = 0; i < 3; ++i) {
23 const uint64_t factor = power(decay[i], periods);
24 const uint64_t target = static_cast<uint64_t>(active) * Scale;
25 m_Values[i] = (m_Values[i] * factor + target * (Scale - factor) + Scale / 2) / Scale;
26 }
27 }
28 void snapshot(uint64_t values[3]) const {
29 for (size_t i = 0; i < 3; ++i)
30 values[i] = m_Values[i];
31 }
32
33 private:
34 static uint64_t power(uint64_t base, uint64_t exponent) {
35 uint64_t result = Scale;
36 // A delayed worker folds missed periods in at most 64 iterations.
37 while (exponent) {
38 if (exponent & 1)
39 result = (result * base + Scale / 2) / Scale;
40 exponent >>= 1;
41 if (exponent)
42 base = (base * base + Scale / 2) / Scale;
43 }
44 return result;
45 }
46 uint64_t m_LastSample = 0;
47 uint64_t m_Values[3] = {};
48};
49
50#endif