From d2050dce394bfcfbcff9bcbb6fd03c493aedd47d Mon Sep 17 00:00:00 2001 From: "turnidge@google.com" Date: Wed, 4 Apr 2012 19:47:22 +0000 Subject: [PATCH] Add a unit test Benchmark_UseDartApi to measure dart api overhead. Sample output: Benchmark_UseDartApi: 3.245700 us per iteration Review URL: https://chromiumcodereview.appspot.com//9979016 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@6189 260f80e4-7a28-3924-810f-c04153c831b5 --- runtime/vm/dart_api_impl.cc | 5 ++ runtime/vm/dart_api_impl_test.cc | 105 +++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc index a087815241f..e9efaa6fe98 100644 --- a/runtime/vm/dart_api_impl.cc +++ b/runtime/vm/dart_api_impl.cc @@ -2919,6 +2919,11 @@ DART_EXPORT Dart_Handle Dart_GetNativeArgument(Dart_NativeArguments args, int index) { DARTSCOPE(Isolate::Current()); NativeArguments* arguments = reinterpret_cast(args); + if (index < 0 || index >= arguments->Count()) { + return Api::NewError( + "%s: argument 'index' out of range. Expected 0..%d but saw %d.", + CURRENT_FUNC, arguments->Count() - 1, index); + } const Object& obj = Object::Handle(arguments->At(index)); return Api::NewLocalHandle(obj); } diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc index 49b5a9c7745..6d4c51d5b96 100644 --- a/runtime/vm/dart_api_impl_test.cc +++ b/runtime/vm/dart_api_impl_test.cc @@ -4740,6 +4740,111 @@ TEST_CASE(IsolateInterrupt) { Isolate::SetInterruptCallback(saved); } + +void InitNativeFields(Dart_NativeArguments args) { + Dart_EnterScope(); + int count = Dart_GetNativeArgumentCount(args); + EXPECT_EQ(1, count); + + Dart_Handle recv = Dart_GetNativeArgument(args, 0); + EXPECT(!Dart_IsError(recv)); + Dart_Handle result = Dart_SetNativeInstanceField(recv, 0, 7); + EXPECT(!Dart_IsError(result)); + + Dart_ExitScope(); +} + + +// The specific api functions called here are a bit arbitrary. We are +// trying to get a sense of the overhead for using the dart api. +void UseDartApi(Dart_NativeArguments args) { + Dart_EnterScope(); + int count = Dart_GetNativeArgumentCount(args); + EXPECT_EQ(3, count); + + // Get the receiver. + Dart_Handle recv = Dart_GetNativeArgument(args, 0); + EXPECT(!Dart_IsError(recv)); + + // Get param1. + Dart_Handle param1 = Dart_GetNativeArgument(args, 1); + EXPECT(!Dart_IsError(param1)); + EXPECT(Dart_IsInteger(param1)); + bool fits = false; + Dart_Handle result = Dart_IntegerFitsIntoInt64(param1, &fits); + EXPECT(!Dart_IsError(result) && fits); + int64_t value1; + result = Dart_IntegerToInt64(param1, &value1); + EXPECT(!Dart_IsError(result)); + EXPECT_LE(0, value1); + EXPECT_LE(value1, 1000000); + + // Get native field from receiver. + intptr_t value2; + result = Dart_GetNativeInstanceField(recv, 0, &value2); + EXPECT(!Dart_IsError(result)); + EXPECT_EQ(7, value2); + + // Return param + receiver.field. + Dart_SetReturnValue(args, Dart_NewInteger(value1 * value2)); + Dart_ExitScope(); +} + + +static Dart_NativeFunction bm_uda_lookup(Dart_Handle name, int argument_count) { + const char* cstr = NULL; + Dart_Handle result = Dart_StringToCString(name, &cstr); + EXPECT(!Dart_IsError(result)); + if (strcmp(cstr, "init") == 0) { + return InitNativeFields; + } else { + return UseDartApi; + } +} + + +TEST_CASE(Benchmark_UseDartApi) { + const char* kScriptChars = + "class Class extends NativeFieldsWrapper{\n" + " int init() native 'init';\n" + " int method(int param1, int param2) native 'method';\n" + "}\n" + "\n" + "double benchmark(int count) {\n" + " Class c = new Class();\n" + " c.init();\n" + " Stopwatch sw = new Stopwatch.start();\n" + " for (int i = 0; i < count; i++) {\n" + " c.method(i,7);\n" + " }\n" + " sw.stop();\n" + " return sw.elapsedInUs() / count;\n" + "}\n"; + + Dart_Handle lib = TestCase::LoadTestScript( + kScriptChars, + reinterpret_cast(bm_uda_lookup)); + + // Create a native wrapper class with native fields. + Dart_Handle result = Dart_CreateNativeWrapperClass( + lib, + Dart_NewString("NativeFieldsWrapper"), + 1); + EXPECT_VALID(result); + + Dart_Handle args[1]; + args[0] = Dart_NewInteger(100000); + result = Dart_Invoke(lib, + Dart_NewString("benchmark"), + 1, + args); + EXPECT_VALID(result); + EXPECT(Dart_IsDouble(result)); + double out; + result = Dart_DoubleValue(result, &out); + fprintf(stderr, "Benchmark_UseDartApi: %f us per iteration\n", out); +} + #endif // defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64). } // namespace dart