1
0
forked from Mirror/wren

Add a benchmark for wrenCall().

This commit is contained in:
Bob Nystrom
2015-12-23 17:29:53 -08:00
parent b7e62926ab
commit 15043b897f
6 changed files with 76 additions and 3 deletions

View File

@ -226,6 +226,12 @@ WrenInterpretResult wrenCallVarArgs(WrenVM* vm, WrenValue* method,
WrenValue** returnValue,
const char* argTypes, va_list args);
// Gets the numeric value of [value].
//
// It is an error to call this if the value is not a number.
double wrenGetValueDouble(WrenVM* vm, WrenValue* value);
// TODO: Functions for other types.
// Releases the reference stored in [value]. After calling this, [value] can no
// longer be used.
void wrenReleaseValue(WrenVM* vm, WrenValue* value);

View File

@ -1474,9 +1474,17 @@ WrenValue* wrenCaptureValue(WrenVM* vm, Value value)
return wrappedValue;
}
double wrenGetValueDouble(WrenVM* vm, WrenValue* value)
{
ASSERT(value != NULL, "Value cannot be NULL.");
ASSERT(IS_NUM(value->value), "Value must be a number.");
return AS_NUM(value->value);
}
void wrenReleaseValue(WrenVM* vm, WrenValue* value)
{
ASSERT(value != NULL, "NULL value.");
ASSERT(value != NULL, "Value cannot be NULL.");
// Update the VM's head pointer if we're releasing the first handle.
if (vm->valueHandles == value) vm->valueHandles = value->next;
@ -1734,7 +1742,7 @@ void wrenSetSlotBool(WrenVM* vm, int slot, bool value)
void wrenSetSlotBytes(WrenVM* vm, int slot, const char* bytes, int length)
{
ASSERT(bytes != NULL, "Byte arraybytes cannot be NULL.");
ASSERT(bytes != NULL, "Byte array cannot be NULL.");
setSlot(vm, slot, wrenNewString(vm, bytes, (size_t)length));
}

View File

@ -1,4 +1,5 @@
#include <string.h>
#include <time.h>
#include "benchmark.h"
@ -14,9 +15,56 @@ static void arguments(WrenVM* vm)
wrenSetSlotDouble(vm, 0, result);
}
const char* testScript =
"class Test {\n"
" static method(a, b, c, d) { a + b + c + d }\n"
"}\n";
static void call(WrenVM* vm)
{
int iterations = (int)wrenGetSlotDouble(vm, 1);
// Since the VM is not re-entrant, we can't call from within this foreign
// method. Instead, make a new VM to run the call test in.
WrenConfiguration config;
wrenInitConfiguration(&config);
WrenVM* otherVM = wrenNewVM(&config);
wrenInterpret(otherVM, testScript);
WrenValue* method = wrenGetMethod(otherVM, "main", "Test", "method(_,_,_,_)");
double startTime = (double)clock() / CLOCKS_PER_SEC;
double result = 0;
for (int i = 0; i < iterations; i++)
{
WrenValue* resultValue;
wrenCall(otherVM, method, &resultValue, "dddd", 1.0, 2.0, 3.0, 4.0);
result += wrenGetValueDouble(otherVM, resultValue);
wrenReleaseValue(otherVM, resultValue);
}
double elapsed = (double)clock() / CLOCKS_PER_SEC - startTime;
wrenReleaseValue(otherVM, method);
wrenFreeVM(otherVM);
if (result == (1.0 + 2.0 + 3.0 + 4.0) * iterations)
{
wrenSetSlotDouble(vm, 0, elapsed);
}
else
{
// Got the wrong result.
wrenSetSlotBool(vm, 0, false);
}
}
WrenForeignMethodFn benchmarkBindMethod(const char* signature)
{
if (strcmp(signature, "static Benchmark.arguments(_,_,_,_)") == 0) return arguments;
if (strcmp(signature, "static Benchmark.call(_)") == 0) return call;
return NULL;
}

View File

@ -64,7 +64,7 @@ static WrenForeignClassMethods bindForeignClass(
}
static void afterLoad(WrenVM* vm) {
if (strstr(testName, "call.wren") != NULL) callRunTests(vm);
if (strstr(testName, "/call.wren") != NULL) callRunTests(vm);
}
int main(int argc, const char* argv[])

View File

@ -0,0 +1,9 @@
class Benchmark {
foreign static call(iterations)
}
var result = Benchmark.call(1000000)
// Returns false if it didn't calculate the right value. Otherwise returns the
// elapsed time.
System.print(result is Num)
System.print("elapsed: %(result)")

View File

@ -51,6 +51,8 @@ def BENCHMARK(name, pattern):
regex = re.compile(pattern + "\n" + r"elapsed: (\d+\.\d+)", re.MULTILINE)
BENCHMARKS.append([name, regex, None])
BENCHMARK("api_call", "true")
BENCHMARK("api_foreign_method", "100000000")
BENCHMARK("binary_trees", """stretch tree of depth 13 check: -1