diff --git a/emper/io/Stats.cpp b/emper/io/Stats.cpp index 17b7d8f32af71932014c9037752ea16353f5010e..21122bceca4ed048c65f2784d93ccd03d9c7b816 100644 --- a/emper/io/Stats.cpp +++ b/emper/io/Stats.cpp @@ -1,12 +1,16 @@ // SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright © 2020-2021 Florian Fischer, Florian Schmaus +// Copyright © 2020-2022 Florian Fischer, Florian Schmaus #include "io/Stats.hpp" +#include <cerrno> +#include <cstdlib> #include <initializer_list> // for initializer_list #include <iomanip> // for operator<<, setfill, setw #include <string> // for operator<<, to_string #include <utility> // for pair +#include "Debug.hpp" +#include "Future.hpp" #include "io/IoContext.hpp" #include "io/Operation.hpp" // for Operation, operator<<, Operation::RECV #include "lib/math.hpp" @@ -119,6 +123,61 @@ auto operator<<(std::ostream& os, const Stats& s) -> std::ostream& { return os; } +void Stats::record_completion(Operation op, int32_t res, ssize_t partial_completion, size_t exp) { + auto& operation_map = io_uring_completions[op]; + + // Persistent Error + if (res < 0) { + if (partial_completion > 0) { + ATOMIC_INC_RELAXED(operation_map[IncrementalError]); + } else { + ATOMIC_INC_RELAXED(operation_map[ErrorCompletion]); + } + return; + } + + // Make sure exp which is passed as future.len is only > 0 for Futures with a buffer + switch (op) { + case Operation::SEND: + case Operation::RECV: + case Operation::READ: + case Operation::WRITE: + case Operation::WRITEV: + break; + case Operation::TIMEOUT: + exp = ETIME; + break; + default: + exp = 0; + break; + } + + // Full completion + if (!exp || (uint32_t)res == exp) { + ATOMIC_INC_RELAXED(operation_map[FullCompletion]); + return; + } + + // we expect partial completion + if (partial_completion != PartialCompletableFuture::DISABLE_PARTIAL_COMPLETION) { + if ((size_t)(res + partial_completion) < exp) { + ATOMIC_INC_RELAXED(operation_map[PartialResubmission]); + } else { + ATOMIC_INC_RELAXED(operation_map[IncrementalCompletion]); + } + return; + } + + if ((uint32_t)res < exp) { + ATOMIC_INC_RELAXED(operation_map[PartialCompletion]); + return; + } + + LOGW("Unexpected completion case in IoStats"); + LOGW(op << ", " << res << ", " << partial_completion << ", " << exp); + abort(); +} + void Stats::printStats(IoContext* globalIoContext, const std::vector<IoContext*>& workerIoContexts, std::ostream& out) { if (globalIoContext) { diff --git a/emper/io/Stats.hpp b/emper/io/Stats.hpp index cbb02ab9ff7de68a56875ebb3712bd0fd80ff3f6..c828a69bca0936d38399c655733a7aacceae7be3 100644 --- a/emper/io/Stats.hpp +++ b/emper/io/Stats.hpp @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright © 2020-2021 Florian Fischer, Florian Schmaus +// Copyright © 2020-2022 Florian Fischer, Florian Schmaus #pragma once #include <bits/types/struct_iovec.h> // for iovec #include <sys/types.h> // for ssize_t @@ -8,13 +8,11 @@ #include <chrono> // for nanoseconds #include <cstddef> // for size_t #include <cstdint> // for uint64_t, int32_t, uint32_t -#include <cstdlib> // for abort #include <iostream> // for operator<<, basic_ostream, basi... #include <map> // for map, map<>::value_compare #include <vector> #include "CallerEnvironment.hpp" -#include "Debug.hpp" // for LOGW #include "Emper.hpp" // for STATS #include "emper-common.h" // for workerid_t #include "io/Future.hpp" // for PartialCompletableFuture, Write... @@ -156,57 +154,7 @@ class Stats { exp); } - void record_completion(Operation op, int32_t res, ssize_t partial_completion, size_t exp) { - auto& operation_map = io_uring_completions[op]; - - // Persistent Error - if (res < 0) { - if (partial_completion > 0) { - ATOMIC_INC_RELAXED(operation_map[IncrementalError]); - } else { - ATOMIC_INC_RELAXED(operation_map[ErrorCompletion]); - } - return; - } - - // Make sure exp which is passed as future.len is only > 0 for Futures with a buffer - switch (op) { - case Operation::SEND: - case Operation::RECV: - case Operation::READ: - case Operation::WRITE: - case Operation::WRITEV: - break; - default: - exp = 0; - break; - } - - // Full completion - if (!exp || (uint32_t)res == exp) { - ATOMIC_INC_RELAXED(operation_map[FullCompletion]); - return; - } - - // we expect partial completion - if (partial_completion != PartialCompletableFuture::DISABLE_PARTIAL_COMPLETION) { - if ((size_t)(res + partial_completion) < exp) { - ATOMIC_INC_RELAXED(operation_map[PartialResubmission]); - } else { - ATOMIC_INC_RELAXED(operation_map[IncrementalCompletion]); - } - return; - } - - if ((uint32_t)res < exp) { - ATOMIC_INC_RELAXED(operation_map[PartialCompletion]); - return; - } - - LOGW("Unexpected completion case in IoStats"); - LOGW(op << ", " << res << ", " << partial_completion << ", " << exp); - abort(); - } + void record_completion(Operation op, int32_t res, ssize_t partial_completion, size_t exp); // running mean calculation taken from // https://math.stackexchange.com/questions/106700/incremental-averageing