fix(stats): Do not crash upon issuing mem stats (#2169)

* fix(stats): Do not crash upon issuing `mem stats`

The reason for the crash is that we can't use a mutex while iterating
connections. It uses a non-Fiber `Await()`, and it also has a fiber
atomic guard.

Instead use the common trick of allocating per-thread data and aggregate
afterward.

* Use pool size
This commit is contained in:
Shahar Mike 2023-11-14 13:12:13 +02:00 committed by GitHub
parent 09415c4f57
commit 87ee4f486c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -165,32 +165,39 @@ struct ConnectionMemoryUsage {
};
ConnectionMemoryUsage GetConnectionMemoryUsage(ServerFamily* server) {
Mutex mu;
ConnectionMemoryUsage mem ABSL_GUARDED_BY(mu);
vector<ConnectionMemoryUsage> mems(shard_set->pool()->size());
for (auto* listener : server->GetListeners()) {
listener->TraverseConnections([&](unsigned thread_index, util::Connection* conn) {
auto* dfly_conn = static_cast<facade::Connection*>(conn);
auto* cntx = static_cast<ConnectionContext*>(dfly_conn->cntx());
lock_guard lock(mu);
if (cntx->replication_flow == nullptr) {
mem.connection_count++;
mem.connections_memory += dfly_conn->GetMemoryUsage();
mems[thread_index].connection_count++;
mems[thread_index].connections_memory += dfly_conn->GetMemoryUsage();
} else {
mem.replication_connection_count++;
mem.replication_memory += dfly_conn->GetMemoryUsage();
mems[thread_index].replication_connection_count++;
mems[thread_index].replication_memory += dfly_conn->GetMemoryUsage();
}
if (cntx != nullptr) {
mem.pipelined_bytes += cntx->conn_state.exec_info.body.capacity() * sizeof(StoredCmd);
mems[thread_index].pipelined_bytes +=
cntx->conn_state.exec_info.body.capacity() * sizeof(StoredCmd);
for (const auto& pipeline : cntx->conn_state.exec_info.body) {
mem.pipelined_bytes += pipeline.UsedHeapMemory();
mems[thread_index].pipelined_bytes += pipeline.UsedHeapMemory();
}
}
});
}
ConnectionMemoryUsage mem;
for (const auto& m : mems) {
mem.connection_count += m.connection_count;
mem.pipelined_bytes += m.pipelined_bytes;
mem.connections_memory += m.connections_memory;
mem.replication_connection_count += m.replication_connection_count;
mem.replication_memory += m.replication_memory;
}
return mem;
}