refactored stats class to be extensible with more channels
This commit is contained in:
parent
010d3b6e75
commit
7388144ec7
|
@ -36,6 +36,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
#include "libtorrent/size_type.hpp"
|
#include "libtorrent/size_type.hpp"
|
||||||
#include "libtorrent/invariant_check.hpp"
|
#include "libtorrent/invariant_check.hpp"
|
||||||
|
@ -44,88 +45,135 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
namespace libtorrent
|
namespace libtorrent
|
||||||
{
|
{
|
||||||
|
class TORRENT_EXPORT stat_channel
|
||||||
class TORRENT_EXPORT stat
|
|
||||||
{
|
{
|
||||||
friend class invariant_access;
|
friend class invariant_access;
|
||||||
public:
|
public:
|
||||||
enum { history = 10 };
|
enum { history = 10 };
|
||||||
|
|
||||||
stat()
|
stat_channel()
|
||||||
: m_downloaded_payload(0)
|
: m_counter(0)
|
||||||
, m_uploaded_payload(0)
|
, m_total_counter(0)
|
||||||
, m_downloaded_protocol(0)
|
, m_rate_sum(0)
|
||||||
, m_uploaded_protocol(0)
|
|
||||||
, m_total_download_payload(0)
|
|
||||||
, m_total_upload_payload(0)
|
|
||||||
, m_total_download_protocol(0)
|
|
||||||
, m_total_upload_protocol(0)
|
|
||||||
, m_mean_download_rate(0)
|
|
||||||
, m_mean_upload_rate(0)
|
|
||||||
, m_mean_download_payload_rate(0)
|
|
||||||
, m_mean_upload_payload_rate(0)
|
|
||||||
{
|
{
|
||||||
std::fill(m_download_rate_history, m_download_rate_history+history, 0.f);
|
std::fill(m_rate_history
|
||||||
std::fill(m_upload_rate_history, m_upload_rate_history+history, 0.f);
|
, m_rate_history + history, 0.f);
|
||||||
std::fill(m_download_payload_rate_history, m_download_payload_rate_history+history, 0.f);
|
|
||||||
std::fill(m_upload_payload_rate_history, m_upload_payload_rate_history+history, 0.f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator+=(const stat& s)
|
void operator+=(stat_channel const& s)
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
m_counter += s.m_counter;
|
||||||
|
m_total_counter += s.m_counter;
|
||||||
m_downloaded_payload += s.m_downloaded_payload;
|
|
||||||
m_total_download_payload += s.m_downloaded_payload;
|
|
||||||
m_downloaded_protocol += s.m_downloaded_protocol;
|
|
||||||
m_total_download_protocol += s.m_downloaded_protocol;
|
|
||||||
|
|
||||||
m_uploaded_payload += s.m_uploaded_payload;
|
|
||||||
m_total_upload_payload += s.m_uploaded_payload;
|
|
||||||
m_uploaded_protocol += s.m_uploaded_protocol;
|
|
||||||
m_total_upload_protocol += s.m_uploaded_protocol;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void received_bytes(int bytes_payload, int bytes_protocol)
|
void add(int count)
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
TORRENT_ASSERT(count >= 0);
|
||||||
|
|
||||||
TORRENT_ASSERT(bytes_payload >= 0);
|
m_counter += count;
|
||||||
TORRENT_ASSERT(bytes_protocol >= 0);
|
m_total_counter += count;
|
||||||
|
|
||||||
m_downloaded_payload += bytes_payload;
|
|
||||||
m_total_download_payload += bytes_payload;
|
|
||||||
m_downloaded_protocol += bytes_protocol;
|
|
||||||
m_total_download_protocol += bytes_protocol;
|
|
||||||
}
|
|
||||||
|
|
||||||
void sent_bytes(int bytes_payload, int bytes_protocol)
|
|
||||||
{
|
|
||||||
INVARIANT_CHECK;
|
|
||||||
|
|
||||||
TORRENT_ASSERT(bytes_payload >= 0);
|
|
||||||
TORRENT_ASSERT(bytes_protocol >= 0);
|
|
||||||
|
|
||||||
m_uploaded_payload += bytes_payload;
|
|
||||||
m_total_upload_payload += bytes_payload;
|
|
||||||
m_uploaded_protocol += bytes_protocol;
|
|
||||||
m_total_upload_protocol += bytes_protocol;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// should be called once every second
|
// should be called once every second
|
||||||
void second_tick(float tick_interval);
|
void second_tick(float tick_interval);
|
||||||
|
float rate() const { return m_rate_sum / history; }
|
||||||
|
size_type total() const { return m_total_counter; }
|
||||||
|
|
||||||
float upload_rate() const { return m_mean_upload_rate; }
|
void offset(size_type counter)
|
||||||
float download_rate() const { return m_mean_download_rate; }
|
{
|
||||||
|
TORRENT_ASSERT(counter >= 0);
|
||||||
|
m_total_counter += counter;
|
||||||
|
}
|
||||||
|
|
||||||
float upload_payload_rate() const { return m_mean_upload_payload_rate; }
|
size_type counter() const { return m_counter; }
|
||||||
float download_payload_rate() const { return m_mean_download_payload_rate; }
|
|
||||||
|
|
||||||
size_type total_payload_upload() const { return m_total_upload_payload; }
|
private:
|
||||||
size_type total_payload_download() const { return m_total_download_payload; }
|
|
||||||
|
|
||||||
size_type total_protocol_upload() const { return m_total_upload_protocol; }
|
#ifndef NDEBUG
|
||||||
size_type total_protocol_download() const { return m_total_download_protocol; }
|
void check_invariant() const
|
||||||
|
{
|
||||||
|
float sum = 0.f;
|
||||||
|
for (int i = 0; i < history; ++i) sum += m_rate_history[i];
|
||||||
|
TORRENT_ASSERT(fabs(m_rate_sum - sum) < 0.1);
|
||||||
|
TORRENT_ASSERT(m_total_counter >= 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// history of rates a few seconds back
|
||||||
|
float m_rate_history[history];
|
||||||
|
|
||||||
|
// the accumulator for this second.
|
||||||
|
int m_counter;
|
||||||
|
|
||||||
|
// total counters
|
||||||
|
size_type m_total_counter;
|
||||||
|
|
||||||
|
// sum of all elements in m_rate_history
|
||||||
|
float m_rate_sum;
|
||||||
|
};
|
||||||
|
|
||||||
|
class TORRENT_EXPORT stat
|
||||||
|
{
|
||||||
|
friend class invariant_access;
|
||||||
|
public:
|
||||||
|
void operator+=(const stat& s)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < num_channels; ++i)
|
||||||
|
m_stat[i] += s.m_stat[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
void received_bytes(int bytes_payload, int bytes_protocol)
|
||||||
|
{
|
||||||
|
TORRENT_ASSERT(bytes_payload >= 0);
|
||||||
|
TORRENT_ASSERT(bytes_protocol >= 0);
|
||||||
|
|
||||||
|
m_stat[download_payload].add(bytes_payload);
|
||||||
|
m_stat[download_protocol].add(bytes_protocol);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sent_bytes(int bytes_payload, int bytes_protocol)
|
||||||
|
{
|
||||||
|
TORRENT_ASSERT(bytes_payload >= 0);
|
||||||
|
TORRENT_ASSERT(bytes_protocol >= 0);
|
||||||
|
|
||||||
|
m_stat[upload_payload].add(bytes_payload);
|
||||||
|
m_stat[upload_protocol].add(bytes_protocol);
|
||||||
|
}
|
||||||
|
|
||||||
|
// should be called once every second
|
||||||
|
void second_tick(float tick_interval)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < num_channels; ++i)
|
||||||
|
m_stat[i].second_tick(tick_interval);
|
||||||
|
}
|
||||||
|
|
||||||
|
float upload_rate() const
|
||||||
|
{
|
||||||
|
return m_stat[upload_payload].rate()
|
||||||
|
+ m_stat[upload_protocol].rate();
|
||||||
|
}
|
||||||
|
|
||||||
|
float download_rate() const
|
||||||
|
{
|
||||||
|
return m_stat[download_payload].rate()
|
||||||
|
+ m_stat[download_protocol].rate();
|
||||||
|
}
|
||||||
|
|
||||||
|
float upload_payload_rate() const
|
||||||
|
{ return m_stat[upload_payload].rate(); }
|
||||||
|
|
||||||
|
float download_payload_rate() const
|
||||||
|
{ return m_stat[download_payload].rate(); }
|
||||||
|
|
||||||
|
size_type total_payload_upload() const
|
||||||
|
{ return m_stat[upload_payload].total(); }
|
||||||
|
size_type total_payload_download() const
|
||||||
|
{ return m_stat[download_payload].total(); }
|
||||||
|
|
||||||
|
size_type total_protocol_upload() const
|
||||||
|
{ return m_stat[upload_protocol].total(); }
|
||||||
|
size_type total_protocol_download() const
|
||||||
|
{ return m_stat[download_protocol].total(); }
|
||||||
|
|
||||||
// this is used to offset the statistics when a
|
// this is used to offset the statistics when a
|
||||||
// peer_connection is opened and have some previous
|
// peer_connection is opened and have some previous
|
||||||
|
@ -134,66 +182,31 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(downloaded >= 0);
|
TORRENT_ASSERT(downloaded >= 0);
|
||||||
TORRENT_ASSERT(uploaded >= 0);
|
TORRENT_ASSERT(uploaded >= 0);
|
||||||
m_total_download_payload += downloaded;
|
m_stat[download_payload].offset(downloaded);
|
||||||
m_total_upload_payload += uploaded;
|
m_stat[upload_payload].offset(uploaded);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_type last_payload_downloaded() const { return m_downloaded_payload; }
|
size_type last_payload_downloaded() const
|
||||||
size_type last_payload_uploaded() const { return m_uploaded_payload; }
|
{ return m_stat[download_payload].counter(); }
|
||||||
|
size_type last_payload_uploaded() const
|
||||||
|
{ return m_stat[upload_payload].counter(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
#ifndef NDEBUG
|
// these are the channels we keep stats for
|
||||||
void check_invariant() const
|
enum
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(m_mean_upload_rate >= 0);
|
upload_payload,
|
||||||
TORRENT_ASSERT(m_mean_download_rate >= 0);
|
upload_protocol,
|
||||||
TORRENT_ASSERT(m_mean_upload_payload_rate >= 0);
|
download_payload,
|
||||||
TORRENT_ASSERT(m_mean_download_payload_rate >= 0);
|
download_protocol,
|
||||||
TORRENT_ASSERT(m_total_upload_payload >= 0);
|
num_channels
|
||||||
TORRENT_ASSERT(m_total_download_payload >= 0);
|
};
|
||||||
TORRENT_ASSERT(m_total_upload_protocol >= 0);
|
|
||||||
TORRENT_ASSERT(m_total_download_protocol >= 0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// history of download/upload speeds a few seconds back
|
stat_channel m_stat[num_channels];
|
||||||
float m_download_rate_history[history];
|
|
||||||
float m_upload_rate_history[history];
|
|
||||||
|
|
||||||
float m_download_payload_rate_history[history];
|
|
||||||
float m_upload_payload_rate_history[history];
|
|
||||||
|
|
||||||
// the accumulators we are adding the downloads/uploads
|
|
||||||
// to this second. This only counts the actual payload
|
|
||||||
// and ignores the bytes sent as protocol chatter.
|
|
||||||
int m_downloaded_payload;
|
|
||||||
int m_uploaded_payload;
|
|
||||||
|
|
||||||
// the accumulators we are adding the downloads/uploads
|
|
||||||
// to this second. This only counts the protocol
|
|
||||||
// chatter and ignores the actual payload
|
|
||||||
int m_downloaded_protocol;
|
|
||||||
int m_uploaded_protocol;
|
|
||||||
|
|
||||||
// total download/upload counters
|
|
||||||
// only counting payload data
|
|
||||||
size_type m_total_download_payload;
|
|
||||||
size_type m_total_upload_payload;
|
|
||||||
|
|
||||||
// total download/upload counters
|
|
||||||
// only counting protocol chatter
|
|
||||||
size_type m_total_download_protocol;
|
|
||||||
size_type m_total_upload_protocol;
|
|
||||||
|
|
||||||
// current mean download/upload rates
|
|
||||||
float m_mean_download_rate;
|
|
||||||
float m_mean_upload_rate;
|
|
||||||
|
|
||||||
float m_mean_download_payload_rate;
|
|
||||||
float m_mean_upload_payload_rate;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // TORRENT_STAT_HPP_INCLUDED
|
#endif // TORRENT_STAT_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
50
src/stat.cpp
50
src/stat.cpp
|
@ -47,47 +47,23 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#define for if (false) {} else for
|
#define for if (false) {} else for
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using namespace libtorrent;
|
namespace libtorrent
|
||||||
|
{
|
||||||
|
|
||||||
void libtorrent::stat::second_tick(float tick_interval)
|
void stat_channel::second_tick(float tick_interval)
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
|
m_rate_sum -= m_rate_history[history-1];
|
||||||
|
|
||||||
for (int i = history - 2; i >= 0; --i)
|
for (int i = history - 2; i >= 0; --i)
|
||||||
{
|
m_rate_history[i + 1] = m_rate_history[i];
|
||||||
m_download_rate_history[i + 1] = m_download_rate_history[i];
|
|
||||||
m_upload_rate_history[i + 1] = m_upload_rate_history[i];
|
|
||||||
m_download_payload_rate_history[i + 1] = m_download_payload_rate_history[i];
|
|
||||||
m_upload_payload_rate_history[i + 1] = m_upload_payload_rate_history[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
m_download_rate_history[0] = (m_downloaded_payload + m_downloaded_protocol)
|
m_rate_history[0] = m_counter / tick_interval;
|
||||||
/ tick_interval;
|
m_rate_sum += m_rate_history[0];
|
||||||
m_upload_rate_history[0] = (m_uploaded_payload + m_uploaded_protocol)
|
m_counter = 0;
|
||||||
/ tick_interval;
|
|
||||||
m_download_payload_rate_history[0] = m_downloaded_payload / tick_interval;
|
|
||||||
m_upload_payload_rate_history[0] = m_uploaded_payload / tick_interval;
|
|
||||||
|
|
||||||
m_downloaded_payload = 0;
|
|
||||||
m_uploaded_payload = 0;
|
|
||||||
m_downloaded_protocol = 0;
|
|
||||||
m_uploaded_protocol = 0;
|
|
||||||
|
|
||||||
m_mean_download_rate = 0;
|
|
||||||
m_mean_upload_rate = 0;
|
|
||||||
m_mean_download_payload_rate = 0;
|
|
||||||
m_mean_upload_payload_rate = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < history; ++i)
|
|
||||||
{
|
|
||||||
m_mean_download_rate += m_download_rate_history[i];
|
|
||||||
m_mean_upload_rate += m_upload_rate_history[i];
|
|
||||||
m_mean_download_payload_rate += m_download_payload_rate_history[i];
|
|
||||||
m_mean_upload_payload_rate += m_upload_payload_rate_history[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
m_mean_download_rate /= history;
|
|
||||||
m_mean_upload_rate /= history;
|
|
||||||
m_mean_download_payload_rate /= history;
|
|
||||||
m_mean_upload_payload_rate /= history;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue