Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
benchmark_test.cc
Go to the documentation of this file.
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"
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/app_snapshot.h"
19#include "vm/dart_api_impl.h"
20#include "vm/datastream.h"
21#include "vm/message_snapshot.h"
22#include "vm/stack_frame.h"
23#include "vm/timer.h"
24
25using dart::bin::File;
26
27namespace dart {
28
29Benchmark* Benchmark::first_ = nullptr;
30Benchmark* Benchmark::tail_ = nullptr;
31const char* Benchmark::executable_ = nullptr;
32
33void Benchmark::RunAll(const char* executable) {
34 SetExecutable(executable);
35 Benchmark* benchmark = first_;
36 while (benchmark != nullptr) {
37 benchmark->RunBenchmark();
38 benchmark = benchmark->next_;
39 }
40}
41
42//
43// Measure compile of all functions in dart core lib classes.
44//
45BENCHMARK(CorelibCompileAll) {
49 TransitionNativeToVM transition(thread);
50 StackZone zone(thread);
51 Timer timer;
52 timer.Start();
53 const Error& error =
54 Error::Handle(Library::CompileAll(/*ignore_error=*/true));
55 if (!error.IsNull()) {
56 OS::PrintErr("Unexpected error in CorelibCompileAll benchmark:\n%s",
57 error.ToErrorCString());
58 }
59 timer.Stop();
60 int64_t elapsed_time = timer.TotalElapsedTime();
61 benchmark->set_score(elapsed_time);
62}
63
64// This file is created by the target //runtime/bin:dart_kernel_platform_cc
65// which is depended on by run_vm_tests.
66static char* ComputeKernelServicePath(const char* arg) {
67 char buffer[2048];
68 char* kernel_service_path =
69 Utils::StrDup(File::GetCanonicalPath(nullptr, arg));
70 EXPECT(kernel_service_path != nullptr);
71 const char* compiler_path = "%s%sgen%skernel_service.dill";
72 const char* path_separator = File::PathSeparator();
73 ASSERT(path_separator != nullptr && strlen(path_separator) == 1);
74 char* ptr = strrchr(kernel_service_path, *path_separator);
75 while (ptr != nullptr) {
76 *ptr = '\0';
77 Utils::SNPrint(buffer, ARRAY_SIZE(buffer), compiler_path,
78 kernel_service_path, path_separator, path_separator);
79 if (File::Exists(nullptr, buffer)) {
80 break;
81 }
82 ptr = strrchr(kernel_service_path, *path_separator);
83 }
84 free(kernel_service_path);
85 if (ptr == nullptr) {
86 return nullptr;
87 }
88 return Utils::StrDup(buffer);
89}
90
91//
92// Measure creation of core isolate from a snapshot.
93//
94BENCHMARK(CorelibIsolateStartup) {
95 const int kNumIterations = 1000;
96 Timer timer;
97 Isolate* isolate = thread->isolate();
99 for (int i = 0; i < kNumIterations; i++) {
100 timer.Start();
102 timer.Stop();
104 }
105 benchmark->set_score(timer.TotalElapsedTime() / kNumIterations);
106 Dart_EnterIsolate(reinterpret_cast<Dart_Isolate>(isolate));
107}
108
109//
110// Measure invocation of Dart API functions.
111//
121
122// The specific api functions called here are a bit arbitrary. We are
123// trying to get a sense of the overhead for using the dart api.
126 EXPECT_EQ(3, count);
127
128 // Get native field from receiver.
129 intptr_t receiver_value;
130 Dart_Handle result = Dart_GetNativeReceiver(args, &receiver_value);
132 EXPECT_EQ(7, receiver_value);
133
134 // Get param1.
136 EXPECT_VALID(param1);
137 EXPECT(Dart_IsInteger(param1));
138 bool fits = false;
139 result = Dart_IntegerFitsIntoInt64(param1, &fits);
141 EXPECT(fits);
142 int64_t value1;
143 result = Dart_IntegerToInt64(param1, &value1);
145 EXPECT_LE(0, value1);
146 EXPECT_LE(value1, 1000000);
147
148 // Return param + receiver.field.
149 Dart_SetReturnValue(args, Dart_NewInteger(value1 * receiver_value));
150}
151
153 int argument_count,
154 bool* auto_setup_scope) {
155 ASSERT(auto_setup_scope != nullptr);
156 *auto_setup_scope = true;
157 const char* cstr = nullptr;
160 if (strcmp(cstr, "init") == 0) {
161 return InitNativeFields;
162 } else {
163 return UseDartApi;
164 }
165}
166
168 const int kNumIterations = 1000000;
169 const char* kScriptChars = R"(
170import 'dart:nativewrappers';
171
172base class Class extends NativeFieldWrapperClass1 {
173 @pragma("vm:external-name", "init")
174 external void init();
175 @pragma("vm:external-name", "method")
176 external int method(int param1, int param2);
177}
178
179void benchmark(int count) {
180 Class c = Class();
181 c.init();
182 for (int i = 0; i < count; i++) {
183 c.method(i,7);
184 }
185})";
186
191
192 Dart_Handle args[1];
193 args[0] = Dart_NewInteger(kNumIterations);
194
195 // Warmup first to avoid compilation jitters.
196 result = Dart_Invoke(lib, NewString("benchmark"), 1, args);
198
199 Timer timer;
200 timer.Start();
201 result = Dart_Invoke(lib, NewString("benchmark"), 1, args);
203 timer.Stop();
204 int64_t elapsed_time = timer.TotalElapsedTime();
205 benchmark->set_score(elapsed_time);
206}
207
209
211 int arg_count,
212 bool* auto_setup_scope) {
213 ASSERT(auto_setup_scope != nullptr);
214 *auto_setup_scope = false;
215 return &vmservice_resolver;
216}
217
218//
219// Measure compile of all kernel Service(CFE) functions.
220//
221BENCHMARK(KernelServiceCompileAll) {
222 // kernel_service.dill is built with sound null safety.
227 File* file = File::Open(nullptr, dill_path, File::kRead);
228 EXPECT(file != nullptr);
230 intptr_t kernel_buffer_size = file->Length();
231 uint8_t* kernel_buffer =
232 reinterpret_cast<uint8_t*>(malloc(kernel_buffer_size));
233 bool read_fully = file->ReadFully(kernel_buffer, kernel_buffer_size);
234 EXPECT(read_fully);
236 Dart_LoadScriptFromKernel(kernel_buffer, kernel_buffer_size);
238 Dart_Handle service_lib = Dart_LookupLibrary(NewString("dart:vmservice_io"));
239 ASSERT(!Dart_IsError(service_lib));
240 Dart_SetNativeResolver(service_lib, NativeResolver, nullptr);
243
244 Timer timer;
245 timer.Start();
246#if !defined(PRODUCT)
247 const bool old_flag = FLAG_background_compilation;
248 FLAG_background_compilation = false;
249#endif
251#if !defined(PRODUCT)
252 FLAG_background_compilation = old_flag;
253#endif
255 timer.Stop();
256 int64_t elapsed_time = timer.TotalElapsedTime();
257 benchmark->set_score(elapsed_time);
258 free(dill_path);
259 free(kernel_buffer);
260}
261
262//
263// Measure frame lookup during stack traversal.
264//
266 Timer timer;
267 timer.Start();
268 {
269 Thread* thread = Thread::Current();
270 TransitionNativeToVM transition(thread);
271 const int kNumIterations = 100;
272 Code& code = Code::Handle(thread->zone());
273 for (int i = 0; i < kNumIterations; i++) {
276 StackFrame* frame = frames.NextFrame();
277 while (frame != nullptr) {
278 if (frame->IsStubFrame()) {
279 code = frame->LookupDartCode();
280 EXPECT(code.function() == Function::null());
281 } else if (frame->IsDartFrame()) {
282 code = frame->LookupDartCode();
283 EXPECT(code.function() != Function::null());
284 }
285 frame = frames.NextFrame();
286 }
287 }
288 }
289 timer.Stop();
290 int64_t elapsed_time = timer.TotalElapsedTime();
292}
293
295 int arg_count,
296 bool* auto_setup_scope) {
297 ASSERT(auto_setup_scope != nullptr);
298 *auto_setup_scope = false;
300}
301
302// Unit test case to verify stack frame iteration.
303BENCHMARK(FrameLookup) {
304 const char* kScriptChars =
305 R"(
306 class StackFrame {
307 @pragma('vm:external-name', 'StackFrame_accessFrame')
308 external static int accessFrame();
309 }
310 class First {
311 First() { }
312 int method1(int param) {
313 if (param == 1) {
314 param = method2(200);
315 } else {
316 param = method2(100);
318 return param;
319 }
320 int method2(int param) {
321 if (param == 200) {
322 return First.staticmethod(this, param);
323 } else {
324 return First.staticmethod(this, 10);
325 }
326 }
327 static int staticmethod(First obj, int param) {
328 if (param == 10) {
329 return obj.method3(10);
330 } else {
331 return obj.method3(200);
332 }
333 }
334 int method3(int param) {
335 return StackFrame.accessFrame();
336 }
337 }
338 class StackFrameTest {
339 static int testMain() {
340 First obj = new First();
341 return obj.method1(1);
342 }
343 }
344 )";
345 Dart_Handle lib =
347 Dart_Handle cls = Dart_GetClass(lib, NewString("StackFrameTest"));
348 Dart_Handle result = Dart_Invoke(cls, NewString("testMain"), 0, nullptr);
350 int64_t elapsed_time = 0;
351 result = Dart_IntegerToInt64(result, &elapsed_time);
353 benchmark->set_score(elapsed_time);
354}
355
356BENCHMARK_SIZE(CoreSnapshotSize) {
357 const char* kScriptChars =
358 "import 'dart:async';\n"
359 "import 'dart:core';\n"
360 "import 'dart:collection';\n"
361 "import 'dart:_internal';\n"
362 "import 'dart:math';\n"
363 "import 'dart:isolate';\n"
364 "import 'dart:mirrors';\n"
365 "import 'dart:typed_data';\n"
366 "\n";
367
368 // Start an Isolate, load a script and create a full snapshot.
369 // Need to load the script into the dart: core library due to
370 // the import of dart:_internal.
371 TestCase::LoadCoreTestScript(kScriptChars, nullptr);
372
373 TransitionNativeToVM transition(thread);
374 StackZone zone(thread);
375
377
378 // Write snapshot with object content.
379 MallocWriteStream vm_snapshot_data(FullSnapshotWriter::kInitialSize);
380 MallocWriteStream isolate_snapshot_data(FullSnapshotWriter::kInitialSize);
381 FullSnapshotWriter writer(
382 Snapshot::kFullCore, &vm_snapshot_data, &isolate_snapshot_data,
383 /*vm_image_writer=*/nullptr, /*iso_image_writer=*/nullptr);
384 writer.WriteFullSnapshot();
385 const Snapshot* snapshot =
386 Snapshot::SetupFromBuffer(isolate_snapshot_data.buffer());
387 ASSERT(snapshot->kind() == Snapshot::kFullCore);
388 benchmark->set_score(snapshot->length());
390
391BENCHMARK_SIZE(StandaloneSnapshotSize) {
392 const char* kScriptChars =
393 "import 'dart:async';\n"
394 "import 'dart:core';\n"
395 "import 'dart:collection';\n"
396 "import 'dart:convert';\n"
397 "import 'dart:math';\n"
398 "import 'dart:isolate';\n"
399 "import 'dart:mirrors';\n"
400 "import 'dart:typed_data';\n"
401 "import 'dart:io';\n"
402 "import 'dart:cli';\n"
403 "\n";
404
405 // Start an Isolate, load a script and create a full snapshot.
406 // Need to load the script into the dart: core library due to
407 // the import of dart:_internal.
408 TestCase::LoadCoreTestScript(kScriptChars, nullptr);
409
410 TransitionNativeToVM transition(thread);
411 StackZone zone(thread);
412
414
415 // Write snapshot with object content.
418 FullSnapshotWriter writer(
419 Snapshot::kFullCore, &vm_snapshot_data, &isolate_snapshot_data,
420 /*vm_image_writer=*/nullptr, /*iso_image_writer=*/nullptr);
421 writer.WriteFullSnapshot();
422 const Snapshot* snapshot =
423 Snapshot::SetupFromBuffer(isolate_snapshot_data.buffer());
424 ASSERT(snapshot->kind() == Snapshot::kFullCore);
425 benchmark->set_score(snapshot->length());
426}
427
428BENCHMARK(CreateMirrorSystem) {
429 const char* kScriptChars =
430 "import 'dart:mirrors';\n"
431 "\n"
432 "void benchmark() {\n"
433 " currentMirrorSystem();\n"
434 "}\n";
435
436 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
437
438 Timer timer;
439 timer.Start();
440 Dart_Handle result = Dart_Invoke(lib, NewString("benchmark"), 0, nullptr);
442 timer.Stop();
443 int64_t elapsed_time = timer.TotalElapsedTime();
444 benchmark->set_score(elapsed_time);
445}
446
447BENCHMARK(EnterExitIsolate) {
448 const char* kScriptChars =
449 "import 'dart:core';\n"
450 "\n";
451 const intptr_t kLoopCount = 1000000;
452 TestCase::LoadTestScript(kScriptChars, nullptr);
453 {
454 TransitionNativeToVM transition(thread);
455 StackZone zone(thread);
457 }
459 Timer timer;
460 timer.Start();
461 for (intptr_t i = 0; i < kLoopCount; i++) {
463 Dart_EnterIsolate(isolate);
464 }
465 timer.Stop();
466 int64_t elapsed_time = timer.TotalElapsedTime();
467 benchmark->set_score(elapsed_time);
468}
469
470BENCHMARK(SerializeNull) {
471 TransitionNativeToVM transition(thread);
472 StackZone zone(thread);
473 const Object& null_object = Object::Handle();
474 const intptr_t kLoopCount = 1000000;
475 Timer timer;
476 timer.Start();
477 for (intptr_t i = 0; i < kLoopCount; i++) {
478 StackZone zone(thread);
479 std::unique_ptr<Message> message =
480 WriteMessage(/* same_group */ false, null_object, ILLEGAL_PORT,
482
483 // Read object back from the snapshot.
484 ReadMessage(thread, message.get());
485 }
486 timer.Stop();
487 int64_t elapsed_time = timer.TotalElapsedTime();
488 benchmark->set_score(elapsed_time);
489}
490
491BENCHMARK(SerializeSmi) {
492 TransitionNativeToVM transition(thread);
493 StackZone zone(thread);
494 const Integer& smi_object = Integer::Handle(Smi::New(42));
495 const intptr_t kLoopCount = 1000000;
496 Timer timer;
497 timer.Start();
498 for (intptr_t i = 0; i < kLoopCount; i++) {
499 StackZone zone(thread);
500 std::unique_ptr<Message> message =
501 WriteMessage(/* same_group */ false, smi_object, ILLEGAL_PORT,
503
504 // Read object back from the snapshot.
505 ReadMessage(thread, message.get());
506 }
507 timer.Stop();
508 int64_t elapsed_time = timer.TotalElapsedTime();
509 benchmark->set_score(elapsed_time);
510}
511
512BENCHMARK(SimpleMessage) {
513 TransitionNativeToVM transition(thread);
514 StackZone zone(thread);
515 const Array& array_object = Array::Handle(Array::New(2));
516 array_object.SetAt(0, Integer::Handle(Smi::New(42)));
517 array_object.SetAt(1, Object::Handle());
518 const intptr_t kLoopCount = 1000000;
519 Timer timer;
520 timer.Start();
521 for (intptr_t i = 0; i < kLoopCount; i++) {
522 StackZone zone(thread);
523 std::unique_ptr<Message> message =
524 WriteMessage(/* same_group */ false, array_object, ILLEGAL_PORT,
526
527 // Read object back from the snapshot.
528 ReadMessage(thread, message.get());
529 }
530 timer.Stop();
531 int64_t elapsed_time = timer.TotalElapsedTime();
532 benchmark->set_score(elapsed_time);
533}
534
535BENCHMARK(LargeMap) {
536 const char* kScript =
537 "makeMap() {\n"
538 " Map m = {};\n"
539 " for (int i = 0; i < 100000; ++i) m[i*13+i*(i>>7)] = i;\n"
540 " return m;\n"
541 "}";
542 Dart_Handle h_lib = TestCase::LoadTestScript(kScript, nullptr);
543 EXPECT_VALID(h_lib);
544 Dart_Handle h_result = Dart_Invoke(h_lib, NewString("makeMap"), 0, nullptr);
545 EXPECT_VALID(h_result);
546 TransitionNativeToVM transition(thread);
547 StackZone zone(thread);
548 Instance& map = Instance::Handle();
549 map ^= Api::UnwrapHandle(h_result);
550 const intptr_t kLoopCount = 100;
551 Timer timer;
552 timer.Start();
553 for (intptr_t i = 0; i < kLoopCount; i++) {
554 StackZone zone(thread);
555 std::unique_ptr<Message> message = WriteMessage(
556 /* same_group */ false, map, ILLEGAL_PORT, Message::kNormalPriority);
557
558 // Read object back from the snapshot.
559 ReadMessage(thread, message.get());
560 }
561 timer.Stop();
562 int64_t elapsed_time = timer.TotalElapsedTime();
563 benchmark->set_score(elapsed_time);
564}
565
566BENCHMARK_MEMORY(InitialRSS) {
567 benchmark->set_score(bin::Process::MaxRSS());
568}
569
570} // namespace dart
int count
#define EXPECT(type, expectedAlignment, expectedSize)
#define BENCHMARK_MEMORY(name)
#define BENCHMARK(name)
#define BENCHMARK_SIZE(name)
static ObjectPtr UnwrapHandle(Dart_Handle object)
static Dart_Handle CheckAndFinalizePendingClasses(Thread *thread)
static ArrayPtr New(intptr_t len, Heap::Space space=Heap::kNew)
Definition object.h:10933
static const char * Executable()
static void RunAll(const char *executable)
static void SetExecutable(const char *arg)
static constexpr intptr_t kInitialSize
static ErrorPtr CompileAll(bool ignore_error=false)
Definition object.cc:15275
@ kNormalPriority
Definition message.h:28
static void static void PrintErr(const char *format,...) PRINTF_ATTRIBUTE(1
static ObjectPtr null()
Definition object.h:433
static Object & Handle()
Definition object.h:407
static SmiPtr New(intptr_t value)
Definition object.h:9985
Kind kind() const
Definition snapshot.h:60
static const Snapshot * SetupFromBuffer(const void *raw_memory)
Definition snapshot.cc:30
intptr_t length() const
Definition snapshot.h:56
static Dart_Handle LoadTestScript(const char *script, Dart_NativeEntryResolver resolver, const char *lib_uri=RESOLVED_USER_TEST_URI, bool finalize=true, bool allow_compile_errors=false)
Definition unit_test.cc:422
static Dart_Isolate CreateTestIsolate(const char *name=nullptr, void *isolate_group_data=nullptr, void *isolate_data=nullptr)
Definition unit_test.cc:139
static Dart_Handle LoadCoreTestScript(const char *script, Dart_NativeEntryResolver resolver)
Definition unit_test.cc:624
Zone * zone() const
static Thread * Current()
Definition thread.h:361
void Stop()
Definition timer.h:117
void Start()
Definition timer.h:111
int64_t TotalElapsedTime() const
Definition timer.h:123
static int SNPrint(char *str, size_t size, const char *format,...) PRINTF_ATTRIBUTE(3
static char * StrDup(const char *s)
static void SetNativeResolver(BuiltinLibraryId id)
Definition builtin.cc:28
static int64_t MaxRSS()
#define ILLEGAL_PORT
Definition dart_api.h:1530
struct _Dart_Handle * Dart_Handle
Definition dart_api.h:258
struct _Dart_Isolate * Dart_Isolate
Definition dart_api.h:88
struct _Dart_NativeArguments * Dart_NativeArguments
Definition dart_api.h:3010
void(* Dart_NativeFunction)(Dart_NativeArguments arguments)
Definition dart_api.h:3198
#define ASSERT(E)
double frame
Definition examples.cpp:31
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
static const uint8_t buffer[]
const uint8_t uint32_t uint32_t GError ** error
GAsyncResult * result
int argument_count
Definition fuchsia.cc:52
Win32Message message
static Dart_NativeFunction NativeResolver(Dart_Handle name, int arg_count, bool *auto_setup_scope)
ObjectPtr ReadMessage(Thread *thread, Message *message)
const char *const name
DART_EXPORT Dart_Handle Dart_FinalizeLoading(bool complete_futures)
DART_EXPORT void Dart_EnterIsolate(Dart_Isolate isolate)
DART_EXPORT Dart_Handle Dart_Invoke(Dart_Handle target, Dart_Handle name, int number_of_arguments, Dart_Handle *arguments)
DART_EXPORT Dart_Handle Dart_GetClass(Dart_Handle library, Dart_Handle class_name)
static void UseDartApi(Dart_NativeArguments args)
void * malloc(size_t size)
Definition allocation.cc:19
DART_EXPORT Dart_Handle Dart_NewInteger(int64_t value)
DART_EXPORT void Dart_SetReturnValue(Dart_NativeArguments args, Dart_Handle retval)
static char * ComputeKernelServicePath(const char *arg)
DART_EXPORT Dart_Isolate Dart_CurrentIsolate()
DART_EXPORT bool Dart_IsError(Dart_Handle handle)
DART_EXPORT Dart_Handle Dart_SetNativeInstanceField(Dart_Handle obj, int index, intptr_t value)
static void InitNativeFields(Dart_NativeArguments args)
DART_EXPORT Dart_Handle Dart_SetNativeResolver(Dart_Handle library, Dart_NativeEntryResolver resolver, Dart_NativeEntrySymbol symbol)
static Dart_NativeFunction bm_uda_lookup(Dart_Handle name, int argument_count, bool *auto_setup_scope)
DART_EXPORT Dart_Handle Dart_GetNativeArgument(Dart_NativeArguments args, int index)
DART_EXPORT void Dart_ExitIsolate()
Dart_Handle NewString(const char *str)
static void vmservice_resolver(Dart_NativeArguments args)
DART_EXPORT Dart_Handle Dart_CompileAll()
std::unique_ptr< Message > WriteMessage(bool same_group, const Object &obj, Dart_Port dest_port, Message::Priority priority)
DART_EXPORT Dart_Handle Dart_IntegerFitsIntoInt64(Dart_Handle integer, bool *fits)
DART_EXPORT Dart_Handle Dart_LookupLibrary(Dart_Handle url)
DART_EXPORT int Dart_GetNativeArgumentCount(Dart_NativeArguments args)
DART_EXPORT Dart_Handle Dart_LoadScriptFromKernel(const uint8_t *buffer, intptr_t buffer_size)
DART_EXPORT bool Dart_IsInteger(Dart_Handle object)
DART_EXPORT Dart_Handle Dart_StringToCString(Dart_Handle object, const char **cstr)
DART_EXPORT void Dart_ShutdownIsolate()
DART_EXPORT Dart_Handle Dart_GetNativeReceiver(Dart_NativeArguments args, intptr_t *value)
static Dart_NativeFunction StackFrameNativeResolver(Dart_Handle name, int arg_count, bool *auto_setup_scope)
static void StackFrame_accessFrame(Dart_NativeArguments args)
DART_EXPORT Dart_Handle Dart_IntegerToInt64(Dart_Handle integer, int64_t *value)
SI auto map(std::index_sequence< I... >, Fn &&fn, const Args &... args) -> skvx::Vec< sizeof...(I), decltype(fn(args[0]...))>
Definition SkVx.h:680
#define RESOLVED_USER_TEST_URI
Definition unit_test.h:317
#define EXPECT_VALID(handle)
Definition unit_test.h:650
#define ARRAY_SIZE(array)
Definition globals.h:72