Stepan Sindelar
OracleLabs
The following is intended to provide some insight into a line of research in Oracle Labs. It is intended for information purposes only, and may not be incorporated into any contract. It is not a commitment to deliver any material, code, or functionality, and should not be relied upon in making purchasing decisions. Oracle reserves the right to alter its development plans and practices at any time, and the development, release, and timing of any features or functionality described in connection with any Oracle product or service remains at the sole discretion of Oracle. Any views expressed in this presentation are my own and do not necessarily reflect the views of Oracle.
FastR is a GNU-R compatible implementation of R built on top of the GraalVM platform. It is currently based on R 3.5.1 and reuses the base packages of GNU-R.
Open source and licensed under GPLv3.
GNU-R == the reference implementation of R
GraalVM is a universal virtual machine for running applications written in JavaScript, Python, Ruby, R, JVM-based languages like Java.
Language Implementation Framework based on self-optimizing abstract syntax trees and partial evaluation.
Abstract syntax tree (AST)
2 + x
Self optimizing AST
foo <- function(x) 2 + x
foo(0.2)
Partial evaluation
int f(int x, int y) {
return x*42 + y;
}
// Given x = 3
int f(int y) {
return 126 + y;
}
Partial evaluation of an AST interpreter
double interpret(AST ast, Environment env) {
ast.execute(env)
}
// Partially evaluate "interpreter"
// given fixed self-optimized AST of program "2+x"
double interpret(Environment env) {
return 2 + env.get("x")
}
// ==> Compile this code with Graal to machine code
# differences in paths
assertthat => s/Path '.*' does not exist/Path 'path/to/somewhere' does not exist
assertthat => s/Path '.*' is not a directory/Path 'path/to/dir' is not a directory
# different output format in GNUR and FastR
assertthat => R/[1] "mean %has_args% \"y\" is not TRUE"/REPLACED has_args
assertthat => R/[1] "`%has_args%`(f = mean, args = \"y\") is not TRUE"/REPLACED has_args
Work-in-progress
SEXP foo(SEXP x) {
// no translation to opaque pointer/handle
// x directly points to the FastR object
// INTEGER function in FastR gets directly the FastR object
// no translation from handle to FastR object
int* data = INTEGER(x)
// INTEGER returns special Java object "VectorWrapper"
// that represents the data of x
data[1] = 42;
// Graal LLVM calls VectorWrapper.writeArrayElement(1, 42)
DATAPTR(mylist)[0] = x;
// Graal LLVM calls VectorWrapper.writeArrayElement(0, x)
// where x is still FastR object representing the vector
// this operation is visible to Java GC
SEXP benchmark(SEXP x) {
SEXP result;
PROTECT(result = Rf_allocVector(VECSXP, Rf_length(x)));
for (int i = 0; i < Rf_length(x); ++i) {
SET_VECTOR_ELT(result, i, ScalarInteger(
Rf_length(VECTOR_ELT(x, i))));
}
UNPROTECT(1);
return result;
}
a <- rep(list(1:5, rnorm(10), runif(10)), 1_000_000)
.Call(C_benchmark, a); # 3 times == one run
FastR vs GNU-R: ~0.270s vs ~0.220s
i7-8750H CPU, 6x2.20GHz, 32GB RAM