1 #include "TestLatency.h"
2 
3 #include "IPDLUnitTests.h"  // fail etc.
4 
5 // A ping/pong trial takes O(100us) or more, so if we don't have 10us
6 // resolution or better, the results will not be terribly useful
7 static const double kTimingResolutionCutoff = 0.00001;  // 10us
8 
9 namespace mozilla {
10 namespace _ipdltest {
11 
12 //-----------------------------------------------------------------------------
13 // parent
14 
TestLatencyParent()15 TestLatencyParent::TestLatencyParent()
16     : mStart(),
17       mPPTimeTotal(),
18       mPP5TimeTotal(),
19       mRpcTimeTotal(),
20       mPPTrialsToGo(NR_TRIALS),
21       mPP5TrialsToGo(NR_TRIALS),
22       mNumChildProcessedCompressedSpams(0),
23       mWhichPong5(0) {
24   MOZ_COUNT_CTOR(TestLatencyParent);
25 }
26 
~TestLatencyParent()27 TestLatencyParent::~TestLatencyParent() { MOZ_COUNT_DTOR(TestLatencyParent); }
28 
Main()29 void TestLatencyParent::Main() {
30   TimeDuration resolution = TimeDuration::Resolution();
31   if (resolution.ToSeconds() > kTimingResolutionCutoff) {
32     puts("  (skipping TestLatency, timing resolution is too poor)");
33     Close();
34     return;
35   }
36 
37   printf("  timing resolution: %g seconds\n", resolution.ToSecondsSigDigits());
38 
39   if (mozilla::ipc::LoggingEnabled())
40     MOZ_CRASH(
41         "you really don't want to log all IPC messages during this test, trust "
42         "me");
43 
44   PingPongTrial();
45 }
46 
PingPongTrial()47 void TestLatencyParent::PingPongTrial() {
48   mStart = TimeStamp::Now();
49   if (!SendPing()) fail("sending Ping()");
50 }
51 
Ping5Pong5Trial()52 void TestLatencyParent::Ping5Pong5Trial() {
53   mStart = TimeStamp::Now();
54 
55   if (!SendPing5() || !SendPing5() || !SendPing5() || !SendPing5() ||
56       !SendPing5())
57     fail("sending Ping5()");
58 }
59 
RecvPong()60 mozilla::ipc::IPCResult TestLatencyParent::RecvPong() {
61   TimeDuration thisTrial = (TimeStamp::Now() - mStart);
62   mPPTimeTotal += thisTrial;
63 
64   if (0 == (mPPTrialsToGo % 1000))
65     printf("  PP trial %d: %g\n", mPPTrialsToGo,
66            thisTrial.ToSecondsSigDigits());
67 
68   if (--mPPTrialsToGo > 0)
69     PingPongTrial();
70   else
71     Ping5Pong5Trial();
72   return IPC_OK();
73 }
74 
RecvPong5()75 mozilla::ipc::IPCResult TestLatencyParent::RecvPong5() {
76   ++mWhichPong5;
77 
78   if (mWhichPong5 < 5) {
79     return IPC_OK();
80   }
81 
82   mWhichPong5 = 0;
83 
84   TimeDuration thisTrial = (TimeStamp::Now() - mStart);
85   mPP5TimeTotal += thisTrial;
86 
87   if (0 == (mPP5TrialsToGo % 1000))
88     printf("  PP5 trial %d: %g\n", mPP5TrialsToGo,
89            thisTrial.ToSecondsSigDigits());
90 
91   if (0 < --mPP5TrialsToGo)
92     Ping5Pong5Trial();
93   else
94     RpcTrials();
95 
96   return IPC_OK();
97 }
98 
RpcTrials()99 void TestLatencyParent::RpcTrials() {
100   TimeStamp start = TimeStamp::Now();
101   for (int i = 0; i < NR_TRIALS; ++i) {
102     if (!CallRpc()) fail("can't call Rpc()");
103     if (0 == (i % 1000)) printf("  Rpc trial %d\n", i);
104   }
105   mRpcTimeTotal = (TimeStamp::Now() - start);
106 
107   SpamTrial();
108 }
109 
SpamTrial()110 void TestLatencyParent::SpamTrial() {
111   TimeStamp start = TimeStamp::Now();
112   for (int i = 0; i < NR_SPAMS - 1; ++i) {
113     if (!SendSpam()) fail("sending Spam()");
114     if (0 == (i % 10000)) printf("  Spam trial %d\n", i);
115   }
116 
117   // Synchronize with the child process to ensure all messages have
118   // been processed.  This adds the overhead of a reply message from
119   // child-->here, but should be insignificant compared to >>
120   // NR_SPAMS.
121   if (!CallSynchro()) fail("calling Synchro()");
122 
123   mSpamTimeTotal = (TimeStamp::Now() - start);
124 
125   CompressedSpamTrial();
126 }
127 
CompressedSpamTrial()128 void TestLatencyParent::CompressedSpamTrial() {
129   for (int i = 0; i < NR_SPAMS; ++i) {
130     if (!SendCompressedSpam(i + 1)) fail("sending CompressedSpam()");
131     if (0 == (i % 10000)) printf("  CompressedSpam trial %d\n", i);
132   }
133 
134   uint32_t lastSeqno;
135   if (!CallSynchro2(&lastSeqno, &mNumChildProcessedCompressedSpams))
136     fail("calling Synchro2()");
137 
138   if (lastSeqno != NR_SPAMS)
139     fail("last seqno was %u, expected %u", lastSeqno, NR_SPAMS);
140 
141   // NB: since this is testing an optimization, it's somewhat bogus.
142   // Need to make a warning if it actually intermittently fails in
143   // practice, which is doubtful.
144   if (!(mNumChildProcessedCompressedSpams < NR_SPAMS))
145     fail("Didn't compress any messages?");
146 
147   Exit();
148 }
149 
Exit()150 void TestLatencyParent::Exit() { Close(); }
151 
152 //-----------------------------------------------------------------------------
153 // child
154 
TestLatencyChild()155 TestLatencyChild::TestLatencyChild()
156     : mLastSeqno(0), mNumProcessedCompressedSpams(0), mWhichPing5(0) {
157   MOZ_COUNT_CTOR(TestLatencyChild);
158 }
159 
~TestLatencyChild()160 TestLatencyChild::~TestLatencyChild() { MOZ_COUNT_DTOR(TestLatencyChild); }
161 
RecvPing()162 mozilla::ipc::IPCResult TestLatencyChild::RecvPing() {
163   SendPong();
164   return IPC_OK();
165 }
166 
RecvPing5()167 mozilla::ipc::IPCResult TestLatencyChild::RecvPing5() {
168   ++mWhichPing5;
169 
170   if (mWhichPing5 < 5) {
171     return IPC_OK();
172   }
173 
174   mWhichPing5 = 0;
175 
176   if (!SendPong5() || !SendPong5() || !SendPong5() || !SendPong5() ||
177       !SendPong5())
178     fail("sending Pong5()");
179 
180   return IPC_OK();
181 }
182 
AnswerRpc()183 mozilla::ipc::IPCResult TestLatencyChild::AnswerRpc() { return IPC_OK(); }
184 
RecvSpam()185 mozilla::ipc::IPCResult TestLatencyChild::RecvSpam() {
186   // no-op
187   return IPC_OK();
188 }
189 
AnswerSynchro()190 mozilla::ipc::IPCResult TestLatencyChild::AnswerSynchro() { return IPC_OK(); }
191 
RecvCompressedSpam(const uint32_t & seqno)192 mozilla::ipc::IPCResult TestLatencyChild::RecvCompressedSpam(
193     const uint32_t& seqno) {
194   if (seqno <= mLastSeqno)
195     fail("compressed seqnos must monotonically increase");
196 
197   mLastSeqno = seqno;
198   ++mNumProcessedCompressedSpams;
199   return IPC_OK();
200 }
201 
AnswerSynchro2(uint32_t * lastSeqno,uint32_t * numMessagesDispatched)202 mozilla::ipc::IPCResult TestLatencyChild::AnswerSynchro2(
203     uint32_t* lastSeqno, uint32_t* numMessagesDispatched) {
204   *lastSeqno = mLastSeqno;
205   *numMessagesDispatched = mNumProcessedCompressedSpams;
206   return IPC_OK();
207 }
208 
209 }  // namespace _ipdltest
210 }  // namespace mozilla
211