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 | |
23 | using dart::bin::File; |
24 | |
25 | namespace dart { |
26 | |
27 | Benchmark* Benchmark::first_ = NULL; |
28 | Benchmark* Benchmark::tail_ = NULL; |
29 | const char* Benchmark::executable_ = NULL; |
30 | |
31 | void 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 | // |
43 | BENCHMARK(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. |
65 | static 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. |
91 | static 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 | |
115 | static 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 | |
163 | BENCHMARK(GenKernelKernelLoadKernel) { |
164 | benchmark->set_score( |
165 | GenKernelKernelBenchmark("GenKernelKernelLoadKernel benchmark" , |
166 | /* benchmark_load */ true, |
167 | /* benchmark_read_bytecode */ false)); |
168 | } |
169 | |
170 | BENCHMARK(GenKernelKernelReadAllBytecode) { |
171 | benchmark->set_score( |
172 | GenKernelKernelBenchmark("GenKernelKernelReadAllBytecode benchmark" , |
173 | /* benchmark_load */ false, |
174 | /* benchmark_read_bytecode */ true)); |
175 | } |
176 | |
177 | BENCHMARK(GenKernelKernelCombined) { |
178 | benchmark->set_score( |
179 | GenKernelKernelBenchmark("GenKernelKernelCombined benchmark" , |
180 | /* benchmark_load */ true, |
181 | /* benchmark_read_bytecode */ true)); |
182 | } |
183 | |
184 | BENCHMARK_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 | // |
194 | BENCHMARK(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 | // |
212 | static 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. |
224 | static 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 | |
252 | static 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 | |
267 | BENCHMARK(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 | |
305 | static void NoopFinalizer(void* isolate_callback_data, |
306 | Dart_WeakPersistentHandle handle, |
307 | void* peer) {} |
308 | |
309 | // |
310 | // Measure time accessing internal and external strings. |
311 | // |
312 | BENCHMARK(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 | |
348 | static void vmservice_resolver(Dart_NativeArguments args) {} |
349 | |
350 | static 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 | // |
361 | BENCHMARK(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 | // |
409 | static 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 | |
444 | static 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. |
453 | BENCHMARK(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 | |
503 | static 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 | |
509 | BENCHMARK_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 | |
548 | BENCHMARK_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 | |
589 | BENCHMARK(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 | |
608 | BENCHMARK(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 | |
632 | BENCHMARK(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 | |
655 | BENCHMARK(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 | |
678 | BENCHMARK(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 | |
703 | BENCHMARK(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 | |
737 | BENCHMARK_MEMORY(InitialRSS) { |
738 | benchmark->set_score(bin::Process::MaxRSS()); |
739 | } |
740 | |
741 | } // namespace dart |
742 | |