blob: e5850c9c618c18235b3fdf51b4463a70fb0abd46 [file] [log] [blame]
Steve Block6ded16b2010-05-10 14:33:55 +01001// Copyright 2010 the V8 project authors. All rights reserved.
2//
3// Tests of profiles generator and utilities.
4
5#ifdef ENABLE_LOGGING_AND_PROFILING
6
7#include "v8.h"
8#include "profile-generator-inl.h"
9#include "cctest.h"
10
11namespace i = v8::internal;
12
13using i::CodeEntry;
14using i::CodeMap;
15using i::CpuProfile;
16using i::CpuProfilesCollection;
17using i::ProfileNode;
18using i::ProfileTree;
19using i::ProfileGenerator;
20using i::SampleRateCalculator;
21using i::TickSample;
22using i::Vector;
23
24
25TEST(ProfileNodeFindOrAddChild) {
26 ProfileNode node(NULL, NULL);
27 CodeEntry entry1(i::Logger::FUNCTION_TAG, "", "aaa", "", 0);
28 ProfileNode* childNode1 = node.FindOrAddChild(&entry1);
29 CHECK_NE(NULL, childNode1);
30 CHECK_EQ(childNode1, node.FindOrAddChild(&entry1));
31 CodeEntry entry2(i::Logger::FUNCTION_TAG, "", "bbb", "", 0);
32 ProfileNode* childNode2 = node.FindOrAddChild(&entry2);
33 CHECK_NE(NULL, childNode2);
34 CHECK_NE(childNode1, childNode2);
35 CHECK_EQ(childNode1, node.FindOrAddChild(&entry1));
36 CHECK_EQ(childNode2, node.FindOrAddChild(&entry2));
37 CodeEntry entry3(i::Logger::FUNCTION_TAG, "", "ccc", "", 0);
38 ProfileNode* childNode3 = node.FindOrAddChild(&entry3);
39 CHECK_NE(NULL, childNode3);
40 CHECK_NE(childNode1, childNode3);
41 CHECK_NE(childNode2, childNode3);
42 CHECK_EQ(childNode1, node.FindOrAddChild(&entry1));
43 CHECK_EQ(childNode2, node.FindOrAddChild(&entry2));
44 CHECK_EQ(childNode3, node.FindOrAddChild(&entry3));
45}
46
47
48namespace {
49
50class ProfileTreeTestHelper {
51 public:
52 explicit ProfileTreeTestHelper(const ProfileTree* tree)
53 : tree_(tree) { }
54
55 ProfileNode* Walk(CodeEntry* entry1,
56 CodeEntry* entry2 = NULL,
57 CodeEntry* entry3 = NULL) {
58 ProfileNode* node = tree_->root();
59 node = node->FindChild(entry1);
60 if (node == NULL) return NULL;
61 if (entry2 != NULL) {
62 node = node->FindChild(entry2);
63 if (node == NULL) return NULL;
64 }
65 if (entry3 != NULL) {
66 node = node->FindChild(entry3);
67 }
68 return node;
69 }
70
71 private:
72 const ProfileTree* tree_;
73};
74
75} // namespace
76
77TEST(ProfileTreeAddPathFromStart) {
78 CodeEntry entry1(i::Logger::FUNCTION_TAG, "", "aaa", "", 0);
79 CodeEntry entry2(i::Logger::FUNCTION_TAG, "", "bbb", "", 0);
80 CodeEntry entry3(i::Logger::FUNCTION_TAG, "", "ccc", "", 0);
81 ProfileTree tree;
82 ProfileTreeTestHelper helper(&tree);
83 CHECK_EQ(NULL, helper.Walk(&entry1));
84 CHECK_EQ(NULL, helper.Walk(&entry2));
85 CHECK_EQ(NULL, helper.Walk(&entry3));
86
87 CodeEntry* path[] = {NULL, &entry1, NULL, &entry2, NULL, NULL, &entry3, NULL};
88 Vector<CodeEntry*> path_vec(path, sizeof(path) / sizeof(path[0]));
89 tree.AddPathFromStart(path_vec);
90 CHECK_EQ(NULL, helper.Walk(&entry2));
91 CHECK_EQ(NULL, helper.Walk(&entry3));
92 ProfileNode* node1 = helper.Walk(&entry1);
93 CHECK_NE(NULL, node1);
94 CHECK_EQ(0, node1->total_ticks());
95 CHECK_EQ(0, node1->self_ticks());
96 CHECK_EQ(NULL, helper.Walk(&entry1, &entry1));
97 CHECK_EQ(NULL, helper.Walk(&entry1, &entry3));
98 ProfileNode* node2 = helper.Walk(&entry1, &entry2);
99 CHECK_NE(NULL, node2);
100 CHECK_NE(node1, node2);
101 CHECK_EQ(0, node2->total_ticks());
102 CHECK_EQ(0, node2->self_ticks());
103 CHECK_EQ(NULL, helper.Walk(&entry1, &entry2, &entry1));
104 CHECK_EQ(NULL, helper.Walk(&entry1, &entry2, &entry2));
105 ProfileNode* node3 = helper.Walk(&entry1, &entry2, &entry3);
106 CHECK_NE(NULL, node3);
107 CHECK_NE(node1, node3);
108 CHECK_NE(node2, node3);
109 CHECK_EQ(0, node3->total_ticks());
110 CHECK_EQ(1, node3->self_ticks());
111
112 tree.AddPathFromStart(path_vec);
113 CHECK_EQ(node1, helper.Walk(&entry1));
114 CHECK_EQ(node2, helper.Walk(&entry1, &entry2));
115 CHECK_EQ(node3, helper.Walk(&entry1, &entry2, &entry3));
116 CHECK_EQ(0, node1->total_ticks());
117 CHECK_EQ(0, node1->self_ticks());
118 CHECK_EQ(0, node2->total_ticks());
119 CHECK_EQ(0, node2->self_ticks());
120 CHECK_EQ(0, node3->total_ticks());
121 CHECK_EQ(2, node3->self_ticks());
122
123 CodeEntry* path2[] = {&entry1, &entry2, &entry2};
124 Vector<CodeEntry*> path2_vec(path2, sizeof(path2) / sizeof(path2[0]));
125 tree.AddPathFromStart(path2_vec);
126 CHECK_EQ(NULL, helper.Walk(&entry2));
127 CHECK_EQ(NULL, helper.Walk(&entry3));
128 CHECK_EQ(node1, helper.Walk(&entry1));
129 CHECK_EQ(NULL, helper.Walk(&entry1, &entry1));
130 CHECK_EQ(NULL, helper.Walk(&entry1, &entry3));
131 CHECK_EQ(node2, helper.Walk(&entry1, &entry2));
132 CHECK_EQ(NULL, helper.Walk(&entry1, &entry2, &entry1));
133 CHECK_EQ(node3, helper.Walk(&entry1, &entry2, &entry3));
134 CHECK_EQ(0, node3->total_ticks());
135 CHECK_EQ(2, node3->self_ticks());
136 ProfileNode* node4 = helper.Walk(&entry1, &entry2, &entry2);
137 CHECK_NE(NULL, node4);
138 CHECK_NE(node3, node4);
139 CHECK_EQ(0, node4->total_ticks());
140 CHECK_EQ(1, node4->self_ticks());
141}
142
143
144TEST(ProfileTreeAddPathFromEnd) {
145 CodeEntry entry1(i::Logger::FUNCTION_TAG, "", "aaa", "", 0);
146 CodeEntry entry2(i::Logger::FUNCTION_TAG, "", "bbb", "", 0);
147 CodeEntry entry3(i::Logger::FUNCTION_TAG, "", "ccc", "", 0);
148 ProfileTree tree;
149 ProfileTreeTestHelper helper(&tree);
150 CHECK_EQ(NULL, helper.Walk(&entry1));
151 CHECK_EQ(NULL, helper.Walk(&entry2));
152 CHECK_EQ(NULL, helper.Walk(&entry3));
153
154 CodeEntry* path[] = {NULL, &entry3, NULL, &entry2, NULL, NULL, &entry1, NULL};
155 Vector<CodeEntry*> path_vec(path, sizeof(path) / sizeof(path[0]));
156 tree.AddPathFromEnd(path_vec);
157 CHECK_EQ(NULL, helper.Walk(&entry2));
158 CHECK_EQ(NULL, helper.Walk(&entry3));
159 ProfileNode* node1 = helper.Walk(&entry1);
160 CHECK_NE(NULL, node1);
161 CHECK_EQ(0, node1->total_ticks());
162 CHECK_EQ(0, node1->self_ticks());
163 CHECK_EQ(NULL, helper.Walk(&entry1, &entry1));
164 CHECK_EQ(NULL, helper.Walk(&entry1, &entry3));
165 ProfileNode* node2 = helper.Walk(&entry1, &entry2);
166 CHECK_NE(NULL, node2);
167 CHECK_NE(node1, node2);
168 CHECK_EQ(0, node2->total_ticks());
169 CHECK_EQ(0, node2->self_ticks());
170 CHECK_EQ(NULL, helper.Walk(&entry1, &entry2, &entry1));
171 CHECK_EQ(NULL, helper.Walk(&entry1, &entry2, &entry2));
172 ProfileNode* node3 = helper.Walk(&entry1, &entry2, &entry3);
173 CHECK_NE(NULL, node3);
174 CHECK_NE(node1, node3);
175 CHECK_NE(node2, node3);
176 CHECK_EQ(0, node3->total_ticks());
177 CHECK_EQ(1, node3->self_ticks());
178
179 tree.AddPathFromEnd(path_vec);
180 CHECK_EQ(node1, helper.Walk(&entry1));
181 CHECK_EQ(node2, helper.Walk(&entry1, &entry2));
182 CHECK_EQ(node3, helper.Walk(&entry1, &entry2, &entry3));
183 CHECK_EQ(0, node1->total_ticks());
184 CHECK_EQ(0, node1->self_ticks());
185 CHECK_EQ(0, node2->total_ticks());
186 CHECK_EQ(0, node2->self_ticks());
187 CHECK_EQ(0, node3->total_ticks());
188 CHECK_EQ(2, node3->self_ticks());
189
190 CodeEntry* path2[] = {&entry2, &entry2, &entry1};
191 Vector<CodeEntry*> path2_vec(path2, sizeof(path2) / sizeof(path2[0]));
192 tree.AddPathFromEnd(path2_vec);
193 CHECK_EQ(NULL, helper.Walk(&entry2));
194 CHECK_EQ(NULL, helper.Walk(&entry3));
195 CHECK_EQ(node1, helper.Walk(&entry1));
196 CHECK_EQ(NULL, helper.Walk(&entry1, &entry1));
197 CHECK_EQ(NULL, helper.Walk(&entry1, &entry3));
198 CHECK_EQ(node2, helper.Walk(&entry1, &entry2));
199 CHECK_EQ(NULL, helper.Walk(&entry1, &entry2, &entry1));
200 CHECK_EQ(node3, helper.Walk(&entry1, &entry2, &entry3));
201 CHECK_EQ(0, node3->total_ticks());
202 CHECK_EQ(2, node3->self_ticks());
203 ProfileNode* node4 = helper.Walk(&entry1, &entry2, &entry2);
204 CHECK_NE(NULL, node4);
205 CHECK_NE(node3, node4);
206 CHECK_EQ(0, node4->total_ticks());
207 CHECK_EQ(1, node4->self_ticks());
208}
209
210
211TEST(ProfileTreeCalculateTotalTicks) {
212 ProfileTree empty_tree;
213 CHECK_EQ(0, empty_tree.root()->total_ticks());
214 CHECK_EQ(0, empty_tree.root()->self_ticks());
215 empty_tree.CalculateTotalTicks();
216 CHECK_EQ(0, empty_tree.root()->total_ticks());
217 CHECK_EQ(0, empty_tree.root()->self_ticks());
218 empty_tree.root()->IncrementSelfTicks();
219 CHECK_EQ(0, empty_tree.root()->total_ticks());
220 CHECK_EQ(1, empty_tree.root()->self_ticks());
221 empty_tree.CalculateTotalTicks();
222 CHECK_EQ(1, empty_tree.root()->total_ticks());
223 CHECK_EQ(1, empty_tree.root()->self_ticks());
224
225 CodeEntry entry1(i::Logger::FUNCTION_TAG, "", "aaa", "", 0);
226 CodeEntry entry2(i::Logger::FUNCTION_TAG, "", "bbb", "", 0);
227 CodeEntry* e1_path[] = {&entry1};
228 Vector<CodeEntry*> e1_path_vec(
229 e1_path, sizeof(e1_path) / sizeof(e1_path[0]));
230 CodeEntry* e1_e2_path[] = {&entry1, &entry2};
231 Vector<CodeEntry*> e1_e2_path_vec(
232 e1_e2_path, sizeof(e1_e2_path) / sizeof(e1_e2_path[0]));
233
234 ProfileTree flat_tree;
235 ProfileTreeTestHelper flat_helper(&flat_tree);
236 flat_tree.AddPathFromStart(e1_path_vec);
237 flat_tree.AddPathFromStart(e1_path_vec);
238 flat_tree.AddPathFromStart(e1_e2_path_vec);
239 flat_tree.AddPathFromStart(e1_e2_path_vec);
240 flat_tree.AddPathFromStart(e1_e2_path_vec);
241 // Results in {root,0,0} -> {entry1,0,2} -> {entry2,0,3}
242 CHECK_EQ(0, flat_tree.root()->total_ticks());
243 CHECK_EQ(0, flat_tree.root()->self_ticks());
244 ProfileNode* node1 = flat_helper.Walk(&entry1);
245 CHECK_NE(NULL, node1);
246 CHECK_EQ(0, node1->total_ticks());
247 CHECK_EQ(2, node1->self_ticks());
248 ProfileNode* node2 = flat_helper.Walk(&entry1, &entry2);
249 CHECK_NE(NULL, node2);
250 CHECK_EQ(0, node2->total_ticks());
251 CHECK_EQ(3, node2->self_ticks());
252 flat_tree.CalculateTotalTicks();
253 // Must calculate {root,5,0} -> {entry1,5,2} -> {entry2,3,3}
254 CHECK_EQ(5, flat_tree.root()->total_ticks());
255 CHECK_EQ(0, flat_tree.root()->self_ticks());
256 CHECK_EQ(5, node1->total_ticks());
257 CHECK_EQ(2, node1->self_ticks());
258 CHECK_EQ(3, node2->total_ticks());
259 CHECK_EQ(3, node2->self_ticks());
260
261 CodeEntry* e2_path[] = {&entry2};
262 Vector<CodeEntry*> e2_path_vec(
263 e2_path, sizeof(e2_path) / sizeof(e2_path[0]));
264 CodeEntry entry3(i::Logger::FUNCTION_TAG, "", "ccc", "", 0);
265 CodeEntry* e3_path[] = {&entry3};
266 Vector<CodeEntry*> e3_path_vec(
267 e3_path, sizeof(e3_path) / sizeof(e3_path[0]));
268
269 ProfileTree wide_tree;
270 ProfileTreeTestHelper wide_helper(&wide_tree);
271 wide_tree.AddPathFromStart(e1_path_vec);
272 wide_tree.AddPathFromStart(e1_path_vec);
273 wide_tree.AddPathFromStart(e1_e2_path_vec);
274 wide_tree.AddPathFromStart(e2_path_vec);
275 wide_tree.AddPathFromStart(e2_path_vec);
276 wide_tree.AddPathFromStart(e2_path_vec);
277 wide_tree.AddPathFromStart(e3_path_vec);
278 wide_tree.AddPathFromStart(e3_path_vec);
279 wide_tree.AddPathFromStart(e3_path_vec);
280 wide_tree.AddPathFromStart(e3_path_vec);
281 // Results in -> {entry1,0,2} -> {entry2,0,1}
282 // {root,0,0} -> {entry2,0,3}
283 // -> {entry3,0,4}
284 CHECK_EQ(0, wide_tree.root()->total_ticks());
285 CHECK_EQ(0, wide_tree.root()->self_ticks());
286 node1 = wide_helper.Walk(&entry1);
287 CHECK_NE(NULL, node1);
288 CHECK_EQ(0, node1->total_ticks());
289 CHECK_EQ(2, node1->self_ticks());
290 ProfileNode* node1_2 = wide_helper.Walk(&entry1, &entry2);
291 CHECK_NE(NULL, node1_2);
292 CHECK_EQ(0, node1_2->total_ticks());
293 CHECK_EQ(1, node1_2->self_ticks());
294 node2 = wide_helper.Walk(&entry2);
295 CHECK_NE(NULL, node2);
296 CHECK_EQ(0, node2->total_ticks());
297 CHECK_EQ(3, node2->self_ticks());
298 ProfileNode* node3 = wide_helper.Walk(&entry3);
299 CHECK_NE(NULL, node3);
300 CHECK_EQ(0, node3->total_ticks());
301 CHECK_EQ(4, node3->self_ticks());
302 wide_tree.CalculateTotalTicks();
303 // Calculates -> {entry1,3,2} -> {entry2,1,1}
304 // {root,10,0} -> {entry2,3,3}
305 // -> {entry3,4,4}
306 CHECK_EQ(10, wide_tree.root()->total_ticks());
307 CHECK_EQ(0, wide_tree.root()->self_ticks());
308 CHECK_EQ(3, node1->total_ticks());
309 CHECK_EQ(2, node1->self_ticks());
310 CHECK_EQ(1, node1_2->total_ticks());
311 CHECK_EQ(1, node1_2->self_ticks());
312 CHECK_EQ(3, node2->total_ticks());
313 CHECK_EQ(3, node2->self_ticks());
314 CHECK_EQ(4, node3->total_ticks());
315 CHECK_EQ(4, node3->self_ticks());
316}
317
318
319static inline i::Address ToAddress(int n) {
320 return reinterpret_cast<i::Address>(n);
321}
322
323TEST(CodeMapAddCode) {
324 CodeMap code_map;
325 CodeEntry entry1(i::Logger::FUNCTION_TAG, "", "aaa", "", 0);
326 CodeEntry entry2(i::Logger::FUNCTION_TAG, "", "bbb", "", 0);
327 CodeEntry entry3(i::Logger::FUNCTION_TAG, "", "ccc", "", 0);
328 CodeEntry entry4(i::Logger::FUNCTION_TAG, "", "ddd", "", 0);
329 code_map.AddCode(ToAddress(0x1500), &entry1, 0x200);
330 code_map.AddCode(ToAddress(0x1700), &entry2, 0x100);
331 code_map.AddCode(ToAddress(0x1900), &entry3, 0x50);
332 code_map.AddCode(ToAddress(0x1950), &entry4, 0x10);
333 CHECK_EQ(NULL, code_map.FindEntry(0));
334 CHECK_EQ(NULL, code_map.FindEntry(ToAddress(0x1500 - 1)));
335 CHECK_EQ(&entry1, code_map.FindEntry(ToAddress(0x1500)));
336 CHECK_EQ(&entry1, code_map.FindEntry(ToAddress(0x1500 + 0x100)));
337 CHECK_EQ(&entry1, code_map.FindEntry(ToAddress(0x1500 + 0x200 - 1)));
338 CHECK_EQ(&entry2, code_map.FindEntry(ToAddress(0x1700)));
339 CHECK_EQ(&entry2, code_map.FindEntry(ToAddress(0x1700 + 0x50)));
340 CHECK_EQ(&entry2, code_map.FindEntry(ToAddress(0x1700 + 0x100 - 1)));
341 CHECK_EQ(NULL, code_map.FindEntry(ToAddress(0x1700 + 0x100)));
342 CHECK_EQ(NULL, code_map.FindEntry(ToAddress(0x1900 - 1)));
343 CHECK_EQ(&entry3, code_map.FindEntry(ToAddress(0x1900)));
344 CHECK_EQ(&entry3, code_map.FindEntry(ToAddress(0x1900 + 0x28)));
345 CHECK_EQ(&entry4, code_map.FindEntry(ToAddress(0x1950)));
346 CHECK_EQ(&entry4, code_map.FindEntry(ToAddress(0x1950 + 0x7)));
347 CHECK_EQ(&entry4, code_map.FindEntry(ToAddress(0x1950 + 0x10 - 1)));
348 CHECK_EQ(NULL, code_map.FindEntry(ToAddress(0x1950 + 0x10)));
349 CHECK_EQ(NULL, code_map.FindEntry(ToAddress(0xFFFFFFFF)));
350}
351
352
353TEST(CodeMapMoveAndDeleteCode) {
354 CodeMap code_map;
355 CodeEntry entry1(i::Logger::FUNCTION_TAG, "", "aaa", "", 0);
356 CodeEntry entry2(i::Logger::FUNCTION_TAG, "", "bbb", "", 0);
357 code_map.AddCode(ToAddress(0x1500), &entry1, 0x200);
358 code_map.AddCode(ToAddress(0x1700), &entry2, 0x100);
359 CHECK_EQ(&entry1, code_map.FindEntry(ToAddress(0x1500)));
360 CHECK_EQ(&entry2, code_map.FindEntry(ToAddress(0x1700)));
361 code_map.MoveCode(ToAddress(0x1500), ToAddress(0x1800));
362 CHECK_EQ(NULL, code_map.FindEntry(ToAddress(0x1500)));
363 CHECK_EQ(&entry2, code_map.FindEntry(ToAddress(0x1700)));
364 CHECK_EQ(&entry1, code_map.FindEntry(ToAddress(0x1800)));
365 code_map.DeleteCode(ToAddress(0x1700));
366 CHECK_EQ(NULL, code_map.FindEntry(ToAddress(0x1700)));
367 CHECK_EQ(&entry1, code_map.FindEntry(ToAddress(0x1800)));
368}
369
370
371namespace {
372
373class TestSetup {
374 public:
375 TestSetup()
376 : old_flag_prof_browser_mode_(i::FLAG_prof_browser_mode) {
377 i::FLAG_prof_browser_mode = false;
378 }
379
380 ~TestSetup() {
381 i::FLAG_prof_browser_mode = old_flag_prof_browser_mode_;
382 }
383
384 private:
385 bool old_flag_prof_browser_mode_;
386};
387
388} // namespace
389
390TEST(RecordTickSample) {
391 TestSetup test_setup;
392 CpuProfilesCollection profiles;
393 profiles.StartProfiling("", 1);
394 ProfileGenerator generator(&profiles);
395 CodeEntry* entry1 = generator.NewCodeEntry(i::Logger::FUNCTION_TAG, "aaa");
396 CodeEntry* entry2 = generator.NewCodeEntry(i::Logger::FUNCTION_TAG, "bbb");
397 CodeEntry* entry3 = generator.NewCodeEntry(i::Logger::FUNCTION_TAG, "ccc");
398 generator.code_map()->AddCode(ToAddress(0x1500), entry1, 0x200);
399 generator.code_map()->AddCode(ToAddress(0x1700), entry2, 0x100);
400 generator.code_map()->AddCode(ToAddress(0x1900), entry3, 0x50);
401
402 // We are building the following calls tree:
403 // -> aaa - sample1
404 // aaa -> bbb -> ccc - sample2
405 // -> ccc -> aaa - sample3
406 TickSample sample1;
407 sample1.pc = ToAddress(0x1600);
408 sample1.function = ToAddress(0x1500);
409 sample1.stack[0] = ToAddress(0x1510);
410 sample1.frames_count = 1;
411 generator.RecordTickSample(sample1);
412 TickSample sample2;
413 sample2.pc = ToAddress(0x1925);
414 sample2.function = ToAddress(0x1900);
415 sample2.stack[0] = ToAddress(0x1780);
416 sample2.stack[1] = ToAddress(0x10000); // non-existent.
417 sample2.stack[2] = ToAddress(0x1620);
418 sample2.frames_count = 3;
419 generator.RecordTickSample(sample2);
420 TickSample sample3;
421 sample3.pc = ToAddress(0x1510);
422 sample3.function = ToAddress(0x1500);
423 sample3.stack[0] = ToAddress(0x1910);
424 sample3.stack[1] = ToAddress(0x1610);
425 sample3.frames_count = 2;
426 generator.RecordTickSample(sample3);
427
428 CpuProfile* profile = profiles.StopProfiling("", 1);
429 CHECK_NE(NULL, profile);
430 ProfileTreeTestHelper top_down_test_helper(profile->top_down());
431 CHECK_EQ(NULL, top_down_test_helper.Walk(entry2));
432 CHECK_EQ(NULL, top_down_test_helper.Walk(entry3));
433 ProfileNode* node1 = top_down_test_helper.Walk(entry1);
434 CHECK_NE(NULL, node1);
435 CHECK_EQ(entry1, node1->entry());
436 ProfileNode* node2 = top_down_test_helper.Walk(entry1, entry1);
437 CHECK_NE(NULL, node2);
438 CHECK_EQ(entry1, node2->entry());
439 ProfileNode* node3 = top_down_test_helper.Walk(entry1, entry2, entry3);
440 CHECK_NE(NULL, node3);
441 CHECK_EQ(entry3, node3->entry());
442 ProfileNode* node4 = top_down_test_helper.Walk(entry1, entry3, entry1);
443 CHECK_NE(NULL, node4);
444 CHECK_EQ(entry1, node4->entry());
445}
446
447
448TEST(SampleRateCalculator) {
449 const double kSamplingIntervalMs = i::Logger::kSamplingIntervalMs;
450
451 // Verify that ticking exactly in query intervals results in the
452 // initial sampling interval.
453 double time = 0.0;
454 SampleRateCalculator calc1;
455 CHECK_EQ(kSamplingIntervalMs, calc1.ticks_per_ms());
456 calc1.UpdateMeasurements(time);
457 CHECK_EQ(kSamplingIntervalMs, calc1.ticks_per_ms());
458 time += SampleRateCalculator::kWallTimeQueryIntervalMs;
459 calc1.UpdateMeasurements(time);
460 CHECK_EQ(kSamplingIntervalMs, calc1.ticks_per_ms());
461 time += SampleRateCalculator::kWallTimeQueryIntervalMs;
462 calc1.UpdateMeasurements(time);
463 CHECK_EQ(kSamplingIntervalMs, calc1.ticks_per_ms());
464 time += SampleRateCalculator::kWallTimeQueryIntervalMs;
465 calc1.UpdateMeasurements(time);
466 CHECK_EQ(kSamplingIntervalMs, calc1.ticks_per_ms());
467
468 SampleRateCalculator calc2;
469 time = 0.0;
470 CHECK_EQ(kSamplingIntervalMs, calc2.ticks_per_ms());
471 calc2.UpdateMeasurements(time);
472 CHECK_EQ(kSamplingIntervalMs, calc2.ticks_per_ms());
473 time += SampleRateCalculator::kWallTimeQueryIntervalMs * 0.5;
474 calc2.UpdateMeasurements(time);
475 // (1.0 + 2.0) / 2
476 CHECK_EQ(kSamplingIntervalMs * 1.5, calc2.ticks_per_ms());
477 time += SampleRateCalculator::kWallTimeQueryIntervalMs * 0.75;
478 calc2.UpdateMeasurements(time);
479 // (1.0 + 2.0 + 2.0) / 3
480 CHECK_EQ(kSamplingIntervalMs * 1.66666, calc2.ticks_per_ms());
481
482 SampleRateCalculator calc3;
483 time = 0.0;
484 CHECK_EQ(kSamplingIntervalMs, calc3.ticks_per_ms());
485 calc3.UpdateMeasurements(time);
486 CHECK_EQ(kSamplingIntervalMs, calc3.ticks_per_ms());
487 time += SampleRateCalculator::kWallTimeQueryIntervalMs * 2;
488 calc3.UpdateMeasurements(time);
489 // (1.0 + 0.5) / 2
490 CHECK_EQ(kSamplingIntervalMs * 0.75, calc3.ticks_per_ms());
491 time += SampleRateCalculator::kWallTimeQueryIntervalMs * 1.5;
492 calc3.UpdateMeasurements(time);
493 // (1.0 + 0.5 + 0.5) / 3
494 CHECK_EQ(kSamplingIntervalMs * 0.66666, calc3.ticks_per_ms());
495}
496
497#endif // ENABLE_LOGGING_AND_PROFILING