1// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#include "vm/benchmark_test.h"
6
7#include "bin/builtin.h"
8#include "bin/file.h"
9#include "bin/isolate_data.h"
10#include "bin/process.h"
11#include "bin/reference_counting.h"
12#include "bin/vmservice_impl.h"
13
14#include "platform/assert.h"
15#include "platform/globals.h"
16#include "platform/utils.h"
17
18#include "vm/clustered_snapshot.h"
19#include "vm/dart_api_impl.h"
20#include "vm/stack_frame.h"
21#include "vm/timer.h"
22
23using dart::bin::File;
24
25namespace dart {
26
27Benchmark* Benchmark::first_ = NULL;
28Benchmark* Benchmark::tail_ = NULL;
29const char* Benchmark::executable_ = NULL;
30
31void Benchmark::RunAll(const char* executable) {
32 SetExecutable(executable);
33 Benchmark* benchmark = first_;
34 while (benchmark != NULL) {
35 benchmark->RunBenchmark();
36 benchmark = benchmark->next_;
37 }
38}
39
40//
41// Measure compile of all functions in dart core lib classes.
42//
43BENCHMARK(CorelibCompileAll) {
44 bin::Builtin::SetNativeResolver(bin::Builtin::kBuiltinLibrary);
45 bin::Builtin::SetNativeResolver(bin::Builtin::kIOLibrary);
46 bin::Builtin::SetNativeResolver(bin::Builtin::kCLILibrary);
47 TransitionNativeToVM transition(thread);
48 StackZone zone(thread);
49 HANDLESCOPE(thread);
50 Timer timer(true, "Compile all of Core lib benchmark");
51 timer.Start();
52 const Error& error =
53 Error::Handle(Library::CompileAll(/*ignore_error=*/true));
54 if (!error.IsNull()) {
55 OS::PrintErr("Unexpected error in CorelibCompileAll benchmark:\n%s",
56 error.ToErrorCString());
57 }
58 timer.Stop();
59 int64_t elapsed_time = timer.TotalElapsedTime();
60 benchmark->set_score(elapsed_time);
61}
62
63// This file is created by the target //runtime/bin:dart_kernel_platform_cc
64// which is depended on by run_vm_tests.
65static char* ComputeKernelServicePath(const char* arg) {
66 char buffer[2048];
67 char* kernel_service_path = Utils::StrDup(File::GetCanonicalPath(NULL, arg));
68 EXPECT(kernel_service_path != NULL);
69 const char* compiler_path = "%s%sgen%skernel_service.dill";
70 const char* path_separator = File::PathSeparator();
71 ASSERT(path_separator != NULL && strlen(path_separator) == 1);
72 char* ptr = strrchr(kernel_service_path, *path_separator);
73 while (ptr != NULL) {
74 *ptr = '\0';
75 Utils::SNPrint(buffer, ARRAY_SIZE(buffer), compiler_path,
76 kernel_service_path, path_separator, path_separator);
77 if (File::Exists(NULL, buffer)) {
78 break;
79 }
80 ptr = strrchr(kernel_service_path, *path_separator);
81 }
82 free(kernel_service_path);
83 if (ptr == NULL) {
84 return NULL;
85 }
86 return Utils::StrDup(buffer);
87}
88
89// This file is created by the target //runtime/bin:gen_kernel_bytecode_dill
90// which is depended on by run_vm_tests.
91static char* ComputeGenKernelKernelPath(const char* arg) {
92 char buffer[2048];
93 char* gen_kernel_path = Utils::StrDup(File::GetCanonicalPath(NULL, arg));
94 EXPECT(gen_kernel_path != NULL);
95 const char* compiler_path = "%s%sgen_kernel_bytecode.dill";
96 const char* path_separator = File::PathSeparator();
97 ASSERT(path_separator != NULL && strlen(path_separator) == 1);
98 char* ptr = strrchr(gen_kernel_path, *path_separator);
99 while (ptr != NULL) {
100 *ptr = '\0';
101 Utils::SNPrint(buffer, ARRAY_SIZE(buffer), compiler_path, gen_kernel_path,
102 path_separator);
103 if (File::Exists(NULL, buffer)) {
104 break;
105 }
106 ptr = strrchr(gen_kernel_path, *path_separator);
107 }
108 free(gen_kernel_path);
109 if (ptr == NULL) {
110 return NULL;
111 }
112 return Utils::StrDup(buffer);
113}
114
115static int64_t GenKernelKernelBenchmark(const char* name,
116 bool benchmark_load,
117 bool benchmark_read_bytecode) {
118 EXPECT(benchmark_load || benchmark_read_bytecode);
119 bin::Builtin::SetNativeResolver(bin::Builtin::kBuiltinLibrary);
120 bin::Builtin::SetNativeResolver(bin::Builtin::kIOLibrary);
121 bin::Builtin::SetNativeResolver(bin::Builtin::kCLILibrary);
122 bin::VmService::SetNativeResolver();
123
124 char* dill_path = ComputeGenKernelKernelPath(Benchmark::Executable());
125 File* file = File::Open(NULL, dill_path, File::kRead);
126 EXPECT(file != NULL);
127 bin::RefCntReleaseScope<File> rs(file);
128 intptr_t kernel_buffer_size = file->Length();
129 uint8_t* kernel_buffer =
130 reinterpret_cast<uint8_t*>(malloc(kernel_buffer_size));
131 EXPECT(kernel_buffer != NULL);
132 bool read_fully = file->ReadFully(kernel_buffer, kernel_buffer_size);
133 EXPECT(read_fully);
134
135 Timer timer(true, name);
136 if (benchmark_load) {
137 timer.Start();
138 }
139
140 Dart_Handle result =
141 Dart_LoadLibraryFromKernel(kernel_buffer, kernel_buffer_size);
142 EXPECT_VALID(result);
143
144 result = Dart_FinalizeLoading(false);
145 EXPECT_VALID(result);
146
147 if (benchmark_read_bytecode && !benchmark_load) {
148 timer.Start();
149 }
150
151 if (benchmark_read_bytecode) {
152 result = Dart_ReadAllBytecode();
153 EXPECT_VALID(result);
154 }
155
156 timer.Stop();
157 int64_t elapsed_time = timer.TotalElapsedTime();
158 free(dill_path);
159 free(kernel_buffer);
160 return elapsed_time;
161}
162
163BENCHMARK(GenKernelKernelLoadKernel) {
164 benchmark->set_score(
165 GenKernelKernelBenchmark("GenKernelKernelLoadKernel benchmark",
166 /* benchmark_load */ true,
167 /* benchmark_read_bytecode */ false));
168}
169
170BENCHMARK(GenKernelKernelReadAllBytecode) {
171 benchmark->set_score(
172 GenKernelKernelBenchmark("GenKernelKernelReadAllBytecode benchmark",
173 /* benchmark_load */ false,
174 /* benchmark_read_bytecode */ true));
175}
176
177BENCHMARK(GenKernelKernelCombined) {
178 benchmark->set_score(
179 GenKernelKernelBenchmark("GenKernelKernelCombined benchmark",
180 /* benchmark_load */ true,
181 /* benchmark_read_bytecode */ true));
182}
183
184BENCHMARK_MEMORY(GenKernelKernelMaxRSS) {
185 GenKernelKernelBenchmark("GenKernelKernelMaxRSS benchmark",
186 /* benchmark_load */ false,
187 /* benchmark_read_bytecode */ true);
188 benchmark->set_score(bin::Process::MaxRSS());
189}
190
191//
192// Measure creation of core isolate from a snapshot.
193//
194BENCHMARK(CorelibIsolateStartup) {
195 const int kNumIterations = 1000;
196 Timer timer(true, "CorelibIsolateStartup");
197 Isolate* isolate = thread->isolate();
198 Dart_ExitIsolate();
199 for (int i = 0; i < kNumIterations; i++) {
200 timer.Start();
201 TestCase::CreateTestIsolate();
202 timer.Stop();
203 Dart_ShutdownIsolate();
204 }
205 benchmark->set_score(timer.TotalElapsedTime() / kNumIterations);
206 Dart_EnterIsolate(reinterpret_cast<Dart_Isolate>(isolate));
207}
208
209//
210// Measure invocation of Dart API functions.
211//
212static void InitNativeFields(Dart_NativeArguments args) {
213 int count = Dart_GetNativeArgumentCount(args);
214 EXPECT_EQ(1, count);
215
216 Dart_Handle recv = Dart_GetNativeArgument(args, 0);
217 EXPECT_VALID(recv);
218 Dart_Handle result = Dart_SetNativeInstanceField(recv, 0, 7);
219 EXPECT_VALID(result);
220}
221
222// The specific api functions called here are a bit arbitrary. We are
223// trying to get a sense of the overhead for using the dart api.
224static void UseDartApi(Dart_NativeArguments args) {
225 int count = Dart_GetNativeArgumentCount(args);
226 EXPECT_EQ(3, count);
227
228 // Get native field from receiver.
229 intptr_t receiver_value;
230 Dart_Handle result = Dart_GetNativeReceiver(args, &receiver_value);
231 EXPECT_VALID(result);
232 EXPECT_EQ(7, receiver_value);
233
234 // Get param1.
235 Dart_Handle param1 = Dart_GetNativeArgument(args, 1);
236 EXPECT_VALID(param1);
237 EXPECT(Dart_IsInteger(param1));
238 bool fits = false;
239 result = Dart_IntegerFitsIntoInt64(param1, &fits);
240 EXPECT_VALID(result);
241 EXPECT(fits);
242 int64_t value1;
243 result = Dart_IntegerToInt64(param1, &value1);
244 EXPECT_VALID(result);
245 EXPECT_LE(0, value1);
246 EXPECT_LE(value1, 1000000);
247
248 // Return param + receiver.field.
249 Dart_SetReturnValue(args, Dart_NewInteger(value1 * receiver_value));
250}
251
252static Dart_NativeFunction bm_uda_lookup(Dart_Handle name,
253 int argument_count,
254 bool* auto_setup_scope) {
255 ASSERT(auto_setup_scope != NULL);
256 *auto_setup_scope = true;
257 const char* cstr = NULL;
258 Dart_Handle result = Dart_StringToCString(name, &cstr);
259 EXPECT_VALID(result);
260 if (strcmp(cstr, "init") == 0) {
261 return InitNativeFields;
262 } else {
263 return UseDartApi;
264 }
265}
266
267BENCHMARK(UseDartApi) {
268 const int kNumIterations = 1000000;
269 const char* kScriptChars =
270 "import 'dart:nativewrappers';\n"
271 "class Class extends NativeFieldWrapperClass1 {\n"
272 " void init() native 'init';\n"
273 " int method(int param1, int param2) native 'method';\n"
274 "}\n"
275 "\n"
276 "void benchmark(int count) {\n"
277 " Class c = Class();\n"
278 " c.init();\n"
279 " for (int i = 0; i < count; i++) {\n"
280 " c.method(i,7);\n"
281 " }\n"
282 "}\n";
283
284 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, bm_uda_lookup,
285 RESOLVED_USER_TEST_URI, false);
286 Dart_Handle result = Dart_FinalizeLoading(false);
287 EXPECT_VALID(result);
288
289 Dart_Handle args[1];
290 args[0] = Dart_NewInteger(kNumIterations);
291
292 // Warmup first to avoid compilation jitters.
293 result = Dart_Invoke(lib, NewString("benchmark"), 1, args);
294 EXPECT_VALID(result);
295
296 Timer timer(true, "UseDartApi benchmark");
297 timer.Start();
298 result = Dart_Invoke(lib, NewString("benchmark"), 1, args);
299 EXPECT_VALID(result);
300 timer.Stop();
301 int64_t elapsed_time = timer.TotalElapsedTime();
302 benchmark->set_score(elapsed_time);
303}
304
305static void NoopFinalizer(void* isolate_callback_data,
306 Dart_WeakPersistentHandle handle,
307 void* peer) {}
308
309//
310// Measure time accessing internal and external strings.
311//
312BENCHMARK(DartStringAccess) {
313 const int kNumIterations = 10000000;
314 Timer timer(true, "DartStringAccess benchmark");
315 timer.Start();
316 Dart_EnterScope();
317
318 // Create strings.
319 uint8_t data8[] = {'o', 'n', 'e', 0xFF};
320 int external_peer_data = 123;
321 intptr_t char_size;
322 intptr_t str_len;
323 Dart_Handle external_string = Dart_NewExternalLatin1String(
324 data8, ARRAY_SIZE(data8), &external_peer_data, sizeof(data8),
325 NoopFinalizer);
326 Dart_Handle internal_string = NewString("two");
327
328 // Run benchmark.
329 for (int64_t i = 0; i < kNumIterations; i++) {
330 EXPECT(Dart_IsString(internal_string));
331 EXPECT(!Dart_IsExternalString(internal_string));
332 EXPECT_VALID(external_string);
333 EXPECT(Dart_IsExternalString(external_string));
334 void* external_peer = NULL;
335 EXPECT_VALID(Dart_StringGetProperties(external_string, &char_size, &str_len,
336 &external_peer));
337 EXPECT_EQ(1, char_size);
338 EXPECT_EQ(4, str_len);
339 EXPECT_EQ(&external_peer_data, external_peer);
340 }
341
342 Dart_ExitScope();
343 timer.Stop();
344 int64_t elapsed_time = timer.TotalElapsedTime();
345 benchmark->set_score(elapsed_time);
346}
347
348static void vmservice_resolver(Dart_NativeArguments args) {}
349
350static Dart_NativeFunction NativeResolver(Dart_Handle name,
351 int arg_count,
352 bool* auto_setup_scope) {
353 ASSERT(auto_setup_scope != NULL);
354 *auto_setup_scope = false;
355 return &vmservice_resolver;
356}
357
358//
359// Measure compile of all kernel Service(CFE) functions.
360//
361BENCHMARK(KernelServiceCompileAll) {
362 if (FLAG_sound_null_safety == kNullSafetyOptionStrong) {
363 // TODO(bkonyi): remove this check when we build the CFE in strong mode.
364 return;
365 }
366 bin::Builtin::SetNativeResolver(bin::Builtin::kBuiltinLibrary);
367 bin::Builtin::SetNativeResolver(bin::Builtin::kIOLibrary);
368 bin::Builtin::SetNativeResolver(bin::Builtin::kCLILibrary);
369 char* dill_path = ComputeKernelServicePath(Benchmark::Executable());
370 File* file = File::Open(NULL, dill_path, File::kRead);
371 EXPECT(file != NULL);
372 bin::RefCntReleaseScope<File> rs(file);
373 intptr_t kernel_buffer_size = file->Length();
374 uint8_t* kernel_buffer =
375 reinterpret_cast<uint8_t*>(malloc(kernel_buffer_size));
376 EXPECT(kernel_buffer != NULL);
377 bool read_fully = file->ReadFully(kernel_buffer, kernel_buffer_size);
378 EXPECT(read_fully);
379 Dart_Handle result =
380 Dart_LoadScriptFromKernel(kernel_buffer, kernel_buffer_size);
381 EXPECT_VALID(result);
382 Dart_Handle service_lib = Dart_LookupLibrary(NewString("dart:vmservice_io"));
383 ASSERT(!Dart_IsError(service_lib));
384 Dart_SetNativeResolver(service_lib, NativeResolver, NULL);
385 result = Dart_FinalizeLoading(false);
386 EXPECT_VALID(result);
387
388 Timer timer(true, "Compile all of kernel service benchmark");
389 timer.Start();
390#if !defined(PRODUCT)
391 const bool old_flag = FLAG_background_compilation;
392 FLAG_background_compilation = false;
393#endif
394 result = Dart_CompileAll();
395#if !defined(PRODUCT)
396 FLAG_background_compilation = old_flag;
397#endif
398 EXPECT_VALID(result);
399 timer.Stop();
400 int64_t elapsed_time = timer.TotalElapsedTime();
401 benchmark->set_score(elapsed_time);
402 free(dill_path);
403 free(kernel_buffer);
404}
405
406//
407// Measure frame lookup during stack traversal.
408//
409static void StackFrame_accessFrame(Dart_NativeArguments args) {
410 Timer timer(true, "LookupDartCode benchmark");
411 timer.Start();
412 {
413 Thread* thread = Thread::Current();
414 TransitionNativeToVM transition(thread);
415 const int kNumIterations = 100;
416 Code& code = Code::Handle(thread->zone());
417 Bytecode& bytecode = Bytecode::Handle(thread->zone());
418 for (int i = 0; i < kNumIterations; i++) {
419 StackFrameIterator frames(ValidationPolicy::kDontValidateFrames, thread,
420 StackFrameIterator::kNoCrossThreadIteration);
421 StackFrame* frame = frames.NextFrame();
422 while (frame != NULL) {
423 if (frame->IsStubFrame()) {
424 code = frame->LookupDartCode();
425 EXPECT(code.function() == Function::null());
426 } else if (frame->IsDartFrame()) {
427 if (frame->is_interpreted()) {
428 bytecode = frame->LookupDartBytecode();
429 EXPECT(bytecode.function() != Function::null());
430 } else {
431 code = frame->LookupDartCode();
432 EXPECT(code.function() != Function::null());
433 }
434 }
435 frame = frames.NextFrame();
436 }
437 }
438 }
439 timer.Stop();
440 int64_t elapsed_time = timer.TotalElapsedTime();
441 Dart_SetReturnValue(args, Dart_NewInteger(elapsed_time));
442}
443
444static Dart_NativeFunction StackFrameNativeResolver(Dart_Handle name,
445 int arg_count,
446 bool* auto_setup_scope) {
447 ASSERT(auto_setup_scope != NULL);
448 *auto_setup_scope = false;
449 return &StackFrame_accessFrame;
450}
451
452// Unit test case to verify stack frame iteration.
453BENCHMARK(FrameLookup) {
454 const char* kScriptChars =
455 "class StackFrame {"
456 " static int accessFrame() native \"StackFrame_accessFrame\";"
457 "} "
458 "class First {"
459 " First() { }"
460 " int method1(int param) {"
461 " if (param == 1) {"
462 " param = method2(200);"
463 " } else {"
464 " param = method2(100);"
465 " }"
466 " return param;"
467 " }"
468 " int method2(int param) {"
469 " if (param == 200) {"
470 " return First.staticmethod(this, param);"
471 " } else {"
472 " return First.staticmethod(this, 10);"
473 " }"
474 " }"
475 " static int staticmethod(First obj, int param) {"
476 " if (param == 10) {"
477 " return obj.method3(10);"
478 " } else {"
479 " return obj.method3(200);"
480 " }"
481 " }"
482 " int method3(int param) {"
483 " return StackFrame.accessFrame();"
484 " }"
485 "}"
486 "class StackFrameTest {"
487 " static int testMain() {"
488 " First obj = new First();"
489 " return obj.method1(1);"
490 " }"
491 "}";
492 Dart_Handle lib =
493 TestCase::LoadTestScript(kScriptChars, StackFrameNativeResolver);
494 Dart_Handle cls = Dart_GetClass(lib, NewString("StackFrameTest"));
495 Dart_Handle result = Dart_Invoke(cls, NewString("testMain"), 0, NULL);
496 EXPECT_VALID(result);
497 int64_t elapsed_time = 0;
498 result = Dart_IntegerToInt64(result, &elapsed_time);
499 EXPECT_VALID(result);
500 benchmark->set_score(elapsed_time);
501}
502
503static uint8_t* malloc_allocator(uint8_t* ptr,
504 intptr_t old_size,
505 intptr_t new_size) {
506 return reinterpret_cast<uint8_t*>(realloc(ptr, new_size));
507}
508
509BENCHMARK_SIZE(CoreSnapshotSize) {
510 const char* kScriptChars =
511 "import 'dart:async';\n"
512 "import 'dart:core';\n"
513 "import 'dart:collection';\n"
514 "import 'dart:_internal';\n"
515 "import 'dart:math';\n"
516 "import 'dart:isolate';\n"
517 "import 'dart:mirrors';\n"
518 "import 'dart:typed_data';\n"
519 "\n";
520
521 // Start an Isolate, load a script and create a full snapshot.
522 uint8_t* vm_snapshot_data_buffer;
523 uint8_t* isolate_snapshot_data_buffer;
524 // Need to load the script into the dart: core library due to
525 // the import of dart:_internal.
526 TestCase::LoadCoreTestScript(kScriptChars, NULL);
527
528 TransitionNativeToVM transition(thread);
529 StackZone zone(thread);
530 HANDLESCOPE(thread);
531
532 Api::CheckAndFinalizePendingClasses(thread);
533
534 // Write snapshot with object content.
535 FullSnapshotWriter writer(Snapshot::kFull, &vm_snapshot_data_buffer,
536 &isolate_snapshot_data_buffer, &malloc_allocator,
537 NULL, NULL /* image_writer */);
538 writer.WriteFullSnapshot();
539 const Snapshot* snapshot =
540 Snapshot::SetupFromBuffer(isolate_snapshot_data_buffer);
541 ASSERT(snapshot->kind() == Snapshot::kFull);
542 benchmark->set_score(snapshot->length());
543
544 free(vm_snapshot_data_buffer);
545 free(isolate_snapshot_data_buffer);
546}
547
548BENCHMARK_SIZE(StandaloneSnapshotSize) {
549 const char* kScriptChars =
550 "import 'dart:async';\n"
551 "import 'dart:core';\n"
552 "import 'dart:collection';\n"
553 "import 'dart:convert';\n"
554 "import 'dart:math';\n"
555 "import 'dart:isolate';\n"
556 "import 'dart:mirrors';\n"
557 "import 'dart:typed_data';\n"
558 "import 'dart:io';\n"
559 "import 'dart:cli';\n"
560 "\n";
561
562 // Start an Isolate, load a script and create a full snapshot.
563 uint8_t* vm_snapshot_data_buffer;
564 uint8_t* isolate_snapshot_data_buffer;
565 // Need to load the script into the dart: core library due to
566 // the import of dart:_internal.
567 TestCase::LoadCoreTestScript(kScriptChars, NULL);
568
569 TransitionNativeToVM transition(thread);
570 StackZone zone(thread);
571 HANDLESCOPE(thread);
572
573 Api::CheckAndFinalizePendingClasses(thread);
574
575 // Write snapshot with object content.
576 FullSnapshotWriter writer(Snapshot::kFull, &vm_snapshot_data_buffer,
577 &isolate_snapshot_data_buffer, &malloc_allocator,
578 NULL, NULL /* image_writer */);
579 writer.WriteFullSnapshot();
580 const Snapshot* snapshot =
581 Snapshot::SetupFromBuffer(isolate_snapshot_data_buffer);
582 ASSERT(snapshot->kind() == Snapshot::kFull);
583 benchmark->set_score(snapshot->length());
584
585 free(vm_snapshot_data_buffer);
586 free(isolate_snapshot_data_buffer);
587}
588
589BENCHMARK(CreateMirrorSystem) {
590 const char* kScriptChars =
591 "import 'dart:mirrors';\n"
592 "\n"
593 "void benchmark() {\n"
594 " currentMirrorSystem();\n"
595 "}\n";
596
597 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
598
599 Timer timer(true, "currentMirrorSystem() benchmark");
600 timer.Start();
601 Dart_Handle result = Dart_Invoke(lib, NewString("benchmark"), 0, NULL);
602 EXPECT_VALID(result);
603 timer.Stop();
604 int64_t elapsed_time = timer.TotalElapsedTime();
605 benchmark->set_score(elapsed_time);
606}
607
608BENCHMARK(EnterExitIsolate) {
609 const char* kScriptChars =
610 "import 'dart:core';\n"
611 "\n";
612 const intptr_t kLoopCount = 1000000;
613 TestCase::LoadTestScript(kScriptChars, NULL);
614 {
615 TransitionNativeToVM transition(thread);
616 StackZone zone(thread);
617 HANDLESCOPE(thread);
618 Api::CheckAndFinalizePendingClasses(thread);
619 }
620 Dart_Isolate isolate = Dart_CurrentIsolate();
621 Timer timer(true, "Enter and Exit isolate");
622 timer.Start();
623 for (intptr_t i = 0; i < kLoopCount; i++) {
624 Dart_ExitIsolate();
625 Dart_EnterIsolate(isolate);
626 }
627 timer.Stop();
628 int64_t elapsed_time = timer.TotalElapsedTime();
629 benchmark->set_score(elapsed_time);
630}
631
632BENCHMARK(SerializeNull) {
633 TransitionNativeToVM transition(thread);
634 StackZone zone(thread);
635 HANDLESCOPE(thread);
636 const Object& null_object = Object::Handle();
637 const intptr_t kLoopCount = 1000000;
638 Timer timer(true, "Serialize Null");
639 timer.Start();
640 for (intptr_t i = 0; i < kLoopCount; i++) {
641 StackZone zone(thread);
642 MessageWriter writer(true);
643 std::unique_ptr<Message> message = writer.WriteMessage(
644 null_object, ILLEGAL_PORT, Message::kNormalPriority);
645
646 // Read object back from the snapshot.
647 MessageSnapshotReader reader(message.get(), thread);
648 reader.ReadObject();
649 }
650 timer.Stop();
651 int64_t elapsed_time = timer.TotalElapsedTime();
652 benchmark->set_score(elapsed_time);
653}
654
655BENCHMARK(SerializeSmi) {
656 TransitionNativeToVM transition(thread);
657 StackZone zone(thread);
658 HANDLESCOPE(thread);
659 const Integer& smi_object = Integer::Handle(Smi::New(42));
660 const intptr_t kLoopCount = 1000000;
661 Timer timer(true, "Serialize Smi");
662 timer.Start();
663 for (intptr_t i = 0; i < kLoopCount; i++) {
664 StackZone zone(thread);
665 MessageWriter writer(true);
666 std::unique_ptr<Message> message =
667 writer.WriteMessage(smi_object, ILLEGAL_PORT, Message::kNormalPriority);
668
669 // Read object back from the snapshot.
670 MessageSnapshotReader reader(message.get(), thread);
671 reader.ReadObject();
672 }
673 timer.Stop();
674 int64_t elapsed_time = timer.TotalElapsedTime();
675 benchmark->set_score(elapsed_time);
676}
677
678BENCHMARK(SimpleMessage) {
679 TransitionNativeToVM transition(thread);
680 StackZone zone(thread);
681 HANDLESCOPE(thread);
682 const Array& array_object = Array::Handle(Array::New(2));
683 array_object.SetAt(0, Integer::Handle(Smi::New(42)));
684 array_object.SetAt(1, Object::Handle());
685 const intptr_t kLoopCount = 1000000;
686 Timer timer(true, "Simple Message");
687 timer.Start();
688 for (intptr_t i = 0; i < kLoopCount; i++) {
689 StackZone zone(thread);
690 MessageWriter writer(true);
691 std::unique_ptr<Message> message = writer.WriteMessage(
692 array_object, ILLEGAL_PORT, Message::kNormalPriority);
693
694 // Read object back from the snapshot.
695 MessageSnapshotReader reader(message.get(), thread);
696 reader.ReadObject();
697 }
698 timer.Stop();
699 int64_t elapsed_time = timer.TotalElapsedTime();
700 benchmark->set_score(elapsed_time);
701}
702
703BENCHMARK(LargeMap) {
704 const char* kScript =
705 "makeMap() {\n"
706 " Map m = {};\n"
707 " for (int i = 0; i < 100000; ++i) m[i*13+i*(i>>7)] = i;\n"
708 " return m;\n"
709 "}";
710 Dart_Handle h_lib = TestCase::LoadTestScript(kScript, NULL);
711 EXPECT_VALID(h_lib);
712 Dart_Handle h_result = Dart_Invoke(h_lib, NewString("makeMap"), 0, NULL);
713 EXPECT_VALID(h_result);
714 TransitionNativeToVM transition(thread);
715 StackZone zone(thread);
716 HANDLESCOPE(thread);
717 Instance& map = Instance::Handle();
718 map ^= Api::UnwrapHandle(h_result);
719 const intptr_t kLoopCount = 100;
720 Timer timer(true, "Large Map");
721 timer.Start();
722 for (intptr_t i = 0; i < kLoopCount; i++) {
723 StackZone zone(thread);
724 MessageWriter writer(true);
725 std::unique_ptr<Message> message =
726 writer.WriteMessage(map, ILLEGAL_PORT, Message::kNormalPriority);
727
728 // Read object back from the snapshot.
729 MessageSnapshotReader reader(message.get(), thread);
730 reader.ReadObject();
731 }
732 timer.Stop();
733 int64_t elapsed_time = timer.TotalElapsedTime();
734 benchmark->set_score(elapsed_time);
735}
736
737BENCHMARK_MEMORY(InitialRSS) {
738 benchmark->set_score(bin::Process::MaxRSS());
739}
740
741} // namespace dart
742