1
0
mirror of https://github.com/dart-lang/sdk synced 2024-07-08 20:16:39 +00:00

[benchmarks/ffi] Add FfiCall benchmark with Handles

On x64 desktop in JIT the trampolines with Handles are a bit slower
than trampolines passing integers or Pointers.

FfiCall.Uint64x01(RunTime): 200.8482627033541 us.
FfiCall.PointerUint8x01(RunTime): 261.3910088865656 us.
FfiCall.Handlex01(RunTime): 355.4978670458585 us.
FfiCall.Handlex02(RunTime): 384.86376755820663 us.
FfiCall.Handlex04(RunTime): 492.896007885658 us.
FfiCall.Handlex10(RunTime): 846.1214043993232 us.
FfiCall.Handlex20(RunTime): 1193.412291169451 us.

Issue: https://github.com/dart-lang/sdk/issues/36858
Issue: https://github.com/dart-lang/sdk/issues/41319

New issue for optimizing multiple handles:
https://github.com/dart-lang/sdk/issues/42341

Also cleans up dart2/native which was erroneously left over from the
benchmark duplication for NNBD.

Change-Id: I81223fefc47129d00984492efb9502d5449f0d4a
Cq-Include-Trybots: luci.dart.try:benchmark-linux-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/145593
Commit-Queue: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Jonas Termansen <sortie@google.com>
This commit is contained in:
Daco Harkes 2020-06-15 13:27:16 +00:00 committed by commit-bot@chromium.org
parent 28606d040b
commit d87046342f
8 changed files with 514 additions and 202 deletions

2
DEPS
View File

@ -505,7 +505,7 @@ deps = {
"packages": [
{
"package": "dart/benchmarks/fficall",
"version": "_AKfaNTE0blKZwinuNMETidy44AK5b-u_rXmdBpat9UC",
"version": "ebF5aRXKDananlaN4Y8b0bbCNHT1MnkGbWqfpCpiND4C",
},
],
"dep_type": "cipd",

View File

@ -297,6 +297,67 @@ typedef Function20PointerUint8 = Pointer<Uint8> Function(
Function20PointerUint8 function20PointerUint8 = ffiTestFunctions.lookupFunction<
Function20PointerUint8, Function20PointerUint8>("Function20PointerUint8");
final function1handle = ffiTestFunctions.lookupFunction<Handle Function(Handle),
Object Function(Object)>("Function1Handle");
final function2handle = ffiTestFunctions.lookupFunction<
Handle Function(Handle, Handle),
Object Function(Object, Object)>("Function2Handle");
final function4handle = ffiTestFunctions.lookupFunction<
Handle Function(Handle, Handle, Handle, Handle),
Object Function(Object, Object, Object, Object)>("Function4Handle");
final function10handle = ffiTestFunctions.lookupFunction<
Handle Function(Handle, Handle, Handle, Handle, Handle, Handle, Handle,
Handle, Handle, Handle),
Object Function(Object, Object, Object, Object, Object, Object, Object,
Object, Object, Object)>("Function10Handle");
final function20handle = ffiTestFunctions.lookupFunction<
Handle Function(
Handle,
Handle,
Handle,
Handle,
Handle,
Handle,
Handle,
Handle,
Handle,
Handle,
Handle,
Handle,
Handle,
Handle,
Handle,
Handle,
Handle,
Handle,
Handle,
Handle),
Object Function(
Object,
Object,
Object,
Object,
Object,
Object,
Object,
Object,
Object,
Object,
Object,
Object,
Object,
Object,
Object,
Object,
Object,
Object,
Object,
Object)>("Function20Handle");
//
// Trampoline call.
//
@ -597,6 +658,69 @@ Pointer<Uint8> doCall20PointerUint8(
return x;
}
Object doCall1Handle(int length, Object p1) {
Object x = p1;
for (int i = 0; i < length; i++) {
x = function1handle(x);
}
return x;
}
Object doCall2Handle(int length, Object p1, Object p2) {
Object x = p1;
for (int i = 0; i < length; i++) {
x = function2handle(x, p2);
}
return x;
}
Object doCall4Handle(int length, Object p1, Object p2, Object p3, Object p4) {
Object x = p1;
for (int i = 0; i < length; i++) {
x = function4handle(x, p2, p3, p4);
}
return x;
}
Object doCall10Handle(int length, Object p1, Object p2, Object p3, Object p4,
Object p5, Object p6, Object p7, Object p8, Object p9, Object p10) {
Object x = p1;
for (int i = 0; i < length; i++) {
x = function10handle(x, p2, p3, p4, p5, p6, p7, p8, p9, p10);
}
return x;
}
Object doCall20Handle(
int length,
Object p1,
Object p2,
Object p3,
Object p4,
Object p5,
Object p6,
Object p7,
Object p8,
Object p9,
Object p10,
Object p11,
Object p12,
Object p13,
Object p14,
Object p15,
Object p16,
Object p17,
Object p18,
Object p19,
Object p20) {
Object x = p1;
for (int i = 0; i < length; i++) {
x = function20handle(x, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13,
p14, p15, p16, p17, p18, p19, p20);
}
return x;
}
//
// Benchmark fixtures.
//
@ -1106,6 +1230,109 @@ class PointerUint8x20 extends BenchmarkBase {
}
}
class MyClass {
int a;
MyClass(this.a);
}
class Handlex01 extends BenchmarkBase {
Handlex01() : super("FfiCall.Handlex01");
void run() {
final p1 = MyClass(123);
final x = doCall1Handle(N, p1);
if (!identical(p1, x)) {
throw Exception("$name: Unexpected result: $x");
}
}
}
class Handlex02 extends BenchmarkBase {
Handlex02() : super("FfiCall.Handlex02");
void run() {
final p1 = MyClass(123);
final p2 = MyClass(2);
final x = doCall2Handle(N, p1, p2);
if (!identical(p1, x)) {
throw Exception("$name: Unexpected result: $x");
}
}
}
class Handlex04 extends BenchmarkBase {
Handlex04() : super("FfiCall.Handlex04");
void run() {
final p1 = MyClass(123);
final p2 = MyClass(2);
final p3 = MyClass(3);
final p4 = MyClass(4);
final x = doCall4Handle(N, p1, p2, p3, p4);
if (!identical(p1, x)) {
throw Exception("$name: Unexpected result: $x");
}
}
}
class Handlex10 extends BenchmarkBase {
Handlex10() : super("FfiCall.Handlex10");
void run() {
final p1 = MyClass(123);
final p2 = MyClass(2);
final p3 = MyClass(3);
final p4 = MyClass(4);
final p5 = MyClass(5);
final p6 = MyClass(6);
final p7 = MyClass(7);
final p8 = MyClass(8);
final p9 = MyClass(9);
final p10 = MyClass(10);
final x = doCall10Handle(N, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
if (!identical(p1, x)) {
throw Exception("$name: Unexpected result: $x");
}
}
}
class Handlex20 extends BenchmarkBase {
Handlex20() : super("FfiCall.Handlex20");
void run() {
final p1 = MyClass(123);
final p2 = MyClass(2);
final p3 = MyClass(3);
final p4 = MyClass(4);
final p5 = MyClass(5);
final p6 = MyClass(6);
final p7 = MyClass(7);
final p8 = MyClass(8);
final p9 = MyClass(9);
final p10 = MyClass(10);
final p11 = MyClass(11);
final p12 = MyClass(12);
final p13 = MyClass(13);
final p14 = MyClass(14);
final p15 = MyClass(15);
final p16 = MyClass(16);
final p17 = MyClass(17);
final p18 = MyClass(18);
final p19 = MyClass(19);
final p20 = MyClass(20);
final x = doCall20Handle(N, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11,
p12, p13, p14, p15, p16, p17, p18, p19, p20);
if (!identical(p1, x)) {
throw Exception("$name: Unexpected result: $x");
}
}
}
//
// Main driver.
//
@ -1144,6 +1371,11 @@ main() {
() => PointerUint8x04(),
() => PointerUint8x10(),
() => PointerUint8x20(),
() => Handlex01(),
() => Handlex02(),
() => Handlex04(),
() => Handlex10(),
() => Handlex20(),
];
benchmarks.forEach((benchmark) => benchmark().report());
}

View File

@ -297,6 +297,67 @@ typedef Function20PointerUint8 = Pointer<Uint8> Function(
Function20PointerUint8 function20PointerUint8 = ffiTestFunctions.lookupFunction<
Function20PointerUint8, Function20PointerUint8>("Function20PointerUint8");
final function1handle = ffiTestFunctions.lookupFunction<Handle Function(Handle),
Object Function(Object)>("Function1Handle");
final function2handle = ffiTestFunctions.lookupFunction<
Handle Function(Handle, Handle),
Object Function(Object, Object)>("Function2Handle");
final function4handle = ffiTestFunctions.lookupFunction<
Handle Function(Handle, Handle, Handle, Handle),
Object Function(Object, Object, Object, Object)>("Function4Handle");
final function10handle = ffiTestFunctions.lookupFunction<
Handle Function(Handle, Handle, Handle, Handle, Handle, Handle, Handle,
Handle, Handle, Handle),
Object Function(Object, Object, Object, Object, Object, Object, Object,
Object, Object, Object)>("Function10Handle");
final function20handle = ffiTestFunctions.lookupFunction<
Handle Function(
Handle,
Handle,
Handle,
Handle,
Handle,
Handle,
Handle,
Handle,
Handle,
Handle,
Handle,
Handle,
Handle,
Handle,
Handle,
Handle,
Handle,
Handle,
Handle,
Handle),
Object Function(
Object,
Object,
Object,
Object,
Object,
Object,
Object,
Object,
Object,
Object,
Object,
Object,
Object,
Object,
Object,
Object,
Object,
Object,
Object,
Object)>("Function20Handle");
//
// Trampoline call.
//
@ -597,6 +658,69 @@ Pointer<Uint8> doCall20PointerUint8(
return x;
}
Object doCall1Handle(int length, Object p1) {
Object x = p1;
for (int i = 0; i < length; i++) {
x = function1handle(x);
}
return x;
}
Object doCall2Handle(int length, Object p1, Object p2) {
Object x = p1;
for (int i = 0; i < length; i++) {
x = function2handle(x, p2);
}
return x;
}
Object doCall4Handle(int length, Object p1, Object p2, Object p3, Object p4) {
Object x = p1;
for (int i = 0; i < length; i++) {
x = function4handle(x, p2, p3, p4);
}
return x;
}
Object doCall10Handle(int length, Object p1, Object p2, Object p3, Object p4,
Object p5, Object p6, Object p7, Object p8, Object p9, Object p10) {
Object x = p1;
for (int i = 0; i < length; i++) {
x = function10handle(x, p2, p3, p4, p5, p6, p7, p8, p9, p10);
}
return x;
}
Object doCall20Handle(
int length,
Object p1,
Object p2,
Object p3,
Object p4,
Object p5,
Object p6,
Object p7,
Object p8,
Object p9,
Object p10,
Object p11,
Object p12,
Object p13,
Object p14,
Object p15,
Object p16,
Object p17,
Object p18,
Object p19,
Object p20) {
Object x = p1;
for (int i = 0; i < length; i++) {
x = function20handle(x, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13,
p14, p15, p16, p17, p18, p19, p20);
}
return x;
}
//
// Benchmark fixtures.
//
@ -1106,6 +1230,109 @@ class PointerUint8x20 extends BenchmarkBase {
}
}
class MyClass {
int a;
MyClass(this.a);
}
class Handlex01 extends BenchmarkBase {
Handlex01() : super("FfiCall.Handlex01");
void run() {
final p1 = MyClass(123);
final x = doCall1Handle(N, p1);
if (!identical(p1, x)) {
throw Exception("$name: Unexpected result: $x");
}
}
}
class Handlex02 extends BenchmarkBase {
Handlex02() : super("FfiCall.Handlex02");
void run() {
final p1 = MyClass(123);
final p2 = MyClass(2);
final x = doCall2Handle(N, p1, p2);
if (!identical(p1, x)) {
throw Exception("$name: Unexpected result: $x");
}
}
}
class Handlex04 extends BenchmarkBase {
Handlex04() : super("FfiCall.Handlex04");
void run() {
final p1 = MyClass(123);
final p2 = MyClass(2);
final p3 = MyClass(3);
final p4 = MyClass(4);
final x = doCall4Handle(N, p1, p2, p3, p4);
if (!identical(p1, x)) {
throw Exception("$name: Unexpected result: $x");
}
}
}
class Handlex10 extends BenchmarkBase {
Handlex10() : super("FfiCall.Handlex10");
void run() {
final p1 = MyClass(123);
final p2 = MyClass(2);
final p3 = MyClass(3);
final p4 = MyClass(4);
final p5 = MyClass(5);
final p6 = MyClass(6);
final p7 = MyClass(7);
final p8 = MyClass(8);
final p9 = MyClass(9);
final p10 = MyClass(10);
final x = doCall10Handle(N, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
if (!identical(p1, x)) {
throw Exception("$name: Unexpected result: $x");
}
}
}
class Handlex20 extends BenchmarkBase {
Handlex20() : super("FfiCall.Handlex20");
void run() {
final p1 = MyClass(123);
final p2 = MyClass(2);
final p3 = MyClass(3);
final p4 = MyClass(4);
final p5 = MyClass(5);
final p6 = MyClass(6);
final p7 = MyClass(7);
final p8 = MyClass(8);
final p9 = MyClass(9);
final p10 = MyClass(10);
final p11 = MyClass(11);
final p12 = MyClass(12);
final p13 = MyClass(13);
final p14 = MyClass(14);
final p15 = MyClass(15);
final p16 = MyClass(16);
final p17 = MyClass(17);
final p18 = MyClass(18);
final p19 = MyClass(19);
final p20 = MyClass(20);
final x = doCall20Handle(N, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11,
p12, p13, p14, p15, p16, p17, p18, p19, p20);
if (!identical(p1, x)) {
throw Exception("$name: Unexpected result: $x");
}
}
}
//
// Main driver.
//
@ -1144,6 +1371,11 @@ main() {
() => PointerUint8x04(),
() => PointerUint8x10(),
() => PointerUint8x20(),
() => Handlex01(),
() => Handlex02(),
() => Handlex04(),
() => Handlex10(),
() => Handlex20(),
];
benchmarks.forEach((benchmark) => benchmark().report());
}

View File

@ -1,5 +0,0 @@
# Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
out/

View File

@ -1,60 +0,0 @@
# Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
# TODO(37531): Remove this makefile and build with sdk instead when
# benchmark runner gets support for that.
CC=gcc
CCARM=arm-linux-gnueabihf-gcc
CCARM64=aarch64-linux-gnu-gcc
CFLAGS=-Wall -g -O -fPIC
# Bump this whenever the benchmark is updated.
VERSION=1
.PHONY: all clean
all: out/linux/x64/libnative_functions.so out/linux/ia32/libnative_functions.so out/linux/arm64/libnative_functions.so out/linux/arm/libnative_functions.so
cipd:
cipd create -name dart/benchmarks/fficall -in out -install-mode copy -tag version:$(VERSION)
clean:
rm -rf *.o *.so out
out/linux/x64:
mkdir -p out/linux/x64
out/linux/x64/native_functions.o: native_functions.c | out/linux/x64
$(CC) $(CFLAGS) -c -o $@ native_functions.c
out/linux/x64/libnative_functions.so: out/linux/x64/native_functions.o
$(CC) $(CFLAGS) -s -shared -o $@ out/linux/x64/native_functions.o
out/linux/ia32:
mkdir -p out/linux/ia32
out/linux/ia32/native_functions.o: native_functions.c | out/linux/ia32
$(CC) $(CFLAGS) -m32 -c -o $@ native_functions.c
out/linux/ia32/libnative_functions.so: out/linux/ia32/native_functions.o
$(CC) $(CFLAGS) -m32 -s -shared -o $@ out/linux/ia32/native_functions.o
out/linux/arm64:
mkdir -p out/linux/arm64
out/linux/arm64/native_functions.o: native_functions.c | out/linux/arm64
$(CCARM64) $(CFLAGS) -c -o $@ native_functions.c
out/linux/arm64/libnative_functions.so: out/linux/arm64/native_functions.o
$(CCARM64) $(CFLAGS) -s -shared -o $@ out/linux/arm64/native_functions.o
out/linux/arm:
mkdir -p out/linux/arm
out/linux/arm/native_functions.o: native_functions.c | out/linux/arm
$(CCARM) $(CFLAGS) -c -o $@ native_functions.c
out/linux/arm/libnative_functions.so: out/linux/arm/native_functions.o
$(CCARM) $(CFLAGS) -s -shared -o $@ out/linux/arm/native_functions.o

View File

@ -1,132 +0,0 @@
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include <stdint.h>
uint8_t Function1Uint8(uint8_t x) { return x + 42; }
uint16_t Function1Uint16(uint16_t x) { return x + 42; }
uint32_t Function1Uint32(uint32_t x) { return x + 42; }
uint64_t Function1Uint64(uint64_t x) { return x + 42; }
int8_t Function1Int8(int8_t x) { return x + 42; }
int16_t Function1Int16(int16_t x) { return x + 42; }
int32_t Function1Int32(int32_t x) { return x + 42; }
int32_t Function2Int32(int32_t a, int32_t b) {
return a + b;
}
int32_t Function4Int32(int32_t a, int32_t b, int32_t c, int32_t d) {
return a + b + c + d;
}
int32_t Function10Int32(int32_t a, int32_t b, int32_t c, int32_t d, int32_t e,
int32_t f, int32_t g, int32_t h, int32_t i, int32_t j) {
return a + b + c + d + e + f + g + h + i + j;
}
int32_t Function20Int32(int32_t a, int32_t b, int32_t c, int32_t d, int32_t e,
int32_t f, int32_t g, int32_t h, int32_t i, int32_t j,
int32_t k, int32_t l, int32_t m, int32_t n, int32_t o,
int32_t p, int32_t q, int32_t r, int32_t s, int32_t t) {
return a + b + c + d + e + f + g + h + i + j + k + l + m + n + o +
p + q + r + s + t;
}
int64_t Function1Int64(int64_t x) { return x + 42; }
int64_t Function2Int64(int64_t a, int64_t b) {
return a + b;
}
int64_t Function4Int64(int64_t a, int64_t b, int64_t c, int64_t d) {
return a + b + c + d;
}
int64_t Function10Int64(int64_t a, int64_t b, int64_t c, int64_t d, int64_t e,
int64_t f, int64_t g, int64_t h, int64_t i, int64_t j) {
return a + b + c + d + e + f + g + h + i + j;
}
int64_t Function20Int64(int64_t a, int64_t b, int64_t c, int64_t d, int64_t e,
int64_t f, int64_t g, int64_t h, int64_t i, int64_t j,
int64_t k, int64_t l, int64_t m, int64_t n, int64_t o,
int64_t p, int64_t q, int64_t r, int64_t s, int64_t t) {
return a + b + c + d + e + f + g + h + i + j + k + l + m + n + o +
p + q + r + s + t;
}
float Function1Float(float x) { return x + 42.0f; }
float Function2Float(float a, float b) {
return a + b;
}
float Function4Float(float a, float b, float c, float d) {
return a + b + c + d;
}
float Function10Float(float a, float b, float c, float d, float e, float f,
float g, float h, float i, float j) {
return a + b + c + d + e + f + g + h + i + j;
}
float Function20Float(float a, float b, float c, float d, float e, float f,
float g, float h, float i, float j, float k, float l,
float m, float n, float o, float p, float q, float r,
float s, float t) {
return a + b + c + d + e + f + g + h + i + j + k + l + m + n + o + p +
q + r + s + t;
}
double Function1Double(double x) { return x + 42.0; }
double Function2Double(double a, double b) {
return a + b;
}
double Function4Double(double a, double b, double c, double d) {
return a + b + c + d;
}
double Function10Double(double a, double b, double c, double d, double e,
double f, double g, double h, double i, double j) {
return a + b + c + d + e + f + g + h + i + j;
}
double Function20Double(double a, double b, double c, double d, double e,
double f, double g, double h, double i, double j,
double k, double l, double m, double n, double o,
double p, double q, double r, double s, double t) {
return a + b + c + d + e + f + g + h + i + j + k + l + m + n + o +
p + q + r + s + t;
}
uint8_t *Function1PointerUint8(uint8_t *a) { return a + 1; }
uint8_t *Function2PointerUint8(uint8_t *a, uint8_t *b) { return a + 1; }
uint8_t *Function4PointerUint8(uint8_t *a, uint8_t *b, uint8_t *c, uint8_t *d) {
return a + 1;
}
uint8_t *Function10PointerUint8(uint8_t *a, uint8_t *b, uint8_t *c, uint8_t *d,
uint8_t *e, uint8_t *f, uint8_t *g, uint8_t *h,
uint8_t *i, uint8_t *j) {
return a + 1;
}
uint8_t *Function20PointerUint8(uint8_t *a, uint8_t *b, uint8_t *c, uint8_t *d,
uint8_t *e, uint8_t *f, uint8_t *g, uint8_t *h,
uint8_t *i, uint8_t *j, uint8_t *k, uint8_t *l,
uint8_t *m, uint8_t *n, uint8_t *o, uint8_t *p,
uint8_t *q, uint8_t *r, uint8_t *s,
uint8_t *t) {
return a + 1;
}

View File

@ -10,15 +10,12 @@ CCARM=arm-linux-gnueabihf-gcc
CCARM64=aarch64-linux-gnu-gcc
CFLAGS=-Wall -g -O -fPIC
# Bump this whenever the benchmark is updated.
VERSION=1
.PHONY: all clean
all: out/linux/x64/libnative_functions.so out/linux/ia32/libnative_functions.so out/linux/arm64/libnative_functions.so out/linux/arm/libnative_functions.so
cipd:
cipd create -name dart/benchmarks/fficall -in out -install-mode copy -tag version:$(VERSION)
cipd create -name dart/benchmarks/fficall -in out -install-mode copy
clean:
rm -rf *.o *.so out

View File

@ -130,3 +130,51 @@ uint8_t *Function20PointerUint8(uint8_t *a, uint8_t *b, uint8_t *c, uint8_t *d,
uint8_t *t) {
return a + 1;
}
void* Function1Handle(void* a) {
return a;
}
void* Function2Handle(void* a, void* b) {
return a;
}
void* Function4Handle(void* a, void* b, void* c, void* d) {
return a;
}
void* Function10Handle(void* a,
void* b,
void* c,
void* d,
void* e,
void* f,
void* g,
void* h,
void* i,
void* j) {
return a;
}
void* Function20Handle(void* a,
void* b,
void* c,
void* d,
void* e,
void* f,
void* g,
void* h,
void* i,
void* j,
void* k,
void* l,
void* m,
void* n,
void* o,
void* p,
void* q,
void* r,
void* s,
void* t) {
return a;
}