Plot the capacity of a trace-based delivery filter.
Breaks out the instantaneous rate counters to its own class. R=solenberg@webrtc.org Review URL: https://webrtc-codereview.appspot.com/7999005 git-svn-id: http://webrtc.googlecode.com/svn/trunk@5494 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
ea1c5ad58f
commit
77c917a6ee
@ -67,7 +67,7 @@ INSTANTIATE_TEST_CASE_P(VideoSendersTest, BweSimulation,
|
|||||||
TEST_P(BweSimulation, SprintUplinkTest) {
|
TEST_P(BweSimulation, SprintUplinkTest) {
|
||||||
VerboseLogging(true);
|
VerboseLogging(true);
|
||||||
RateCounterFilter counter1(this, "sender_output");
|
RateCounterFilter counter1(this, "sender_output");
|
||||||
TraceBasedDeliveryFilter filter(this);
|
TraceBasedDeliveryFilter filter(this, "link_capacity");
|
||||||
RateCounterFilter counter2(this, "receiver_input");
|
RateCounterFilter counter2(this, "receiver_input");
|
||||||
ASSERT_TRUE(filter.Init(test::ResourcePath("sprint-uplink", "rx")));
|
ASSERT_TRUE(filter.Init(test::ResourcePath("sprint-uplink", "rx")));
|
||||||
RunFor(60 * 1000);
|
RunFor(60 * 1000);
|
||||||
@ -76,7 +76,7 @@ TEST_P(BweSimulation, SprintUplinkTest) {
|
|||||||
TEST_P(BweSimulation, Verizon4gDownlinkTest) {
|
TEST_P(BweSimulation, Verizon4gDownlinkTest) {
|
||||||
VerboseLogging(true);
|
VerboseLogging(true);
|
||||||
RateCounterFilter counter1(this, "sender_output");
|
RateCounterFilter counter1(this, "sender_output");
|
||||||
TraceBasedDeliveryFilter filter(this);
|
TraceBasedDeliveryFilter filter(this, "link_capacity");
|
||||||
RateCounterFilter counter2(this, "receiver_input");
|
RateCounterFilter counter2(this, "receiver_input");
|
||||||
ASSERT_TRUE(filter.Init(test::ResourcePath("verizon4g-downlink", "rx")));
|
ASSERT_TRUE(filter.Init(test::ResourcePath("verizon4g-downlink", "rx")));
|
||||||
RunFor(22 * 60 * 1000);
|
RunFor(22 * 60 * 1000);
|
||||||
|
@ -29,7 +29,7 @@ function gen_gnuplot_input {
|
|||||||
linetypes=($(echo "$data_sets" | cut -d '#' -f 2 | cut -d ' ' -f 1))
|
linetypes=($(echo "$data_sets" | cut -d '#' -f 2 | cut -d ' ' -f 1))
|
||||||
echo -n "reset; "
|
echo -n "reset; "
|
||||||
echo -n "set terminal wxt size 1440,900 font \"Arial,9\"; "
|
echo -n "set terminal wxt size 1440,900 font \"Arial,9\"; "
|
||||||
echo -n "set xtics 60; set xlabel \"Seconds\"; "
|
echo -n "set xlabel \"Seconds\"; "
|
||||||
if [ -n $linetypes ]; then
|
if [ -n $linetypes ]; then
|
||||||
echo -n "set ylabel 'bitrate (kbps)';"
|
echo -n "set ylabel 'bitrate (kbps)';"
|
||||||
echo -n "set ytics nomirror;"
|
echo -n "set ytics nomirror;"
|
||||||
|
@ -17,6 +17,48 @@ namespace webrtc {
|
|||||||
namespace testing {
|
namespace testing {
|
||||||
namespace bwe {
|
namespace bwe {
|
||||||
|
|
||||||
|
class RateCounter {
|
||||||
|
public:
|
||||||
|
RateCounter()
|
||||||
|
: kWindowSizeUs(1000000),
|
||||||
|
packets_per_second_(0),
|
||||||
|
bytes_per_second_(0),
|
||||||
|
last_accumulated_us_(0),
|
||||||
|
window_() {}
|
||||||
|
|
||||||
|
void UpdateRates(int64_t send_time_us, uint32_t payload_size) {
|
||||||
|
packets_per_second_++;
|
||||||
|
bytes_per_second_ += payload_size;
|
||||||
|
last_accumulated_us_ = send_time_us;
|
||||||
|
window_.push_back(std::make_pair(send_time_us, payload_size));
|
||||||
|
while (!window_.empty()) {
|
||||||
|
const TimeSizePair& packet = window_.front();
|
||||||
|
if (packet.first > (last_accumulated_us_ - kWindowSizeUs)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
assert(packets_per_second_ >= 1);
|
||||||
|
assert(bytes_per_second_ >= packet.second);
|
||||||
|
packets_per_second_--;
|
||||||
|
bytes_per_second_ -= packet.second;
|
||||||
|
window_.pop_front();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t bits_per_second() const {
|
||||||
|
return bytes_per_second_ * 8;
|
||||||
|
}
|
||||||
|
uint32_t packets_per_second() const { return packets_per_second_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef std::pair<int64_t, uint32_t> TimeSizePair;
|
||||||
|
|
||||||
|
const int64_t kWindowSizeUs;
|
||||||
|
uint32_t packets_per_second_;
|
||||||
|
uint32_t bytes_per_second_;
|
||||||
|
int64_t last_accumulated_us_;
|
||||||
|
std::list<TimeSizePair> window_;
|
||||||
|
};
|
||||||
|
|
||||||
Random::Random(uint32_t seed)
|
Random::Random(uint32_t seed)
|
||||||
: a_(0x531FDB97 ^ seed),
|
: a_(0x531FDB97 ^ seed),
|
||||||
b_(0x6420ECA8 + seed) {
|
b_(0x6420ECA8 + seed) {
|
||||||
@ -102,33 +144,31 @@ PacketProcessor::~PacketProcessor() {
|
|||||||
|
|
||||||
RateCounterFilter::RateCounterFilter(PacketProcessorListener* listener)
|
RateCounterFilter::RateCounterFilter(PacketProcessorListener* listener)
|
||||||
: PacketProcessor(listener),
|
: PacketProcessor(listener),
|
||||||
kWindowSizeUs(1000000),
|
rate_counter_(new RateCounter()),
|
||||||
packets_per_second_(0),
|
|
||||||
bytes_per_second_(0),
|
|
||||||
last_accumulated_us_(0),
|
|
||||||
window_(),
|
|
||||||
pps_stats_(),
|
pps_stats_(),
|
||||||
kbps_stats_(),
|
kbps_stats_(),
|
||||||
name_("") {
|
name_("") {}
|
||||||
}
|
|
||||||
|
|
||||||
RateCounterFilter::RateCounterFilter(PacketProcessorListener* listener,
|
RateCounterFilter::RateCounterFilter(PacketProcessorListener* listener,
|
||||||
const std::string& name)
|
const std::string& name)
|
||||||
: PacketProcessor(listener),
|
: PacketProcessor(listener),
|
||||||
kWindowSizeUs(1000000),
|
rate_counter_(new RateCounter()),
|
||||||
packets_per_second_(0),
|
|
||||||
bytes_per_second_(0),
|
|
||||||
last_accumulated_us_(0),
|
|
||||||
window_(),
|
|
||||||
pps_stats_(),
|
pps_stats_(),
|
||||||
kbps_stats_(),
|
kbps_stats_(),
|
||||||
name_(name) {
|
name_(name) {}
|
||||||
}
|
|
||||||
|
|
||||||
RateCounterFilter::~RateCounterFilter() {
|
RateCounterFilter::~RateCounterFilter() {
|
||||||
LogStats();
|
LogStats();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t RateCounterFilter::packets_per_second() const {
|
||||||
|
return rate_counter_->packets_per_second();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t RateCounterFilter::bits_per_second() const {
|
||||||
|
return rate_counter_->bits_per_second();
|
||||||
|
}
|
||||||
|
|
||||||
void RateCounterFilter::LogStats() {
|
void RateCounterFilter::LogStats() {
|
||||||
BWE_TEST_LOGGING_CONTEXT("RateCounterFilter");
|
BWE_TEST_LOGGING_CONTEXT("RateCounterFilter");
|
||||||
pps_stats_.Log("pps");
|
pps_stats_.Log("pps");
|
||||||
@ -138,30 +178,16 @@ void RateCounterFilter::LogStats() {
|
|||||||
void RateCounterFilter::Plot(int64_t timestamp_ms) {
|
void RateCounterFilter::Plot(int64_t timestamp_ms) {
|
||||||
BWE_TEST_LOGGING_CONTEXT(name_.c_str());
|
BWE_TEST_LOGGING_CONTEXT(name_.c_str());
|
||||||
BWE_TEST_LOGGING_PLOT("Throughput_#1", timestamp_ms,
|
BWE_TEST_LOGGING_PLOT("Throughput_#1", timestamp_ms,
|
||||||
(bytes_per_second_ * 8) / 1000.0);
|
rate_counter_->bits_per_second() / 1000.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RateCounterFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) {
|
void RateCounterFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) {
|
||||||
assert(in_out);
|
assert(in_out);
|
||||||
for (PacketsConstIt it = in_out->begin(); it != in_out->end(); ++it) {
|
for (PacketsConstIt it = in_out->begin(); it != in_out->end(); ++it) {
|
||||||
packets_per_second_++;
|
rate_counter_->UpdateRates(it->send_time_us(), it->payload_size());
|
||||||
bytes_per_second_ += it->payload_size();
|
|
||||||
last_accumulated_us_ = it->send_time_us();
|
|
||||||
}
|
}
|
||||||
window_.insert(window_.end(), in_out->begin(), in_out->end());
|
pps_stats_.Push(rate_counter_->packets_per_second());
|
||||||
while (!window_.empty()) {
|
kbps_stats_.Push(rate_counter_->bits_per_second() / 1000.0);
|
||||||
const Packet& packet = window_.front();
|
|
||||||
if (packet.send_time_us() > (last_accumulated_us_ - kWindowSizeUs)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
assert(packets_per_second_ >= 1);
|
|
||||||
assert(bytes_per_second_ >= packet.payload_size());
|
|
||||||
packets_per_second_--;
|
|
||||||
bytes_per_second_ -= packet.payload_size();
|
|
||||||
window_.pop_front();
|
|
||||||
}
|
|
||||||
pps_stats_.Push(packets_per_second_);
|
|
||||||
kbps_stats_.Push((bytes_per_second_ * 8) / 1000.0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LossFilter::LossFilter(PacketProcessorListener* listener)
|
LossFilter::LossFilter(PacketProcessorListener* listener)
|
||||||
@ -311,7 +337,22 @@ TraceBasedDeliveryFilter::TraceBasedDeliveryFilter(
|
|||||||
: PacketProcessor(listener),
|
: PacketProcessor(listener),
|
||||||
delivery_times_us_(),
|
delivery_times_us_(),
|
||||||
next_delivery_it_(),
|
next_delivery_it_(),
|
||||||
local_time_us_(-1) {}
|
local_time_us_(-1),
|
||||||
|
rate_counter_(new RateCounter),
|
||||||
|
name_("") {}
|
||||||
|
|
||||||
|
TraceBasedDeliveryFilter::TraceBasedDeliveryFilter(
|
||||||
|
PacketProcessorListener* listener,
|
||||||
|
const std::string& name)
|
||||||
|
: PacketProcessor(listener),
|
||||||
|
delivery_times_us_(),
|
||||||
|
next_delivery_it_(),
|
||||||
|
local_time_us_(-1),
|
||||||
|
rate_counter_(new RateCounter),
|
||||||
|
name_(name) {}
|
||||||
|
|
||||||
|
TraceBasedDeliveryFilter::~TraceBasedDeliveryFilter() {
|
||||||
|
}
|
||||||
|
|
||||||
bool TraceBasedDeliveryFilter::Init(const std::string& filename) {
|
bool TraceBasedDeliveryFilter::Init(const std::string& filename) {
|
||||||
FILE* trace_file = fopen(filename.c_str(), "r");
|
FILE* trace_file = fopen(filename.c_str(), "r");
|
||||||
@ -341,11 +382,21 @@ bool TraceBasedDeliveryFilter::Init(const std::string& filename) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TraceBasedDeliveryFilter::Plot(int64_t timestamp_ms) {
|
||||||
|
BWE_TEST_LOGGING_CONTEXT(name_.c_str());
|
||||||
|
// This plots the max possible throughput of the trace-based delivery filter,
|
||||||
|
// which will be reached if a packet sent on every packet slot of the trace.
|
||||||
|
BWE_TEST_LOGGING_PLOT("MaxThroughput_#1", timestamp_ms,
|
||||||
|
rate_counter_->bits_per_second() / 1000.0);
|
||||||
|
}
|
||||||
|
|
||||||
void TraceBasedDeliveryFilter::RunFor(int64_t time_ms, Packets* in_out) {
|
void TraceBasedDeliveryFilter::RunFor(int64_t time_ms, Packets* in_out) {
|
||||||
assert(in_out);
|
assert(in_out);
|
||||||
for (PacketsIt it = in_out->begin(); it != in_out->end(); ++it) {
|
for (PacketsIt it = in_out->begin(); it != in_out->end(); ++it) {
|
||||||
do {
|
do {
|
||||||
ProceedToNextSlot();
|
ProceedToNextSlot();
|
||||||
|
const int kPayloadSize = 1240;
|
||||||
|
rate_counter_->UpdateRates(local_time_us_, kPayloadSize);
|
||||||
} while (local_time_us_ < it->send_time_us());
|
} while (local_time_us_ < it->send_time_us());
|
||||||
it->set_send_time_us(local_time_us_);
|
it->set_send_time_us(local_time_us_);
|
||||||
}
|
}
|
||||||
|
@ -21,11 +21,14 @@
|
|||||||
|
|
||||||
#include "webrtc/modules/interface/module_common_types.h"
|
#include "webrtc/modules/interface/module_common_types.h"
|
||||||
#include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_logging.h"
|
#include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_logging.h"
|
||||||
|
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
namespace testing {
|
namespace testing {
|
||||||
namespace bwe {
|
namespace bwe {
|
||||||
|
|
||||||
|
class RateCounter;
|
||||||
|
|
||||||
template<typename T> class Stats {
|
template<typename T> class Stats {
|
||||||
public:
|
public:
|
||||||
Stats()
|
Stats()
|
||||||
@ -193,22 +196,18 @@ class RateCounterFilter : public PacketProcessor {
|
|||||||
public:
|
public:
|
||||||
explicit RateCounterFilter(PacketProcessorListener* listener);
|
explicit RateCounterFilter(PacketProcessorListener* listener);
|
||||||
RateCounterFilter(PacketProcessorListener* listener,
|
RateCounterFilter(PacketProcessorListener* listener,
|
||||||
const std::string& context);
|
const std::string& name);
|
||||||
virtual ~RateCounterFilter();
|
virtual ~RateCounterFilter();
|
||||||
|
|
||||||
uint32_t packets_per_second() const { return packets_per_second_; }
|
uint32_t packets_per_second() const;
|
||||||
uint32_t bits_per_second() const { return bytes_per_second_ * 8; }
|
uint32_t bits_per_second() const;
|
||||||
|
|
||||||
void LogStats();
|
void LogStats();
|
||||||
virtual void Plot(int64_t timestamp_ms);
|
virtual void Plot(int64_t timestamp_ms);
|
||||||
virtual void RunFor(int64_t time_ms, Packets* in_out);
|
virtual void RunFor(int64_t time_ms, Packets* in_out);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const int64_t kWindowSizeUs;
|
scoped_ptr<RateCounter> rate_counter_;
|
||||||
uint32_t packets_per_second_;
|
|
||||||
uint32_t bytes_per_second_;
|
|
||||||
int64_t last_accumulated_us_;
|
|
||||||
Packets window_;
|
|
||||||
Stats<double> pps_stats_;
|
Stats<double> pps_stats_;
|
||||||
Stats<double> kbps_stats_;
|
Stats<double> kbps_stats_;
|
||||||
std::string name_;
|
std::string name_;
|
||||||
@ -298,12 +297,15 @@ class ChokeFilter : public PacketProcessor {
|
|||||||
class TraceBasedDeliveryFilter : public PacketProcessor {
|
class TraceBasedDeliveryFilter : public PacketProcessor {
|
||||||
public:
|
public:
|
||||||
explicit TraceBasedDeliveryFilter(PacketProcessorListener* listener);
|
explicit TraceBasedDeliveryFilter(PacketProcessorListener* listener);
|
||||||
virtual ~TraceBasedDeliveryFilter() {}
|
TraceBasedDeliveryFilter(PacketProcessorListener* listener,
|
||||||
|
const std::string& name);
|
||||||
|
virtual ~TraceBasedDeliveryFilter();
|
||||||
|
|
||||||
// The file should contain nanosecond timestamps corresponding to the time
|
// The file should contain nanosecond timestamps corresponding to the time
|
||||||
// when the network can accept another packet. The timestamps should be
|
// when the network can accept another packet. The timestamps should be
|
||||||
// separated by new lines, e.g., "100000000\n125000000\n321000000\n..."
|
// separated by new lines, e.g., "100000000\n125000000\n321000000\n..."
|
||||||
bool Init(const std::string& filename);
|
bool Init(const std::string& filename);
|
||||||
|
virtual void Plot(int64_t timestamp_ms);
|
||||||
virtual void RunFor(int64_t time_ms, Packets* in_out);
|
virtual void RunFor(int64_t time_ms, Packets* in_out);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -313,6 +315,8 @@ class TraceBasedDeliveryFilter : public PacketProcessor {
|
|||||||
TimeList delivery_times_us_;
|
TimeList delivery_times_us_;
|
||||||
TimeList::const_iterator next_delivery_it_;
|
TimeList::const_iterator next_delivery_it_;
|
||||||
int64_t local_time_us_;
|
int64_t local_time_us_;
|
||||||
|
scoped_ptr<RateCounter> rate_counter_;
|
||||||
|
std::string name_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(TraceBasedDeliveryFilter);
|
DISALLOW_COPY_AND_ASSIGN(TraceBasedDeliveryFilter);
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user