OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <vector> | 5 #include <vector> |
6 | 6 |
7 #include "src/counters-inl.h" | |
8 #include "src/counters.h" | 7 #include "src/counters.h" |
9 #include "src/handles-inl.h" | 8 #include "src/handles-inl.h" |
10 #include "src/objects-inl.h" | 9 #include "src/objects-inl.h" |
11 #include "src/tracing/tracing-category-observer.h" | |
12 #include "testing/gtest/include/gtest/gtest.h" | 10 #include "testing/gtest/include/gtest/gtest.h" |
13 | 11 |
14 namespace v8 { | 12 namespace v8 { |
15 namespace internal { | 13 namespace internal { |
16 | 14 |
17 namespace { | 15 namespace { |
18 | 16 |
19 class MockHistogram : public Histogram { | 17 class MockHistogram : public Histogram { |
20 public: | 18 public: |
21 void AddSample(int value) { samples_.push_back(value); } | 19 void AddSample(int value) { samples_.push_back(value); } |
(...skipping 15 matching lines...) Expand all Loading... |
37 aggregated_.AddSample(current_ms, current_value); | 35 aggregated_.AddSample(current_ms, current_value); |
38 } | 36 } |
39 | 37 |
40 std::vector<int>* samples() { return mock_.samples(); } | 38 std::vector<int>* samples() { return mock_.samples(); } |
41 | 39 |
42 private: | 40 private: |
43 AggregatedMemoryHistogram<MockHistogram> aggregated_; | 41 AggregatedMemoryHistogram<MockHistogram> aggregated_; |
44 MockHistogram mock_; | 42 MockHistogram mock_; |
45 }; | 43 }; |
46 | 44 |
47 class RuntimeCallStatsTest : public ::testing::Test { | |
48 public: | |
49 RuntimeCallStatsTest() { | |
50 FLAG_runtime_stats = | |
51 v8::tracing::TracingCategoryObserver::ENABLED_BY_NATIVE; | |
52 } | |
53 virtual ~RuntimeCallStatsTest() {} | |
54 | |
55 RuntimeCallStats* stats() { return &stats_; } | |
56 RuntimeCallStats::CounterId counter_id() { | |
57 return &RuntimeCallStats::TestCounter1; | |
58 } | |
59 RuntimeCallStats::CounterId counter_id2() { | |
60 return &RuntimeCallStats::TestCounter2; | |
61 } | |
62 RuntimeCallStats::CounterId counter_id3() { | |
63 return &RuntimeCallStats::TestCounter3; | |
64 } | |
65 RuntimeCallCounter* counter() { return &(stats()->*counter_id()); } | |
66 RuntimeCallCounter* counter2() { return &(stats()->*counter_id2()); } | |
67 RuntimeCallCounter* counter3() { return &(stats()->*counter_id3()); } | |
68 void Sleep(int32_t milliseconds) { | |
69 base::ElapsedTimer timer; | |
70 base::TimeDelta delta = base::TimeDelta::FromMilliseconds(milliseconds); | |
71 timer.Start(); | |
72 while (!timer.HasExpired(delta)) { | |
73 base::OS::Sleep(base::TimeDelta::FromMicroseconds(0)); | |
74 } | |
75 } | |
76 | |
77 const uint32_t kEpsilonMs = 10; | |
78 | |
79 private: | |
80 RuntimeCallStats stats_; | |
81 }; | |
82 | |
83 } // namespace | 45 } // namespace |
84 | 46 |
85 | 47 |
86 TEST_F(AggregatedMemoryHistogramTest, OneSample1) { | 48 TEST_F(AggregatedMemoryHistogramTest, OneSample1) { |
87 FLAG_histogram_interval = 10; | 49 FLAG_histogram_interval = 10; |
88 AddSample(10, 1000); | 50 AddSample(10, 1000); |
89 AddSample(20, 1000); | 51 AddSample(20, 1000); |
90 EXPECT_EQ(1U, samples()->size()); | 52 EXPECT_EQ(1U, samples()->size()); |
91 EXPECT_EQ(1000, (*samples())[0]); | 53 EXPECT_EQ(1000, (*samples())[0]); |
92 } | 54 } |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
226 FLAG_histogram_interval = 10; | 188 FLAG_histogram_interval = 10; |
227 const int kMaxSamples = 1000; | 189 const int kMaxSamples = 1000; |
228 AddSample(0, 0); | 190 AddSample(0, 0); |
229 AddSample(10 * (2 * kMaxSamples), 10 * (2 * kMaxSamples)); | 191 AddSample(10 * (2 * kMaxSamples), 10 * (2 * kMaxSamples)); |
230 EXPECT_EQ(static_cast<unsigned>(kMaxSamples), samples()->size()); | 192 EXPECT_EQ(static_cast<unsigned>(kMaxSamples), samples()->size()); |
231 for (int i = 0; i < kMaxSamples; i++) { | 193 for (int i = 0; i < kMaxSamples; i++) { |
232 EXPECT_EQ(i * 10 + 5, (*samples())[i]); | 194 EXPECT_EQ(i * 10 + 5, (*samples())[i]); |
233 } | 195 } |
234 } | 196 } |
235 | 197 |
236 #define EXPECT_IN_RANGE(start, value, end) \ | |
237 EXPECT_LE(start, value); \ | |
238 EXPECT_GE(end, value) | |
239 | |
240 TEST_F(RuntimeCallStatsTest, RuntimeCallTimer) { | |
241 RuntimeCallTimer timer; | |
242 | |
243 Sleep(50); | |
244 RuntimeCallStats::Enter(stats(), &timer, counter_id()); | |
245 EXPECT_EQ(counter(), timer.counter()); | |
246 EXPECT_EQ(nullptr, timer.parent()); | |
247 EXPECT_TRUE(timer.IsStarted()); | |
248 EXPECT_EQ(&timer, stats()->current_timer()); | |
249 | |
250 Sleep(100); | |
251 | |
252 RuntimeCallStats::Leave(stats(), &timer); | |
253 Sleep(50); | |
254 EXPECT_FALSE(timer.IsStarted()); | |
255 EXPECT_EQ(1, counter()->count()); | |
256 EXPECT_IN_RANGE(100, counter()->time().InMilliseconds(), 100 + kEpsilonMs); | |
257 } | |
258 | |
259 TEST_F(RuntimeCallStatsTest, RuntimeCallTimerSubTimer) { | |
260 RuntimeCallTimer timer; | |
261 RuntimeCallTimer timer2; | |
262 | |
263 RuntimeCallStats::Enter(stats(), &timer, counter_id()); | |
264 EXPECT_TRUE(timer.IsStarted()); | |
265 EXPECT_FALSE(timer2.IsStarted()); | |
266 EXPECT_EQ(counter(), timer.counter()); | |
267 EXPECT_EQ(nullptr, timer.parent()); | |
268 EXPECT_EQ(&timer, stats()->current_timer()); | |
269 | |
270 Sleep(50); | |
271 | |
272 RuntimeCallStats::Enter(stats(), &timer2, counter_id2()); | |
273 // timer 1 is paused, while timer 2 is active. | |
274 EXPECT_TRUE(timer2.IsStarted()); | |
275 EXPECT_EQ(counter(), timer.counter()); | |
276 EXPECT_EQ(counter2(), timer2.counter()); | |
277 EXPECT_EQ(nullptr, timer.parent()); | |
278 EXPECT_EQ(&timer, timer2.parent()); | |
279 EXPECT_EQ(&timer2, stats()->current_timer()); | |
280 | |
281 Sleep(100); | |
282 RuntimeCallStats::Leave(stats(), &timer2); | |
283 | |
284 // The subtimer subtracts its time from the parent timer. | |
285 EXPECT_TRUE(timer.IsStarted()); | |
286 EXPECT_FALSE(timer2.IsStarted()); | |
287 EXPECT_EQ(0, counter()->count()); | |
288 EXPECT_EQ(1, counter2()->count()); | |
289 EXPECT_EQ(0, counter()->time().InMilliseconds()); | |
290 EXPECT_IN_RANGE(100, counter2()->time().InMilliseconds(), 100 + kEpsilonMs); | |
291 EXPECT_EQ(&timer, stats()->current_timer()); | |
292 | |
293 Sleep(100); | |
294 | |
295 RuntimeCallStats::Leave(stats(), &timer); | |
296 EXPECT_FALSE(timer.IsStarted()); | |
297 EXPECT_EQ(1, counter()->count()); | |
298 EXPECT_EQ(1, counter2()->count()); | |
299 EXPECT_IN_RANGE(150, counter()->time().InMilliseconds(), 150 + kEpsilonMs); | |
300 EXPECT_IN_RANGE(100, counter2()->time().InMilliseconds(), 100 + kEpsilonMs); | |
301 EXPECT_EQ(nullptr, stats()->current_timer()); | |
302 } | |
303 | |
304 TEST_F(RuntimeCallStatsTest, RuntimeCallTimerRecursive) { | |
305 RuntimeCallTimer timer; | |
306 RuntimeCallTimer timer2; | |
307 | |
308 RuntimeCallStats::Enter(stats(), &timer, counter_id()); | |
309 EXPECT_EQ(counter(), timer.counter()); | |
310 EXPECT_EQ(nullptr, timer.parent()); | |
311 EXPECT_TRUE(timer.IsStarted()); | |
312 EXPECT_EQ(&timer, stats()->current_timer()); | |
313 | |
314 RuntimeCallStats::Enter(stats(), &timer2, counter_id()); | |
315 EXPECT_EQ(counter(), timer2.counter()); | |
316 EXPECT_EQ(nullptr, timer.parent()); | |
317 EXPECT_EQ(&timer, timer2.parent()); | |
318 EXPECT_TRUE(timer2.IsStarted()); | |
319 EXPECT_EQ(&timer2, stats()->current_timer()); | |
320 | |
321 Sleep(50); | |
322 | |
323 RuntimeCallStats::Leave(stats(), &timer2); | |
324 EXPECT_EQ(nullptr, timer.parent()); | |
325 EXPECT_FALSE(timer2.IsStarted()); | |
326 EXPECT_TRUE(timer.IsStarted()); | |
327 EXPECT_EQ(1, counter()->count()); | |
328 EXPECT_IN_RANGE(50, counter()->time().InMilliseconds(), 50 + kEpsilonMs); | |
329 | |
330 Sleep(100); | |
331 | |
332 RuntimeCallStats::Leave(stats(), &timer); | |
333 EXPECT_FALSE(timer.IsStarted()); | |
334 EXPECT_EQ(2, counter()->count()); | |
335 EXPECT_IN_RANGE(150, counter()->time().InMilliseconds(), | |
336 150 + 2 * kEpsilonMs); | |
337 } | |
338 | |
339 TEST_F(RuntimeCallStatsTest, RuntimeCallTimerScope) { | |
340 { | |
341 RuntimeCallTimerScope scope(stats(), counter_id()); | |
342 Sleep(50); | |
343 } | |
344 Sleep(100); | |
345 EXPECT_EQ(1, counter()->count()); | |
346 EXPECT_IN_RANGE(50, counter()->time().InMilliseconds(), 50 + kEpsilonMs); | |
347 { | |
348 RuntimeCallTimerScope scope(stats(), counter_id()); | |
349 Sleep(50); | |
350 } | |
351 EXPECT_EQ(2, counter()->count()); | |
352 EXPECT_IN_RANGE(100, counter()->time().InMilliseconds(), | |
353 100 + 2 * kEpsilonMs); | |
354 } | |
355 | |
356 TEST_F(RuntimeCallStatsTest, RuntimeCallTimerScopeRecursive) { | |
357 { | |
358 RuntimeCallTimerScope scope(stats(), counter_id()); | |
359 Sleep(50); | |
360 EXPECT_EQ(0, counter()->count()); | |
361 EXPECT_EQ(0, counter()->time().InMilliseconds()); | |
362 { | |
363 RuntimeCallTimerScope scope(stats(), counter_id()); | |
364 Sleep(50); | |
365 } | |
366 EXPECT_EQ(1, counter()->count()); | |
367 EXPECT_IN_RANGE(50, counter()->time().InMilliseconds(), 50 + kEpsilonMs); | |
368 } | |
369 EXPECT_EQ(2, counter()->count()); | |
370 EXPECT_IN_RANGE(100, counter()->time().InMilliseconds(), | |
371 100 + 2 * kEpsilonMs); | |
372 } | |
373 | |
374 TEST_F(RuntimeCallStatsTest, RenameTimer) { | |
375 { | |
376 RuntimeCallTimerScope scope(stats(), counter_id()); | |
377 Sleep(50); | |
378 EXPECT_EQ(0, counter()->count()); | |
379 EXPECT_EQ(0, counter2()->count()); | |
380 EXPECT_EQ(0, counter()->time().InMilliseconds()); | |
381 EXPECT_EQ(0, counter2()->time().InMilliseconds()); | |
382 { | |
383 RuntimeCallTimerScope scope(stats(), counter_id()); | |
384 Sleep(100); | |
385 } | |
386 CHANGE_CURRENT_RUNTIME_COUNTER(stats(), TestCounter2); | |
387 EXPECT_EQ(1, counter()->count()); | |
388 EXPECT_EQ(0, counter2()->count()); | |
389 EXPECT_IN_RANGE(100, counter()->time().InMilliseconds(), 100 + kEpsilonMs); | |
390 EXPECT_IN_RANGE(0, counter2()->time().InMilliseconds(), 0); | |
391 } | |
392 EXPECT_EQ(1, counter()->count()); | |
393 EXPECT_EQ(1, counter2()->count()); | |
394 EXPECT_IN_RANGE(100, counter()->time().InMilliseconds(), 100 + kEpsilonMs); | |
395 EXPECT_IN_RANGE(50, counter2()->time().InMilliseconds(), 50 + kEpsilonMs); | |
396 } | |
397 | |
398 TEST_F(RuntimeCallStatsTest, BasicPrintAndSnapshot) { | |
399 std::ostringstream out; | |
400 stats()->Print(out); | |
401 EXPECT_EQ(0, counter()->count()); | |
402 EXPECT_EQ(0, counter2()->count()); | |
403 EXPECT_EQ(0, counter3()->count()); | |
404 EXPECT_EQ(0, counter()->time().InMilliseconds()); | |
405 EXPECT_EQ(0, counter2()->time().InMilliseconds()); | |
406 EXPECT_EQ(0, counter3()->time().InMilliseconds()); | |
407 | |
408 { | |
409 RuntimeCallTimerScope scope(stats(), counter_id()); | |
410 Sleep(50); | |
411 stats()->Print(out); | |
412 } | |
413 stats()->Print(out); | |
414 EXPECT_EQ(1, counter()->count()); | |
415 EXPECT_EQ(0, counter2()->count()); | |
416 EXPECT_EQ(0, counter3()->count()); | |
417 EXPECT_IN_RANGE(50, counter()->time().InMilliseconds(), 50 + kEpsilonMs); | |
418 EXPECT_EQ(0, counter2()->time().InMilliseconds()); | |
419 EXPECT_EQ(0, counter3()->time().InMilliseconds()); | |
420 } | |
421 | |
422 TEST_F(RuntimeCallStatsTest, PrintAndSnapshot) { | |
423 { | |
424 RuntimeCallTimerScope scope(stats(), counter_id()); | |
425 Sleep(100); | |
426 EXPECT_EQ(0, counter()->count()); | |
427 EXPECT_EQ(0, counter()->time().InMilliseconds()); | |
428 { | |
429 RuntimeCallTimerScope scope(stats(), counter_id2()); | |
430 EXPECT_EQ(0, counter2()->count()); | |
431 EXPECT_EQ(0, counter2()->time().InMilliseconds()); | |
432 Sleep(50); | |
433 | |
434 // This calls Snapshot on the current active timer and sychronizes and | |
435 // commits the whole timer stack. | |
436 std::ostringstream out; | |
437 stats()->Print(out); | |
438 EXPECT_EQ(0, counter()->count()); | |
439 EXPECT_EQ(0, counter2()->count()); | |
440 EXPECT_IN_RANGE(100, counter()->time().InMilliseconds(), | |
441 100 + kEpsilonMs); | |
442 EXPECT_IN_RANGE(50, counter2()->time().InMilliseconds(), 50 + kEpsilonMs); | |
443 // Calling Print several times shouldn't have a (big) impact on the | |
444 // measured times. | |
445 stats()->Print(out); | |
446 EXPECT_EQ(0, counter()->count()); | |
447 EXPECT_EQ(0, counter2()->count()); | |
448 EXPECT_IN_RANGE(100, counter()->time().InMilliseconds(), | |
449 100 + kEpsilonMs); | |
450 EXPECT_IN_RANGE(50, counter2()->time().InMilliseconds(), 50 + kEpsilonMs); | |
451 | |
452 Sleep(50); | |
453 stats()->Print(out); | |
454 EXPECT_EQ(0, counter()->count()); | |
455 EXPECT_EQ(0, counter2()->count()); | |
456 EXPECT_IN_RANGE(100, counter()->time().InMilliseconds(), | |
457 100 + kEpsilonMs); | |
458 EXPECT_IN_RANGE(100, counter2()->time().InMilliseconds(), | |
459 100 + kEpsilonMs); | |
460 Sleep(50); | |
461 } | |
462 Sleep(50); | |
463 EXPECT_EQ(0, counter()->count()); | |
464 EXPECT_EQ(1, counter2()->count()); | |
465 EXPECT_IN_RANGE(100, counter()->time().InMilliseconds(), 100 + kEpsilonMs); | |
466 EXPECT_IN_RANGE(150, counter2()->time().InMilliseconds(), 150 + kEpsilonMs); | |
467 Sleep(50); | |
468 } | |
469 EXPECT_EQ(1, counter()->count()); | |
470 EXPECT_EQ(1, counter2()->count()); | |
471 EXPECT_IN_RANGE(200, counter()->time().InMilliseconds(), 200 + kEpsilonMs); | |
472 EXPECT_IN_RANGE(150, counter2()->time().InMilliseconds(), | |
473 150 + 2 * kEpsilonMs); | |
474 } | |
475 | |
476 TEST_F(RuntimeCallStatsTest, NestedScopes) { | |
477 { | |
478 RuntimeCallTimerScope scope(stats(), counter_id()); | |
479 Sleep(100); | |
480 { | |
481 RuntimeCallTimerScope scope(stats(), counter_id2()); | |
482 Sleep(100); | |
483 { | |
484 RuntimeCallTimerScope scope(stats(), counter_id3()); | |
485 Sleep(50); | |
486 } | |
487 Sleep(50); | |
488 { | |
489 RuntimeCallTimerScope scope(stats(), counter_id3()); | |
490 Sleep(50); | |
491 } | |
492 Sleep(50); | |
493 } | |
494 Sleep(100); | |
495 { | |
496 RuntimeCallTimerScope scope(stats(), counter_id2()); | |
497 Sleep(100); | |
498 } | |
499 Sleep(50); | |
500 } | |
501 EXPECT_EQ(1, counter()->count()); | |
502 EXPECT_EQ(2, counter2()->count()); | |
503 EXPECT_EQ(2, counter3()->count()); | |
504 EXPECT_IN_RANGE(250, counter()->time().InMilliseconds(), 250 + kEpsilonMs); | |
505 EXPECT_IN_RANGE(300, counter2()->time().InMilliseconds(), 300 + kEpsilonMs); | |
506 EXPECT_IN_RANGE(100, counter3()->time().InMilliseconds(), 100 + kEpsilonMs); | |
507 } | |
508 | 198 |
509 } // namespace internal | 199 } // namespace internal |
510 } // namespace v8 | 200 } // namespace v8 |
OLD | NEW |