diff options
Diffstat (limited to 'ipc/ipdl/test/cxx/TestLatency.cpp')
-rw-r--r-- | ipc/ipdl/test/cxx/TestLatency.cpp | 210 |
1 files changed, 210 insertions, 0 deletions
diff --git a/ipc/ipdl/test/cxx/TestLatency.cpp b/ipc/ipdl/test/cxx/TestLatency.cpp new file mode 100644 index 0000000000..f88d8ea644 --- /dev/null +++ b/ipc/ipdl/test/cxx/TestLatency.cpp @@ -0,0 +1,210 @@ +#include "TestLatency.h" + +#include "IPDLUnitTests.h" // fail etc. + +// A ping/pong trial takes O(100us) or more, so if we don't have 10us +// resolution or better, the results will not be terribly useful +static const double kTimingResolutionCutoff = 0.00001; // 10us + +namespace mozilla { +namespace _ipdltest { + +//----------------------------------------------------------------------------- +// parent + +TestLatencyParent::TestLatencyParent() + : mStart(), + mPPTimeTotal(), + mPP5TimeTotal(), + mRpcTimeTotal(), + mPPTrialsToGo(NR_TRIALS), + mPP5TrialsToGo(NR_TRIALS), + mNumChildProcessedCompressedSpams(0), + mWhichPong5(0) { + MOZ_COUNT_CTOR(TestLatencyParent); +} + +TestLatencyParent::~TestLatencyParent() { MOZ_COUNT_DTOR(TestLatencyParent); } + +void TestLatencyParent::Main() { + TimeDuration resolution = TimeDuration::Resolution(); + if (resolution.ToSeconds() > kTimingResolutionCutoff) { + puts(" (skipping TestLatency, timing resolution is too poor)"); + Close(); + return; + } + + printf(" timing resolution: %g seconds\n", resolution.ToSecondsSigDigits()); + + if (mozilla::ipc::LoggingEnabled()) + MOZ_CRASH( + "you really don't want to log all IPC messages during this test, trust " + "me"); + + PingPongTrial(); +} + +void TestLatencyParent::PingPongTrial() { + mStart = TimeStamp::Now(); + if (!SendPing()) fail("sending Ping()"); +} + +void TestLatencyParent::Ping5Pong5Trial() { + mStart = TimeStamp::Now(); + + if (!SendPing5() || !SendPing5() || !SendPing5() || !SendPing5() || + !SendPing5()) + fail("sending Ping5()"); +} + +mozilla::ipc::IPCResult TestLatencyParent::RecvPong() { + TimeDuration thisTrial = (TimeStamp::Now() - mStart); + mPPTimeTotal += thisTrial; + + if (0 == (mPPTrialsToGo % 1000)) + printf(" PP trial %d: %g\n", mPPTrialsToGo, + thisTrial.ToSecondsSigDigits()); + + if (--mPPTrialsToGo > 0) + PingPongTrial(); + else + Ping5Pong5Trial(); + return IPC_OK(); +} + +mozilla::ipc::IPCResult TestLatencyParent::RecvPong5() { + ++mWhichPong5; + + if (mWhichPong5 < 5) { + return IPC_OK(); + } + + mWhichPong5 = 0; + + TimeDuration thisTrial = (TimeStamp::Now() - mStart); + mPP5TimeTotal += thisTrial; + + if (0 == (mPP5TrialsToGo % 1000)) + printf(" PP5 trial %d: %g\n", mPP5TrialsToGo, + thisTrial.ToSecondsSigDigits()); + + if (0 < --mPP5TrialsToGo) + Ping5Pong5Trial(); + else + RpcTrials(); + + return IPC_OK(); +} + +void TestLatencyParent::RpcTrials() { + TimeStamp start = TimeStamp::Now(); + for (int i = 0; i < NR_TRIALS; ++i) { + if (!CallRpc()) fail("can't call Rpc()"); + if (0 == (i % 1000)) printf(" Rpc trial %d\n", i); + } + mRpcTimeTotal = (TimeStamp::Now() - start); + + SpamTrial(); +} + +void TestLatencyParent::SpamTrial() { + TimeStamp start = TimeStamp::Now(); + for (int i = 0; i < NR_SPAMS - 1; ++i) { + if (!SendSpam()) fail("sending Spam()"); + if (0 == (i % 10000)) printf(" Spam trial %d\n", i); + } + + // Synchronize with the child process to ensure all messages have + // been processed. This adds the overhead of a reply message from + // child-->here, but should be insignificant compared to >> + // NR_SPAMS. + if (!CallSynchro()) fail("calling Synchro()"); + + mSpamTimeTotal = (TimeStamp::Now() - start); + + CompressedSpamTrial(); +} + +void TestLatencyParent::CompressedSpamTrial() { + for (int i = 0; i < NR_SPAMS; ++i) { + if (!SendCompressedSpam(i + 1)) fail("sending CompressedSpam()"); + if (0 == (i % 10000)) printf(" CompressedSpam trial %d\n", i); + } + + uint32_t lastSeqno; + if (!CallSynchro2(&lastSeqno, &mNumChildProcessedCompressedSpams)) + fail("calling Synchro2()"); + + if (lastSeqno != NR_SPAMS) + fail("last seqno was %u, expected %u", lastSeqno, NR_SPAMS); + + // NB: since this is testing an optimization, it's somewhat bogus. + // Need to make a warning if it actually intermittently fails in + // practice, which is doubtful. + if (!(mNumChildProcessedCompressedSpams < NR_SPAMS)) + fail("Didn't compress any messages?"); + + Exit(); +} + +void TestLatencyParent::Exit() { Close(); } + +//----------------------------------------------------------------------------- +// child + +TestLatencyChild::TestLatencyChild() + : mLastSeqno(0), mNumProcessedCompressedSpams(0), mWhichPing5(0) { + MOZ_COUNT_CTOR(TestLatencyChild); +} + +TestLatencyChild::~TestLatencyChild() { MOZ_COUNT_DTOR(TestLatencyChild); } + +mozilla::ipc::IPCResult TestLatencyChild::RecvPing() { + SendPong(); + return IPC_OK(); +} + +mozilla::ipc::IPCResult TestLatencyChild::RecvPing5() { + ++mWhichPing5; + + if (mWhichPing5 < 5) { + return IPC_OK(); + } + + mWhichPing5 = 0; + + if (!SendPong5() || !SendPong5() || !SendPong5() || !SendPong5() || + !SendPong5()) + fail("sending Pong5()"); + + return IPC_OK(); +} + +mozilla::ipc::IPCResult TestLatencyChild::AnswerRpc() { return IPC_OK(); } + +mozilla::ipc::IPCResult TestLatencyChild::RecvSpam() { + // no-op + return IPC_OK(); +} + +mozilla::ipc::IPCResult TestLatencyChild::AnswerSynchro() { return IPC_OK(); } + +mozilla::ipc::IPCResult TestLatencyChild::RecvCompressedSpam( + const uint32_t& seqno) { + if (seqno <= mLastSeqno) + fail("compressed seqnos must monotonically increase"); + + mLastSeqno = seqno; + ++mNumProcessedCompressedSpams; + return IPC_OK(); +} + +mozilla::ipc::IPCResult TestLatencyChild::AnswerSynchro2( + uint32_t* lastSeqno, uint32_t* numMessagesDispatched) { + *lastSeqno = mLastSeqno; + *numMessagesDispatched = mNumProcessedCompressedSpams; + return IPC_OK(); +} + +} // namespace _ipdltest +} // namespace mozilla |