Preserve recorded traffic rates as the history window advances

This commit is contained in:
evgeny committed 2026-10-30 21:30:52 +01:00
1 parent 8e6efd2b00
commit 476ab1b840
3 files changed
+31 -10

No files matched your search

+2
View File
@@ -46,6 +46,8 @@ diagnostic_wire_tx_bytes увеличивается только при прин
его очередь; это не подтверждение фактического выхода в эфир или доставки пиру.
Байт/с = разность счётчиков / время за последние <=1с. Переключение peer/epoch,
падение счётчика и пробел измерений >150мс не образуют скачок скорости.
Скорость вычисляется при записи измерения и хранится вместе с ним. При сдвиге
графика старые значения не пересчитываются: левый край не теряет свою предысторию.
Снимки и ресурсы
---------------
+13 -10
View File
@@ -30,7 +30,8 @@ public:
p.rendered_samples += samples; p.missing_samples += std::min(samples, missing);
b.bins[std::min(CALL_HISTORY_BINS - 1, std::max(0, depth) / CALL_HISTORY_BIN_MS)] += samples;
}
// Все значения принадлежат одному снимку uasync; никаких чтений живых очередей из UI.
// Все значения принадлежат одному снимку uasync. Скорость фиксируется здесь: уход старых
// точек из видимого окна не должен менять секундное среднее уже записанных измерений.
void transmit(const call_history_tx& p) {
unsigned index = (txNext + CALL_HISTORY_POINTS - 1) % CALL_HISTORY_POINTS;
if (txUsed && p.at_ms < tx[index].at_ms) {
@@ -41,6 +42,17 @@ public:
txUsed = std::min(txUsed + 1, (unsigned)CALL_HISTORY_POINTS);
}
tx[index] = p;
auto& current = tx[index]; current.wire_bytes_per_sec = -1;
unsigned first = index;
for (unsigned i = 1; i < txUsed && current.peer_id; ++i) {
unsigned previous = (first + CALL_HISTORY_POINTS - 1) % CALL_HISTORY_POINTS;
if (tx[previous].peer_id != current.peer_id || tx[previous].tx_epoch != current.tx_epoch
|| current.at_ms - tx[previous].at_ms > 1000 || tx[first].at_ms - tx[previous].at_ms > 150
|| tx[first].wire_tx_bytes < tx[previous].wire_tx_bytes) break;
first = previous;
}
if (first != index && current.at_ms > tx[first].at_ms)
current.wire_bytes_per_sec = (current.wire_tx_bytes - tx[first].wire_tx_bytes) * 1000.0 / (current.at_ms - tx[first].at_ms);
}
// out — независимая копия. Пустые/старые участки не интерполируются и не становятся нулевыми измерениями.
void snapshot(uint64_t now, call_audio_history& out) const {
@@ -59,14 +71,5 @@ public:
const auto& p = tx[(txNext + CALL_HISTORY_POINTS - txUsed + i) % CALL_HISTORY_POINTS];
if (p.at_ms <= now && now - p.at_ms < CALL_HISTORY_MS) out.tx[out.tx_count++] = p;
}
for (unsigned i = 0; i < out.tx_count; ++i) {
auto& p = out.tx[i]; unsigned first = i; p.wire_bytes_per_sec = -1;
while (first && p.peer_id && out.tx[first - 1].peer_id == p.peer_id && out.tx[first - 1].tx_epoch == p.tx_epoch
&& p.at_ms - out.tx[first - 1].at_ms <= 1000 && out.tx[first].at_ms - out.tx[first - 1].at_ms <= 150)
--first;
const auto& previous = out.tx[first];
if (first < i && p.at_ms > previous.at_ms && p.wire_tx_bytes >= previous.wire_tx_bytes)
p.wire_bytes_per_sec = (p.wire_tx_bytes - previous.wire_tx_bytes) * 1000.0 / (p.at_ms - previous.at_ms);
}
}
};
+16
View File
@@ -229,6 +229,22 @@ static void test_audio_history() {
CHECK(snapshot.tx[22].wire_bytes_per_sec == 2000);
traffic.transmit({2400, 0, 0, 0, 43, 8, 900200}); traffic.snapshot(2400, snapshot);
CHECK(snapshot.tx[23].wire_bytes_per_sec == -1); // Пропущенные измерения не интерполируются.
traffic.transmit({2450, 0, 0, 0, 43, 8, 10}); traffic.snapshot(2450, snapshot);
CHECK(snapshot.tx[24].wire_bytes_per_sec == -1);
traffic.transmit({2500, 0, 0, 0, 43, 8, 110}); traffic.snapshot(2500, snapshot);
CHECK(snapshot.tx[25].wire_bytes_per_sec == 2000); // После сброса счётчика начинаем новый интервал.
CallHistoryStore scrolling;
uint64_t sent = 0;
for (unsigned i = 0; i <= 700; ++i) {
if (i % 7 == 0) sent += 700;
scrolling.transmit({i * 50, 0, 0, 0, 42, 7, sent});
}
scrolling.snapshot(35000, snapshot);
const auto retained = snapshot.tx[40]; // Точка с полным секундным средним, после оборота кольца.
CHECK(retained.wire_bytes_per_sec > 0);
scrolling.snapshot(retained.at_ms + CALL_HISTORY_MS - 1, snapshot);
CHECK(snapshot.tx[0].at_ms == retained.at_ms);
CHECK(snapshot.tx[0].wire_bytes_per_sec == retained.wire_bytes_per_sec); // Левый край не переписывает прошлое.
puts("audio history: time weights, startup exclusion, gaps, overflow bin and ring expiry PASS");
}