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