Make MessageQueue processing an optional feature of FakeClock
This is used to avoid thread processing in simulated time controller. This saves up to 30% execution time in debug builds. Bug: webrtc:10365 Change-Id: Ie83dfb2468d371e4687d28c776acf7e23eb411d1 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/133173 Reviewed-by: Stefan Holmer <stefan@webrtc.org> Reviewed-by: Niels Moller <nisse@webrtc.org> Commit-Queue: Sebastian Jansson <srte@webrtc.org> Cr-Commit-Position: refs/heads/master@{#27666}
This commit is contained in:
parent
8a7dcb163e
commit
d624c3903c
@ -58,9 +58,7 @@ class RtpDataMediaChannelTest : public ::testing::Test {
|
|||||||
receiver_.reset(new FakeDataReceiver());
|
receiver_.reset(new FakeDataReceiver());
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetNow(double now) {
|
void SetNow(double now) { clock_.SetTime(webrtc::Timestamp::seconds(now)); }
|
||||||
clock_.SetTimeNanos(now * rtc::kNumNanosecsPerSec);
|
|
||||||
}
|
|
||||||
|
|
||||||
cricket::RtpDataEngine* CreateEngine() {
|
cricket::RtpDataEngine* CreateEngine() {
|
||||||
cricket::RtpDataEngine* dme = new cricket::RtpDataEngine();
|
cricket::RtpDataEngine* dme = new cricket::RtpDataEngine();
|
||||||
|
|||||||
@ -611,7 +611,7 @@ class P2PTransportChannelTestBase : public ::testing::Test,
|
|||||||
DestroyChannels();
|
DestroyChannels();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestSendRecv(rtc::FakeClock* clock) {
|
void TestSendRecv(rtc::ThreadProcessingFakeClock* clock) {
|
||||||
for (int i = 0; i < 10; ++i) {
|
for (int i = 0; i < 10; ++i) {
|
||||||
const char* data = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
|
const char* data = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
|
||||||
int len = static_cast<int>(strlen(data));
|
int len = static_cast<int>(strlen(data));
|
||||||
@ -3093,10 +3093,11 @@ class P2PTransportChannelPingTest : public ::testing::Test,
|
|||||||
this, &P2PTransportChannelPingTest::OnChannelStateChanged);
|
this, &P2PTransportChannelPingTest::OnChannelStateChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
Connection* WaitForConnectionTo(P2PTransportChannel* ch,
|
Connection* WaitForConnectionTo(
|
||||||
|
P2PTransportChannel* ch,
|
||||||
const std::string& ip,
|
const std::string& ip,
|
||||||
int port_num,
|
int port_num,
|
||||||
rtc::FakeClock* clock = nullptr) {
|
rtc::ThreadProcessingFakeClock* clock = nullptr) {
|
||||||
if (clock == nullptr) {
|
if (clock == nullptr) {
|
||||||
EXPECT_TRUE_WAIT(GetConnectionTo(ch, ip, port_num) != nullptr,
|
EXPECT_TRUE_WAIT(GetConnectionTo(ch, ip, port_num) != nullptr,
|
||||||
kMediumTimeout);
|
kMediumTimeout);
|
||||||
|
|||||||
@ -1084,6 +1084,7 @@ rtc_source_set("rtc_base_tests_utils") {
|
|||||||
":checks",
|
":checks",
|
||||||
":rtc_base",
|
":rtc_base",
|
||||||
"../api/units:time_delta",
|
"../api/units:time_delta",
|
||||||
|
"../api/units:timestamp",
|
||||||
"memory:fifo_buffer",
|
"memory:fifo_buffer",
|
||||||
"third_party/sigslot",
|
"third_party/sigslot",
|
||||||
"//third_party/abseil-cpp/absl/algorithm:container",
|
"//third_party/abseil-cpp/absl/algorithm:container",
|
||||||
|
|||||||
@ -17,28 +17,40 @@ namespace rtc {
|
|||||||
|
|
||||||
int64_t FakeClock::TimeNanos() const {
|
int64_t FakeClock::TimeNanos() const {
|
||||||
CritScope cs(&lock_);
|
CritScope cs(&lock_);
|
||||||
return time_;
|
return time_ns_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FakeClock::SetTimeNanos(int64_t nanos) {
|
void FakeClock::SetTime(webrtc::Timestamp new_time) {
|
||||||
{
|
|
||||||
CritScope cs(&lock_);
|
CritScope cs(&lock_);
|
||||||
RTC_DCHECK(nanos >= time_);
|
RTC_DCHECK(new_time.us() * 1000 >= time_ns_);
|
||||||
time_ = nanos;
|
time_ns_ = new_time.us() * 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FakeClock::AdvanceTime(webrtc::TimeDelta delta) {
|
||||||
|
CritScope cs(&lock_);
|
||||||
|
time_ns_ += delta.ns();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ThreadProcessingFakeClock::SetTime(webrtc::Timestamp time) {
|
||||||
|
clock_.SetTime(time);
|
||||||
// If message queues are waiting in a socket select() with a timeout provided
|
// If message queues are waiting in a socket select() with a timeout provided
|
||||||
// by the OS, they should wake up and dispatch all messages that are ready.
|
// by the OS, they should wake up and dispatch all messages that are ready.
|
||||||
MessageQueueManager::ProcessAllMessageQueuesForTesting();
|
MessageQueueManager::ProcessAllMessageQueuesForTesting();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FakeClock::AdvanceTime(webrtc::TimeDelta delta) {
|
void ThreadProcessingFakeClock::AdvanceTime(webrtc::TimeDelta delta) {
|
||||||
{
|
clock_.AdvanceTime(delta);
|
||||||
CritScope cs(&lock_);
|
|
||||||
time_ += delta.ns();
|
|
||||||
}
|
|
||||||
MessageQueueManager::ProcessAllMessageQueuesForTesting();
|
MessageQueueManager::ProcessAllMessageQueuesForTesting();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ScopedBaseFakeClock::ScopedBaseFakeClock() {
|
||||||
|
prev_clock_ = SetClockForTesting(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
ScopedBaseFakeClock::~ScopedBaseFakeClock() {
|
||||||
|
SetClockForTesting(prev_clock_);
|
||||||
|
}
|
||||||
|
|
||||||
ScopedFakeClock::ScopedFakeClock() {
|
ScopedFakeClock::ScopedFakeClock() {
|
||||||
prev_clock_ = SetClockForTesting(this);
|
prev_clock_ = SetClockForTesting(this);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,6 +14,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "api/units/time_delta.h"
|
#include "api/units/time_delta.h"
|
||||||
|
#include "api/units/timestamp.h"
|
||||||
#include "rtc_base/critical_section.h"
|
#include "rtc_base/critical_section.h"
|
||||||
#include "rtc_base/thread_annotations.h"
|
#include "rtc_base/thread_annotations.h"
|
||||||
#include "rtc_base/time_utils.h"
|
#include "rtc_base/time_utils.h"
|
||||||
@ -26,7 +27,10 @@ namespace rtc {
|
|||||||
// TODO(deadbeef): Unify with webrtc::SimulatedClock.
|
// TODO(deadbeef): Unify with webrtc::SimulatedClock.
|
||||||
class FakeClock : public ClockInterface {
|
class FakeClock : public ClockInterface {
|
||||||
public:
|
public:
|
||||||
~FakeClock() override {}
|
FakeClock() = default;
|
||||||
|
FakeClock(const FakeClock&) = delete;
|
||||||
|
FakeClock& operator=(const FakeClock&) = delete;
|
||||||
|
~FakeClock() override = default;
|
||||||
|
|
||||||
// ClockInterface implementation.
|
// ClockInterface implementation.
|
||||||
int64_t TimeNanos() const override;
|
int64_t TimeNanos() const override;
|
||||||
@ -34,28 +38,45 @@ class FakeClock : public ClockInterface {
|
|||||||
// Methods that can be used by the test to control the time.
|
// Methods that can be used by the test to control the time.
|
||||||
|
|
||||||
// Should only be used to set a time in the future.
|
// Should only be used to set a time in the future.
|
||||||
void SetTimeNanos(int64_t nanos);
|
void SetTime(webrtc::Timestamp new_time);
|
||||||
void SetTimeMicros(int64_t micros) {
|
|
||||||
SetTimeNanos(kNumNanosecsPerMicrosec * micros);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvanceTime(webrtc::TimeDelta delta);
|
void AdvanceTime(webrtc::TimeDelta delta);
|
||||||
|
|
||||||
|
private:
|
||||||
|
CriticalSection lock_;
|
||||||
|
int64_t time_ns_ RTC_GUARDED_BY(lock_) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ThreadProcessingFakeClock : public ClockInterface {
|
||||||
|
public:
|
||||||
|
int64_t TimeNanos() const override { return clock_.TimeNanos(); }
|
||||||
|
void SetTime(webrtc::Timestamp time);
|
||||||
|
void SetTimeMicros(int64_t micros) {
|
||||||
|
SetTime(webrtc::Timestamp ::us(micros));
|
||||||
|
}
|
||||||
|
void AdvanceTime(webrtc::TimeDelta delta);
|
||||||
void AdvanceTimeMicros(int64_t micros) {
|
void AdvanceTimeMicros(int64_t micros) {
|
||||||
AdvanceTime(webrtc::TimeDelta::us(micros));
|
AdvanceTime(webrtc::TimeDelta::us(micros));
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CriticalSection lock_;
|
FakeClock clock_;
|
||||||
int64_t time_ RTC_GUARDED_BY(lock_) = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Helper class that sets itself as the global clock in its constructor and
|
// Helper class that sets itself as the global clock in its constructor and
|
||||||
// unsets it in its destructor.
|
// unsets it in its destructor.
|
||||||
class ScopedFakeClock : public FakeClock {
|
class ScopedBaseFakeClock : public FakeClock {
|
||||||
|
public:
|
||||||
|
ScopedBaseFakeClock();
|
||||||
|
~ScopedBaseFakeClock() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ClockInterface* prev_clock_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO(srte): Rename this to reflect that it also does thread processing.
|
||||||
|
class ScopedFakeClock : public ThreadProcessingFakeClock {
|
||||||
public:
|
public:
|
||||||
ScopedFakeClock();
|
ScopedFakeClock();
|
||||||
ScopedFakeClock(const ScopedFakeClock&) = delete;
|
|
||||||
ScopedFakeClock& operator=(const ScopedFakeClock&) = delete;
|
|
||||||
~ScopedFakeClock() override;
|
~ScopedFakeClock() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@ -28,7 +28,7 @@ TestClient::TestClient(std::unique_ptr<AsyncPacketSocket> socket)
|
|||||||
: TestClient(std::move(socket), nullptr) {}
|
: TestClient(std::move(socket), nullptr) {}
|
||||||
|
|
||||||
TestClient::TestClient(std::unique_ptr<AsyncPacketSocket> socket,
|
TestClient::TestClient(std::unique_ptr<AsyncPacketSocket> socket,
|
||||||
FakeClock* fake_clock)
|
ThreadProcessingFakeClock* fake_clock)
|
||||||
: fake_clock_(fake_clock),
|
: fake_clock_(fake_clock),
|
||||||
socket_(std::move(socket)),
|
socket_(std::move(socket)),
|
||||||
prev_packet_timestamp_(-1) {
|
prev_packet_timestamp_(-1) {
|
||||||
|
|||||||
@ -48,7 +48,8 @@ class TestClient : public sigslot::has_slots<> {
|
|||||||
// Create a test client that will use a fake clock. NextPacket needs to wait
|
// Create a test client that will use a fake clock. NextPacket needs to wait
|
||||||
// for a packet to be received, and thus it needs to advance the fake clock
|
// for a packet to be received, and thus it needs to advance the fake clock
|
||||||
// if the test is using one, rather than just sleeping.
|
// if the test is using one, rather than just sleeping.
|
||||||
TestClient(std::unique_ptr<AsyncPacketSocket> socket, FakeClock* fake_clock);
|
TestClient(std::unique_ptr<AsyncPacketSocket> socket,
|
||||||
|
ThreadProcessingFakeClock* fake_clock);
|
||||||
~TestClient() override;
|
~TestClient() override;
|
||||||
|
|
||||||
SocketAddress address() const { return socket_->GetLocalAddress(); }
|
SocketAddress address() const { return socket_->GetLocalAddress(); }
|
||||||
@ -102,7 +103,7 @@ class TestClient : public sigslot::has_slots<> {
|
|||||||
bool CheckTimestamp(int64_t packet_timestamp);
|
bool CheckTimestamp(int64_t packet_timestamp);
|
||||||
void AdvanceTime(int ms);
|
void AdvanceTime(int ms);
|
||||||
|
|
||||||
FakeClock* fake_clock_ = nullptr;
|
ThreadProcessingFakeClock* fake_clock_ = nullptr;
|
||||||
CriticalSection crit_;
|
CriticalSection crit_;
|
||||||
std::unique_ptr<AsyncPacketSocket> socket_;
|
std::unique_ptr<AsyncPacketSocket> socket_;
|
||||||
std::vector<std::unique_ptr<Packet>> packets_;
|
std::vector<std::unique_ptr<Packet>> packets_;
|
||||||
|
|||||||
@ -217,11 +217,11 @@ TEST(FakeClock, TimeFunctionsUseFakeClock) {
|
|||||||
FakeClock clock;
|
FakeClock clock;
|
||||||
SetClockForTesting(&clock);
|
SetClockForTesting(&clock);
|
||||||
|
|
||||||
clock.SetTimeNanos(987654321);
|
clock.SetTime(webrtc::Timestamp::us(987654));
|
||||||
EXPECT_EQ(987u, Time32());
|
EXPECT_EQ(987u, Time32());
|
||||||
EXPECT_EQ(987, TimeMillis());
|
EXPECT_EQ(987, TimeMillis());
|
||||||
EXPECT_EQ(987654, TimeMicros());
|
EXPECT_EQ(987654, TimeMicros());
|
||||||
EXPECT_EQ(987654321, TimeNanos());
|
EXPECT_EQ(987654000, TimeNanos());
|
||||||
EXPECT_EQ(1000u, TimeAfter(13));
|
EXPECT_EQ(1000u, TimeAfter(13));
|
||||||
|
|
||||||
SetClockForTesting(nullptr);
|
SetClockForTesting(nullptr);
|
||||||
@ -234,12 +234,12 @@ TEST(FakeClock, InitialTime) {
|
|||||||
EXPECT_EQ(0, clock.TimeNanos());
|
EXPECT_EQ(0, clock.TimeNanos());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(FakeClock, SetTimeNanos) {
|
TEST(FakeClock, SetTime) {
|
||||||
FakeClock clock;
|
FakeClock clock;
|
||||||
clock.SetTimeNanos(123);
|
clock.SetTime(webrtc::Timestamp::us(123));
|
||||||
EXPECT_EQ(123, clock.TimeNanos());
|
EXPECT_EQ(123000, clock.TimeNanos());
|
||||||
clock.SetTimeNanos(456);
|
clock.SetTime(webrtc::Timestamp::us(456));
|
||||||
EXPECT_EQ(456, clock.TimeNanos());
|
EXPECT_EQ(456000, clock.TimeNanos());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(FakeClock, AdvanceTime) {
|
TEST(FakeClock, AdvanceTime) {
|
||||||
@ -261,7 +261,7 @@ TEST(FakeClock, AdvanceTime) {
|
|||||||
TEST(FakeClock, SettingTimeWakesThreads) {
|
TEST(FakeClock, SettingTimeWakesThreads) {
|
||||||
int64_t real_start_time_ms = TimeMillis();
|
int64_t real_start_time_ms = TimeMillis();
|
||||||
|
|
||||||
FakeClock clock;
|
ThreadProcessingFakeClock clock;
|
||||||
SetClockForTesting(&clock);
|
SetClockForTesting(&clock);
|
||||||
|
|
||||||
std::unique_ptr<Thread> worker(Thread::CreateWithSocketServer());
|
std::unique_ptr<Thread> worker(Thread::CreateWithSocketServer());
|
||||||
|
|||||||
@ -523,7 +523,7 @@ void VirtualSocket::OnSocketServerReadyToSend() {
|
|||||||
|
|
||||||
VirtualSocketServer::VirtualSocketServer() : VirtualSocketServer(nullptr) {}
|
VirtualSocketServer::VirtualSocketServer() : VirtualSocketServer(nullptr) {}
|
||||||
|
|
||||||
VirtualSocketServer::VirtualSocketServer(FakeClock* fake_clock)
|
VirtualSocketServer::VirtualSocketServer(ThreadProcessingFakeClock* fake_clock)
|
||||||
: fake_clock_(fake_clock),
|
: fake_clock_(fake_clock),
|
||||||
msg_queue_(nullptr),
|
msg_queue_(nullptr),
|
||||||
stop_on_idle_(false),
|
stop_on_idle_(false),
|
||||||
|
|||||||
@ -37,7 +37,7 @@ class VirtualSocketServer : public SocketServer, public sigslot::has_slots<> {
|
|||||||
// This constructor needs to be used if the test uses a fake clock and
|
// This constructor needs to be used if the test uses a fake clock and
|
||||||
// ProcessMessagesUntilIdle, since ProcessMessagesUntilIdle needs a way of
|
// ProcessMessagesUntilIdle, since ProcessMessagesUntilIdle needs a way of
|
||||||
// advancing time.
|
// advancing time.
|
||||||
explicit VirtualSocketServer(FakeClock* fake_clock);
|
explicit VirtualSocketServer(ThreadProcessingFakeClock* fake_clock);
|
||||||
~VirtualSocketServer() override;
|
~VirtualSocketServer() override;
|
||||||
|
|
||||||
// The default route indicates which local address to use when a socket is
|
// The default route indicates which local address to use when a socket is
|
||||||
@ -263,7 +263,7 @@ class VirtualSocketServer : public SocketServer, public sigslot::has_slots<> {
|
|||||||
|
|
||||||
// May be null if the test doesn't use a fake clock, or it does but doesn't
|
// May be null if the test doesn't use a fake clock, or it does but doesn't
|
||||||
// use ProcessMessagesUntilIdle.
|
// use ProcessMessagesUntilIdle.
|
||||||
FakeClock* fake_clock_ = nullptr;
|
ThreadProcessingFakeClock* fake_clock_ = nullptr;
|
||||||
|
|
||||||
// Used to implement Wait/WakeUp.
|
// Used to implement Wait/WakeUp.
|
||||||
Event wakeup_;
|
Event wakeup_;
|
||||||
|
|||||||
@ -401,7 +401,7 @@ void SimulatedTimeControllerImpl::Unregister(SimulatedSequenceRunner* runner) {
|
|||||||
GlobalSimulatedTimeController::GlobalSimulatedTimeController(
|
GlobalSimulatedTimeController::GlobalSimulatedTimeController(
|
||||||
Timestamp start_time)
|
Timestamp start_time)
|
||||||
: sim_clock_(start_time.us()), impl_(start_time) {
|
: sim_clock_(start_time.us()), impl_(start_time) {
|
||||||
global_clock_.SetTimeMicros(start_time.us());
|
global_clock_.SetTime(start_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalSimulatedTimeController::~GlobalSimulatedTimeController() = default;
|
GlobalSimulatedTimeController::~GlobalSimulatedTimeController() = default;
|
||||||
@ -431,7 +431,7 @@ void GlobalSimulatedTimeController::Sleep(TimeDelta duration) {
|
|||||||
auto delta = next_time - current_time;
|
auto delta = next_time - current_time;
|
||||||
current_time = next_time;
|
current_time = next_time;
|
||||||
sim_clock_.AdvanceTimeMicroseconds(delta.us());
|
sim_clock_.AdvanceTimeMicroseconds(delta.us());
|
||||||
global_clock_.AdvanceTimeMicros(delta.us());
|
global_clock_.AdvanceTime(delta);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -94,7 +94,7 @@ class GlobalSimulatedTimeController : public TimeController {
|
|||||||
void InvokeWithControlledYield(std::function<void()> closure) override;
|
void InvokeWithControlledYield(std::function<void()> closure) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
rtc::ScopedFakeClock global_clock_;
|
rtc::ScopedBaseFakeClock global_clock_;
|
||||||
// Provides simulated CurrentNtpInMilliseconds()
|
// Provides simulated CurrentNtpInMilliseconds()
|
||||||
SimulatedClock sim_clock_;
|
SimulatedClock sim_clock_;
|
||||||
sim_time_impl::SimulatedTimeControllerImpl impl_;
|
sim_time_impl::SimulatedTimeControllerImpl impl_;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user