内存优化

This commit is contained in:
2026-08-28 11:49:06 +08:00
parent e26f7eb52f
commit fa1e7e24fc
21 changed files with 722 additions and 237 deletions
+7 -4
View File
@@ -65,6 +65,8 @@ Global::Global() : Config() {
SSR::mode_s_logger = new BaseLogger("@/logs/mode_s", MB * size_MB * 10, piece_num);
dsp_logger = new BaseLogger("@/logs/dsp", MB * size_MB, piece_num);
server_logger = new BaseLogger("@/logs/server", MB * size_MB, piece_num);
SSR::parse_pos_call_back = nullptr;
SSR::parse_ok_json = nullptr;
asio_socket::socket_logger->set_redirect([](const BaseLogger::Log_Info& log_info) {
auto msg = "[" + std::string("func") + "~" + log_info.func_pattern + "] " + log_info.log_type.to_string() +
log_info.content;
@@ -77,9 +79,7 @@ Global::Global() : Config() {
});
from_base_json(&j);
#ifdef Cache_Some_Mode_S
auto old_parse_ok_json = SSR::parse_ok_json;
SSR::parse_ok_json = [old_parse_ok_json](Aircraft_Info* aircraft_info, SSR::P_S mode_s_msg, Psc::JSON json) {
old_parse_ok_json(aircraft_info, mode_s_msg, json);
SSR::parse_ok_json = [](Aircraft_Info* aircraft_info, SSR::P_S mode_s_msg, Psc::JSON) {
auto f = static_cast<Aircraft*>(aircraft_info);
f->add_msg_limit(mode_s_msg);
};
@@ -88,7 +88,10 @@ Global::Global() : Config() {
auto src = std::dynamic_pointer_cast<Data_Source>(msg->source);
Mode_S_Statistic_Data* ss = &src->mode_s_statistic;
ss->add_cpr_error(t, err_type);
SSR::mode_s_logger->debug("CPR/" + to_string(t) + "/" + to_string(err_type), {}, log);
if (err_type == SSR::CPR_Ret_Type::Speed_Error || err_type == SSR::CPR_Ret_Type::Inter_Error ||
err_type == SSR::CPR_Ret_Type::Time_Space_Too_Long ||
err_type == SSR::CPR_Ret_Type::Out_of_Maximum_Detection_Range)
SSR::mode_s_logger->debug("CPR/" + to_string(t) + "/" + to_string(err_type), {}, log);
};
// 处理错误
SSR::parse_call_back = [this](SSR::Parse_Call_Back_Type type, SSR::Aircraft_Info* info, std::string_view field_name,
@@ -0,0 +1,227 @@
#include "Memory_Monitor.h"
#include <algorithm>
#include <chrono>
#include <cmath>
#include <fstream>
#include <iterator>
#include <mimalloc.h>
#include <sstream>
#include "Memory_Resource.h"
namespace {
constexpr std::uint64_t kibibyte = 1024;
constexpr std::uint64_t mebibyte = 1024 * kibibyte;
constexpr std::size_t history_capacity = 600;
constexpr std::size_t response_history_capacity = 120;
constexpr std::uint64_t growth_warmup_ms = 10 * 60 * 1000;
constexpr std::uint64_t growth_window_ms = 15 * 60 * 1000;
constexpr std::uint64_t recent_growth_window_ms = 5 * 60 * 1000;
constexpr std::uint64_t minimum_growth_window_ms = 10 * 60 * 1000;
constexpr std::uint64_t minimum_recent_growth_window_ms = 4 * 60 * 1000;
std::uint64_t now_milliseconds() {
return static_cast<std::uint64_t>(std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch()).count());
}
std::uint64_t parse_kibibytes(std::string_view line) {
const auto separator = line.find(':');
if (separator == std::string_view::npos)
return 0;
std::uint64_t value{};
std::istringstream stream(std::string(line.substr(separator + 1)));
stream >> value;
return value * kibibyte;
}
#if defined(ECAP_TARGET_LINUX)
void read_linux_process_memory(Process_Memory_Snapshot& result) {
std::ifstream stream("/proc/self/status");
std::string line;
while (std::getline(stream, line)) {
if (line.starts_with("VmRSS:"))
result.rss_bytes = parse_kibibytes(line);
else if (line.starts_with("VmHWM:"))
result.peak_rss_bytes = parse_kibibytes(line);
else if (line.starts_with("RssAnon:"))
result.anonymous_rss_bytes = parse_kibibytes(line);
else if (line.starts_with("RssFile:"))
result.file_rss_bytes = parse_kibibytes(line);
else if (line.starts_with("RssShmem:"))
result.shared_rss_bytes = parse_kibibytes(line);
else if (line.starts_with("VmSize:"))
result.virtual_bytes = parse_kibibytes(line);
else if (line.starts_with("VmSwap:"))
result.swap_bytes = parse_kibibytes(line);
}
}
void read_linux_system_memory(Process_Memory_Snapshot& result) {
std::ifstream stream("/proc/meminfo");
std::string line;
while (std::getline(stream, line)) {
if (line.starts_with("MemTotal:"))
result.system_total_bytes = parse_kibibytes(line);
else if (line.starts_with("MemAvailable:"))
result.system_available_bytes = parse_kibibytes(line);
}
}
#endif
struct Growth_Trend {
std::int64_t bytes_per_hour{};
std::uint64_t window_ms{};
};
template <typename Getter>
Growth_Trend growth_trend(const std::pmr::deque<Process_Memory_Snapshot>& history, Getter getter,
std::uint64_t maximum_window_ms) {
if (history.size() < 2)
return {};
const auto latest_timestamp = history.back().timestamp_ms;
const auto warmup_end = history.front().timestamp_ms + growth_warmup_ms;
if (latest_timestamp <= warmup_end)
return {};
const auto tail_start = latest_timestamp > maximum_window_ms ? latest_timestamp - maximum_window_ms : 0;
const auto analysis_start = std::max(warmup_end, tail_start);
const auto first = std::find_if(history.begin(), history.end(), [analysis_start](const auto& sample) {
return sample.timestamp_ms >= analysis_start;
});
if (first == history.end() || std::next(first) == history.end())
return {};
const auto origin = first->timestamp_ms;
long double sum_x = 0;
long double sum_y = 0;
for (auto iter = first; iter != history.end(); ++iter) {
const auto& sample = *iter;
sum_x += static_cast<long double>(sample.timestamp_ms - origin) / 1000.0L;
sum_y += static_cast<long double>(getter(sample));
}
const auto count = static_cast<long double>(std::distance(first, history.end()));
const auto mean_x = sum_x / count;
const auto mean_y = sum_y / count;
long double numerator = 0;
long double denominator = 0;
for (auto iter = first; iter != history.end(); ++iter) {
const auto& sample = *iter;
const auto x = static_cast<long double>(sample.timestamp_ms - origin) / 1000.0L - mean_x;
const auto y = static_cast<long double>(getter(sample)) - mean_y;
numerator += x * y;
denominator += x * x;
}
if (denominator == 0)
return {};
return {static_cast<std::int64_t>(numerator / denominator * 3600.0L), latest_timestamp - origin};
}
Psc::JSON snapshot_json(const Process_Memory_Snapshot& value) {
Psc::JSON result = Psc::JSON::object();
result.append({"timestamp_ms", value.timestamp_ms});
result.append({"rss_bytes", value.rss_bytes});
result.append({"peak_rss_bytes", value.peak_rss_bytes});
result.append({"anonymous_rss_bytes", value.anonymous_rss_bytes});
result.append({"file_rss_bytes", value.file_rss_bytes});
result.append({"shared_rss_bytes", value.shared_rss_bytes});
result.append({"virtual_bytes", value.virtual_bytes});
result.append({"swap_bytes", value.swap_bytes});
result.append({"commit_bytes", value.commit_bytes});
result.append({"peak_commit_bytes", value.peak_commit_bytes});
result.append({"system_total_bytes", value.system_total_bytes});
result.append({"system_available_bytes", value.system_available_bytes});
result.append({"page_faults", value.page_faults});
result.append({"allocator_live_bytes", value.allocator_live_bytes});
result.append({"allocator_peak_live_bytes", value.allocator_peak_live_bytes});
result.append({"pmr_live_bytes", value.pmr_live_bytes});
result.append({"pmr_peak_live_bytes", value.pmr_peak_live_bytes});
return result;
}
}
Memory_Monitor::Memory_Monitor() : history_(server_memory_resource()) {
}
Memory_Monitor& Memory_Monitor::instance() {
static Memory_Monitor monitor;
return monitor;
}
void Memory_Monitor::sample() {
Process_Memory_Snapshot result;
result.timestamp_ms = now_milliseconds();
std::size_t elapsed{};
std::size_t user{};
std::size_t system{};
std::size_t rss{};
std::size_t peak_rss{};
std::size_t commit{};
std::size_t peak_commit{};
std::size_t page_faults{};
mi_process_info(&elapsed, &user, &system, &rss, &peak_rss, &commit, &peak_commit, &page_faults);
result.rss_bytes = rss;
result.peak_rss_bytes = peak_rss;
result.commit_bytes = commit;
result.peak_commit_bytes = peak_commit;
result.page_faults = page_faults;
result.system_total_bytes = Psc::get_system_memory();
#if defined(ECAP_TARGET_LINUX)
read_linux_process_memory(result);
read_linux_system_memory(result);
#endif
const auto allocator = server_allocator_snapshot();
result.allocator_live_bytes = allocator.live_bytes;
result.allocator_peak_live_bytes = allocator.peak_live_bytes;
result.pmr_live_bytes = allocator.pmr_live_bytes;
result.pmr_peak_live_bytes = allocator.pmr_peak_live_bytes;
std::lock_guard lock(mutex_);
history_.push_back(result);
if (history_.size() > history_capacity)
history_.pop_front();
}
Psc::JSON Memory_Monitor::state_json() const {
std::lock_guard lock(mutex_);
Psc::JSON result = Psc::JSON::object();
if (history_.empty())
return result;
const auto& latest = history_.back();
const auto window_ms = latest.timestamp_ms - history_.front().timestamp_ms;
const auto rss_growth = growth_trend(history_, [](const auto& sample) { return sample.rss_bytes; }, growth_window_ms);
const auto anonymous_growth = growth_trend(history_, [](const auto& sample) { return sample.anonymous_rss_bytes; },
growth_window_ms);
const auto recent_anonymous_growth = growth_trend(history_, [](const auto& sample) {
return sample.anonymous_rss_bytes;
}, recent_growth_window_ms);
const auto allocator_growth = growth_trend(history_, [](const auto& sample) {
return sample.allocator_live_bytes;
}, growth_window_ms);
const auto process_percent = latest.system_total_bytes == 0 ? 0.0 :
static_cast<double>(latest.rss_bytes) * 100.0 / static_cast<double>(latest.system_total_bytes);
const auto available_percent = latest.system_total_bytes == 0 ? 0.0 :
static_cast<double>(latest.system_available_bytes) * 100.0 / static_cast<double>(latest.system_total_bytes);
std::string pressure = "normal";
if (process_percent >= 75.0 || (available_percent > 0.0 && available_percent <= 5.0))
pressure = "critical";
else if (process_percent >= 50.0 || (available_percent > 0.0 && available_percent <= 15.0))
pressure = "warning";
const bool sustained_growth = anonymous_growth.window_ms >= minimum_growth_window_ms &&
recent_anonymous_growth.window_ms >= minimum_recent_growth_window_ms &&
anonymous_growth.bytes_per_hour >= static_cast<std::int64_t>(16 * mebibyte) &&
recent_anonymous_growth.bytes_per_hour >= static_cast<std::int64_t>(16 * mebibyte);
const auto allocator = server_allocator_snapshot();
result.append({"allocator", "mimalloc"});
result.append({"allocator_version", allocator.allocator_version});
result.append({"current", snapshot_json(latest)});
result.append({"process_memory_percent", process_percent});
result.append({"system_available_percent", available_percent});
result.append({"pressure", pressure});
result.append({"sample_count", history_.size()});
result.append({"window_seconds", window_ms / 1000});
result.append({"growth_window_seconds", anonymous_growth.window_ms / 1000});
result.append({"rss_growth_bytes_per_hour", rss_growth.bytes_per_hour});
result.append({"anonymous_growth_bytes_per_hour", anonymous_growth.bytes_per_hour});
result.append({"recent_anonymous_growth_bytes_per_hour", recent_anonymous_growth.bytes_per_hour});
result.append({"allocator_growth_bytes_per_hour", allocator_growth.bytes_per_hour});
result.append({"sustained_growth", sustained_growth});
result.append({"allocated_bytes_total", allocator.allocated_bytes_total});
result.append({"allocation_count", allocator.allocation_count});
result.append({"deallocation_count", allocator.deallocation_count});
result.append({"pmr_allocated_bytes_total", allocator.pmr_allocated_bytes_total});
result.append({"pmr_allocation_count", allocator.pmr_allocation_count});
result.append({"pmr_deallocation_count", allocator.pmr_deallocation_count});
Psc::JSON history = Psc::JSON::array();
const auto stride = std::max<std::size_t>(1, (history_.size() + response_history_capacity - 1) / response_history_capacity);
for (std::size_t index = 0; index < history_.size(); index += stride)
history.append(snapshot_json(history_[index]));
if ((history_.size() - 1) % stride != 0)
history.append(snapshot_json(history_.back()));
result.append({"history", history});
return result;
}
@@ -0,0 +1,35 @@
#pragma once
#include <cstdint>
#include <deque>
#include <memory_resource>
#include <mutex>
#include "../global_include.h"
struct Process_Memory_Snapshot {
std::uint64_t timestamp_ms{};
std::uint64_t rss_bytes{};
std::uint64_t peak_rss_bytes{};
std::uint64_t anonymous_rss_bytes{};
std::uint64_t file_rss_bytes{};
std::uint64_t shared_rss_bytes{};
std::uint64_t virtual_bytes{};
std::uint64_t swap_bytes{};
std::uint64_t commit_bytes{};
std::uint64_t peak_commit_bytes{};
std::uint64_t system_total_bytes{};
std::uint64_t system_available_bytes{};
std::uint64_t page_faults{};
std::uint64_t allocator_live_bytes{};
std::uint64_t allocator_peak_live_bytes{};
std::uint64_t pmr_live_bytes{};
std::uint64_t pmr_peak_live_bytes{};
};
class Memory_Monitor {
public:
static Memory_Monitor& instance();
void sample();
Psc::JSON state_json() const;
private:
Memory_Monitor();
mutable std::mutex mutex_;
std::pmr::deque<Process_Memory_Snapshot> history_;
};
@@ -0,0 +1,171 @@
#include "Memory_Resource.h"
#include <atomic>
#include <mimalloc.h>
#include <new>
namespace {
struct Allocation_Counters {
std::atomic<std::uint64_t> live_bytes{};
std::atomic<std::uint64_t> peak_live_bytes{};
std::atomic<std::uint64_t> allocated_bytes_total{};
std::atomic<std::uint64_t> allocation_count{};
std::atomic<std::uint64_t> deallocation_count{};
std::atomic<std::uint64_t> pmr_live_bytes{};
std::atomic<std::uint64_t> pmr_peak_live_bytes{};
std::atomic<std::uint64_t> pmr_allocated_bytes_total{};
std::atomic<std::uint64_t> pmr_allocation_count{};
std::atomic<std::uint64_t> pmr_deallocation_count{};
};
constinit Allocation_Counters allocation_counters;
void update_peak(std::atomic<std::uint64_t>& peak, std::uint64_t value) {
auto current = peak.load(std::memory_order_relaxed);
while (current < value && !peak.compare_exchange_weak(current, value, std::memory_order_relaxed)) {
}
}
void record_allocation(void* pointer, bool pmr) {
if (pointer == nullptr)
return;
const auto bytes = static_cast<std::uint64_t>(mi_usable_size(pointer));
const auto live = allocation_counters.live_bytes.fetch_add(bytes, std::memory_order_relaxed) + bytes;
allocation_counters.allocated_bytes_total.fetch_add(bytes, std::memory_order_relaxed);
allocation_counters.allocation_count.fetch_add(1, std::memory_order_relaxed);
update_peak(allocation_counters.peak_live_bytes, live);
if (!pmr)
return;
const auto pmr_live = allocation_counters.pmr_live_bytes.fetch_add(bytes, std::memory_order_relaxed) + bytes;
allocation_counters.pmr_allocated_bytes_total.fetch_add(bytes, std::memory_order_relaxed);
allocation_counters.pmr_allocation_count.fetch_add(1, std::memory_order_relaxed);
update_peak(allocation_counters.pmr_peak_live_bytes, pmr_live);
}
void record_deallocation(void* pointer, bool pmr) {
if (pointer == nullptr)
return;
const auto bytes = static_cast<std::uint64_t>(mi_usable_size(pointer));
allocation_counters.live_bytes.fetch_sub(bytes, std::memory_order_relaxed);
allocation_counters.deallocation_count.fetch_add(1, std::memory_order_relaxed);
if (!pmr)
return;
allocation_counters.pmr_live_bytes.fetch_sub(bytes, std::memory_order_relaxed);
allocation_counters.pmr_deallocation_count.fetch_add(1, std::memory_order_relaxed);
}
void free_tracked(void* pointer) noexcept {
record_deallocation(pointer, false);
mi_free(pointer);
}
class Mimalloc_Memory_Resource final : public std::pmr::memory_resource {
protected:
void* do_allocate(std::size_t bytes, std::size_t alignment) override {
auto pointer = mi_new_aligned(bytes, alignment);
record_allocation(pointer, true);
return pointer;
}
void do_deallocate(void* pointer, std::size_t, std::size_t) override {
record_deallocation(pointer, true);
mi_free(pointer);
}
bool do_is_equal(const std::pmr::memory_resource& other) const noexcept override {
return this == &other;
}
};
}
void* operator new(std::size_t bytes) {
auto pointer = mi_new(bytes);
record_allocation(pointer, false);
return pointer;
}
void* operator new[](std::size_t bytes) {
auto pointer = mi_new(bytes);
record_allocation(pointer, false);
return pointer;
}
void* operator new(std::size_t bytes, const std::nothrow_t&) noexcept {
auto pointer = mi_new_nothrow(bytes);
record_allocation(pointer, false);
return pointer;
}
void* operator new[](std::size_t bytes, const std::nothrow_t&) noexcept {
auto pointer = mi_new_nothrow(bytes);
record_allocation(pointer, false);
return pointer;
}
void operator delete(void* pointer) noexcept {
free_tracked(pointer);
}
void operator delete[](void* pointer) noexcept {
free_tracked(pointer);
}
void operator delete(void* pointer, const std::nothrow_t&) noexcept {
free_tracked(pointer);
}
void operator delete[](void* pointer, const std::nothrow_t&) noexcept {
free_tracked(pointer);
}
void operator delete(void* pointer, std::size_t) noexcept {
free_tracked(pointer);
}
void operator delete[](void* pointer, std::size_t) noexcept {
free_tracked(pointer);
}
void* operator new(std::size_t bytes, std::align_val_t alignment) {
auto pointer = mi_new_aligned(bytes, static_cast<std::size_t>(alignment));
record_allocation(pointer, false);
return pointer;
}
void* operator new[](std::size_t bytes, std::align_val_t alignment) {
auto pointer = mi_new_aligned(bytes, static_cast<std::size_t>(alignment));
record_allocation(pointer, false);
return pointer;
}
void* operator new(std::size_t bytes, std::align_val_t alignment, const std::nothrow_t&) noexcept {
auto pointer = mi_new_aligned_nothrow(bytes, static_cast<std::size_t>(alignment));
record_allocation(pointer, false);
return pointer;
}
void* operator new[](std::size_t bytes, std::align_val_t alignment, const std::nothrow_t&) noexcept {
auto pointer = mi_new_aligned_nothrow(bytes, static_cast<std::size_t>(alignment));
record_allocation(pointer, false);
return pointer;
}
void operator delete(void* pointer, std::align_val_t) noexcept {
free_tracked(pointer);
}
void operator delete[](void* pointer, std::align_val_t) noexcept {
free_tracked(pointer);
}
void operator delete(void* pointer, std::size_t, std::align_val_t) noexcept {
free_tracked(pointer);
}
void operator delete[](void* pointer, std::size_t, std::align_val_t) noexcept {
free_tracked(pointer);
}
void operator delete(void* pointer, std::align_val_t, const std::nothrow_t&) noexcept {
free_tracked(pointer);
}
void operator delete[](void* pointer, std::align_val_t, const std::nothrow_t&) noexcept {
free_tracked(pointer);
}
std::pmr::memory_resource* server_memory_resource() {
static Mimalloc_Memory_Resource resource;
return &resource;
}
void initialize_server_memory_resource() {
mi_process_init();
std::pmr::set_default_resource(server_memory_resource());
}
Server_Allocator_Snapshot server_allocator_snapshot() {
Server_Allocator_Snapshot result;
result.live_bytes = allocation_counters.live_bytes.load(std::memory_order_relaxed);
result.peak_live_bytes = allocation_counters.peak_live_bytes.load(std::memory_order_relaxed);
result.allocated_bytes_total = allocation_counters.allocated_bytes_total.load(std::memory_order_relaxed);
result.allocation_count = allocation_counters.allocation_count.load(std::memory_order_relaxed);
result.deallocation_count = allocation_counters.deallocation_count.load(std::memory_order_relaxed);
result.pmr_live_bytes = allocation_counters.pmr_live_bytes.load(std::memory_order_relaxed);
result.pmr_peak_live_bytes = allocation_counters.pmr_peak_live_bytes.load(std::memory_order_relaxed);
result.pmr_allocated_bytes_total = allocation_counters.pmr_allocated_bytes_total.load(std::memory_order_relaxed);
result.pmr_allocation_count = allocation_counters.pmr_allocation_count.load(std::memory_order_relaxed);
result.pmr_deallocation_count = allocation_counters.pmr_deallocation_count.load(std::memory_order_relaxed);
result.allocator_version = mi_version();
return result;
}
void collect_server_memory(bool force) {
mi_collect(force);
}
@@ -0,0 +1,21 @@
#pragma once
#include <cstddef>
#include <cstdint>
#include <memory_resource>
struct Server_Allocator_Snapshot {
std::uint64_t live_bytes{};
std::uint64_t peak_live_bytes{};
std::uint64_t allocated_bytes_total{};
std::uint64_t allocation_count{};
std::uint64_t deallocation_count{};
std::uint64_t pmr_live_bytes{};
std::uint64_t pmr_peak_live_bytes{};
std::uint64_t pmr_allocated_bytes_total{};
std::uint64_t pmr_allocation_count{};
std::uint64_t pmr_deallocation_count{};
int allocator_version{};
};
void initialize_server_memory_resource();
std::pmr::memory_resource* server_memory_resource();
Server_Allocator_Snapshot server_allocator_snapshot();
void collect_server_memory(bool force);
+5 -6
View File
@@ -2,6 +2,7 @@
#define BIN_Msg_Buffer_H
#include "../global_include.h"
#include <memory_resource>
#include <stack>
#include <string_view>
@@ -38,20 +39,18 @@ protected:
};
struct BIN_Msg_Buffer {
using Batch = std::pmr::vector<std::pmr::string>;
void push(std::string_view msg);
const std::vector<std::string *> &get_all();
Batch take_all();
std::atomic<size_t> mode_s_msg_num{};
std::atomic<size_t> mode_other_msg_num{};
BIN_Msg_Buffer();
Psc::JSON state_json();
protected:
std::mutex mtx;
std::vector<std::string *> msg_list_cache;
std::vector<std::string *> msg_list;
Batch msg_list_cache;
size_t cache_bytes{};
size_t dispatch_batches{};
size_t dispatch_bytes{};
size_t high_water_messages{};
size_t high_water_bytes{};
+4 -16
View File
@@ -136,13 +136,11 @@ asio::awaitable<void> Data_Feed::loop_coro() {
auto feed = this;
auto co = Coro::instance();
auto& mode_acs = Global::instance()->mode_acs;
auto& cfg = mode_acs.data_feed_config;
auto& pool = cfg.pool_;
while (feed->running()) {
if (data_feed_debug) {
std::cout << std::format("{} feed loop begin {}\n", key, thread_id_str());
}
std::vector<std::string> messages;
BIN_Msg_Buffer::Batch messages;
{
if (!feed->running() || !feed->registered()) {
break;
@@ -150,26 +148,17 @@ asio::awaitable<void> Data_Feed::loop_coro() {
co_await feed->handle_in_loop_coro();
auto s_num = feed->msg_buffer.mode_s_msg_num.load();
auto other_num = feed->msg_buffer.mode_other_msg_num.load();
const std::vector<std::string*>& all = feed->msg_buffer.get_all();
Pool_Guard pg(&pool, all);
messages = feed->msg_buffer.take_all();
const auto [num, monitor_msg_live] = mode_acs.settings.read([](const auto& value) {
return std::pair{value.report_data_feed_msg_mum, value.monitor_msg_live};
});
if (monitor_msg_live && num != 0 && all.size() > num && too_many_msg_limit.test()) {
if (monitor_msg_live && num != 0 && messages.size() > num && too_many_msg_limit.test()) {
std::ostringstream oss;
oss << "feed_key:" << feed->key << " ";
oss << "recv_s:" << s_num << " ";
oss << "recv_other:" << other_num << " ";
std::cout << oss.str() << std::endl;
}
messages.reserve(all.size());
for (const auto* str : all) {
if (!str || str->empty()) {
std::cout << "empty feed message:" << feed->key << std::endl;
continue;
}
messages.emplace_back(*str);
}
}
if (messages.empty()) {
co_await co->sleep_for(std::chrono::milliseconds(10));
@@ -186,7 +175,7 @@ asio::awaitable<void> Data_Feed::loop_coro() {
if (data_feed_debug) {
std::cout << std::format("{} before send {}\n", key, thread_id_str());
}
co_await feed->send_coro(msg);
co_await feed->send_coro(std::string_view(msg.data(), msg.size()));
if (data_feed_debug) {
std::cout << std::format("{} after send {}\n", key, thread_id_str());
}
@@ -292,7 +281,6 @@ asio::awaitable<void> Data_Source::loop_coro() {
ask_sleep = false;
}
}
std::cout << std::flush;
}
std::cout << std::format("{} source loop exit {}\n", key, thread_id_str());
co_return;
+14 -7
View File
@@ -5,6 +5,7 @@
#include <cctype>
#include <string_view>
#include "Global.h"
#include "Memory_Monitor.h"
#include "Performance_Monitor.h"
namespace {
constexpr std::size_t kMaxLogRequestBodySize = 8 * 1024;
@@ -174,6 +175,7 @@ void Global::init_web_server() {
add_path(R"(^/map3d)");
add_path(R"(^/aircraftlist)");
add_path(R"(^/topology)");
add_path(R"(^/memory)");
drogon::app().registerHandlerViaRegex(
R"(^/ui(/.*)?$)",
[return_file](const drogon::HttpRequestPtr& req, std::function<void(const drogon::HttpResponsePtr&)>&& callback) {
@@ -185,7 +187,7 @@ void Global::init_web_server() {
}
auto is_spa_path = [](std::string_view value) {
return value == "/" || value == "/map" || value == "/map3d" || value == "/settings" ||
value == "/aircraftlist" || value == "/topology";
value == "/aircraftlist" || value == "/topology" || value == "/memory";
};
if (is_spa_path(rp)) {
path += "/index.html";
@@ -196,12 +198,6 @@ void Global::init_web_server() {
callback(return_file(path));
});
State_Report::instance();
svr.Get(R"(/get_debug_info)", [](HTTP_Param) {
JSON arr = JSON::array();
auto& sp = Global::instance()->mode_acs.data_feed_config.pool_;
arr.append(JSON::object({{"remain_size", sp.remain_size()}, {"free_size", sp.free_size()}}));
res->setBody(arr.to_json_string("", "\n", ""));
});
database_server(this);
external_resources_manager.server(this);
mode_acs.server(this);
@@ -389,6 +385,17 @@ void Global::init_web_server() {
// ret.append({"基站信息", base_station.to_Json()});
res->setBody(warp(ret).to_json_string());
});
svr.Post(api + "memory_status", [this](HTTP_Param) {
auto result = Memory_Monitor::instance().state_json();
JSON sources = JSON::object();
for (const auto& source : mode_acs.data_source_config.map.list()) {
if (const auto dll_source = dynamic_cast<Dll_Data_Source*>(source.get()))
sources.append({source->key, dll_source->backlog_state_json()});
}
result.append({"dll_sources", sources});
result.append({"iq_dropped_frames_total", dsp_config.iq_memory_buffer.dropped()});
res->setBody(warp(result).to_json_string());
});
svr.Post(api + "version", [this](HTTP_Param) {
auto ret = JSON::object();
ret.append({"version", version});