Merge branch 'stats'

Add statistics for memory allocations and httpd.
This commit is contained in:
Avi Kivity
2014-11-24 10:00:34 +02:00
4 changed files with 108 additions and 2 deletions

View File

@@ -10,6 +10,7 @@
#include "core/smp.hh"
#include "core/queue.hh"
#include "core/future-util.hh"
#include "core/scollectd.hh"
#include <iostream>
#include <algorithm>
#include <unordered_map>
@@ -17,9 +18,23 @@
#include <bitset>
#include <limits>
#include <cctype>
#include <vector>
class http_server;
class http_stats;
class http_stats {
std::vector<scollectd::registration> _regs;
public:
http_stats(http_server& server);
};
class http_server {
std::vector<server_socket> _listeners;
http_stats _stats{*this};
uint64_t _total_connections = 0;
uint64_t _current_connections = 0;
uint64_t _requests_served = 0;
public:
future<> listen(ipv4_addr addr) {
listen_options lo;
@@ -49,6 +64,7 @@ public:
});
}
class connection {
http_server& _server;
connected_socket _fd;
input_stream<char> _read_buf;
output_stream<char> _write_buf;
@@ -67,8 +83,14 @@ public:
queue<std::unique_ptr<response>> _responses { 10 };
public:
connection(http_server& server, connected_socket&& fd, socket_address addr)
: _fd(std::move(fd)), _read_buf(_fd.input())
, _write_buf(_fd.output()) {}
: _server(server), _fd(std::move(fd)), _read_buf(_fd.input())
, _write_buf(_fd.output()) {
++_server._total_connections;
++_server._current_connections;
}
~connection() {
--_server._current_connections;
}
future<> process() {
// Launch read and write "threads" simultaneously:
return when_all(read(), respond()).then([] (std::tuple<future<>, future<>> joined) {
@@ -82,6 +104,7 @@ public:
if (_parser.eof()) {
return _responses.push_eventually({});
}
++_server._requests_served;
_req = _parser.get_parsed_request();
return _responses.not_full().then([this] {
bool close = generate_response(std::move(_req));
@@ -173,8 +196,38 @@ public:
return _write_buf.write(_resp->_body.begin(), _resp->_body.size());
}
};
uint64_t total_connections() const {
return _total_connections;
}
uint64_t current_connections() const {
return _current_connections;
}
uint64_t requests_served() const {
return _requests_served;
}
};
http_stats::http_stats(http_server& server)
: _regs{
scollectd::add_polled_metric(
scollectd::type_instance_id("httpd", scollectd::per_cpu_plugin_instance,
"connections", "http-connections"),
scollectd::make_typed(scollectd::data_type::DERIVE,
[&server] { return server.total_connections(); })),
scollectd::add_polled_metric(
scollectd::type_instance_id("httpd", scollectd::per_cpu_plugin_instance,
"current_connections", "current"),
scollectd::make_typed(scollectd::data_type::GAUGE,
[&server] { return server.current_connections(); })),
scollectd::add_polled_metric(
scollectd::type_instance_id("httpd", scollectd::per_cpu_plugin_instance,
"http_requests", "served"),
scollectd::make_typed(scollectd::data_type::DERIVE,
[&server] { return server.requests_served(); })),
} {
}
int main(int ac, char** av) {
app_template app;
app.add_options()

View File

@@ -61,6 +61,9 @@ using pageidx = uint32_t;
struct page;
class page_list;
static uint64_t g_allocs;
static uint64_t g_frees;
namespace bi = boost::intrusive;
class page_list_link {
@@ -641,6 +644,7 @@ size_t object_size(void* ptr) {
}
void* allocate(size_t size) {
++g_allocs;
if (size <= sizeof(free_object)) {
size = sizeof(free_object);
}
@@ -652,6 +656,7 @@ void* allocate(size_t size) {
}
void* allocate_aligned(size_t align, size_t size) {
++g_allocs;
size = std::max(size, align);
if (size <= sizeof(free_object)) {
size = sizeof(free_object);
@@ -664,10 +669,12 @@ void* allocate_aligned(size_t align, size_t size) {
}
void free(void* obj) {
++g_frees;
cpu_mem.free(obj);
}
void free(void* obj, size_t size) {
++g_frees;
cpu_mem.free(obj, size);
}
@@ -705,6 +712,10 @@ void configure(std::vector<resource::memory> m) {
}
}
statistics stats() {
return statistics{g_allocs, g_frees};
}
}
using namespace memory;
@@ -916,6 +927,10 @@ void set_reclaim_hook(std::function<void (std::function<void ()>)> hook) {
void configure(std::vector<resource::memory> m) {
}
statistics stats() {
return statistics{0, 0};
}
}
#endif

View File

@@ -33,6 +33,23 @@ public:
void set_reclaim_hook(
std::function<void (std::function<void ()>)> hook);
class statistics;
statistics stats();
class statistics {
uint64_t _objects_allocated;
uint64_t _objects_freed;
private:
statistics(uint64_t allocs, uint64_t frees)
: _objects_allocated(allocs), _objects_freed(frees) {}
public:
uint64_t object_allocated() const { return _objects_allocated; }
uint64_t object_freed() const { return _objects_freed; }
size_t allocated_objects() const { return object_allocated() - object_freed(); }
friend statistics stats();
};
}
#endif /* MEMORY_HH_ */

View File

@@ -406,6 +406,27 @@ int reactor::run() {
, scollectd::make_typed(scollectd::data_type::GAUGE
, std::bind(&decltype(_timers)::size, &_timers))
),
scollectd::add_polled_metric(
scollectd::type_instance_id("memory",
scollectd::per_cpu_plugin_instance,
"total_operations", "malloc"),
scollectd::make_typed(scollectd::data_type::DERIVE,
[] { return memory::stats().object_allocated(); })
),
scollectd::add_polled_metric(
scollectd::type_instance_id("memory",
scollectd::per_cpu_plugin_instance,
"total_operations", "free"),
scollectd::make_typed(scollectd::data_type::DERIVE,
[] { return memory::stats().object_freed(); })
),
scollectd::add_polled_metric(
scollectd::type_instance_id("memory",
scollectd::per_cpu_plugin_instance,
"objects", "malloc"),
scollectd::make_typed(scollectd::data_type::GAUGE,
[] { return memory::stats().allocated_objects(); })
),
};
#ifndef HAVE_OSV