[rkward/work/faster_watch] rkward/rbackend: Make object modification detection faster (step 1).
Thomas Friedrichsmeier
null at kde.org
Sat Apr 7 19:58:30 UTC 2018
Git commit 92d979a868706ac5b17226a5a939c96559fce09e by Thomas Friedrichsmeier.
Committed on 07/04/2018 at 19:57.
Pushed by tfry into branch 'work/faster_watch'.
Make object modification detection faster (step 1).
This first step avoids get and assign calls. Results in ~30% less time taken on a simple testcase:
system.time(for (i in 1:100000) x <- i)
(with x and i being watched symbols).
TODO: Adjust code for "unwatching".
Next step will be to avoid the .Call().
CCBUG: 380580
M +5 -4 rkward/rbackend/rkrbackend.cpp
M +4 -6 rkward/rbackend/rpackages/rkward/R/internal.R
https://commits.kde.org/rkward/92d979a868706ac5b17226a5a939c96559fce09e
diff --git a/rkward/rbackend/rkrbackend.cpp b/rkward/rbackend/rkrbackend.cpp
index 548d8d1f..d09ba41a 100644
--- a/rkward/rbackend/rkrbackend.cpp
+++ b/rkward/rbackend/rkrbackend.cpp
@@ -957,13 +957,14 @@ SEXP doGetGlobalEnvStructure (SEXP name, SEXP envlevel, SEXP namespacename) {
}
/** copy a symbol without touching it (esp. not forcing any promises) */
-SEXP doCopyNoEval (SEXP name, SEXP fromenv, SEXP toenv) {
+SEXP doCopyNoEval (SEXP fromname, SEXP fromenv, SEXP toname, SEXP toenv) {
RK_TRACE (RBACKEND);
- if(!Rf_isString (name) || Rf_length (name) != 1) Rf_error ("name is not a single string");
+ if(!Rf_isString (fromname) || Rf_length (fromname) != 1) Rf_error ("fromname is not a single string");
+ if(!Rf_isString (toname) || Rf_length (toname) != 1) Rf_error ("toname is not a single string");
if(!Rf_isEnvironment (fromenv)) Rf_error ("fromenv is not an environment");
if(!Rf_isEnvironment (toenv)) Rf_error ("toenv is not an environment");
- Rf_defineVar (Rf_install (CHAR (STRING_ELT (name, 0))), Rf_findVar (Rf_install (CHAR (STRING_ELT (name, 0))), fromenv), toenv);
+ Rf_defineVar (Rf_install (CHAR (STRING_ELT (toname, 0))), Rf_findVar (Rf_install (CHAR (STRING_ELT (fromname, 0))), fromenv), toenv);
return (R_NilValue);
}
@@ -1048,7 +1049,7 @@ bool RKRBackend::startR () {
{ "rk.do.generic.request", (DL_FUNC) &doPlainGenericRequest, 2 },
{ "rk.get.structure", (DL_FUNC) &doGetStructure, 4 },
{ "rk.get.structure.global", (DL_FUNC) &doGetGlobalEnvStructure, 3 },
- { "rk.copy.no.eval", (DL_FUNC) &doCopyNoEval, 3 },
+ { "rk.copy.no.eval", (DL_FUNC) &doCopyNoEval, 4 },
{ "rk.edit.files", (DL_FUNC) &doEditFiles, 4 },
{ "rk.show.files", (DL_FUNC) &doShowFiles, 5 },
{ "rk.dialog", (DL_FUNC) &doDialog, 6 },
diff --git a/rkward/rbackend/rpackages/rkward/R/internal.R b/rkward/rbackend/rpackages/rkward/R/internal.R
index 82ce60a3..625e1d2c 100644
--- a/rkward/rbackend/rpackages/rkward/R/internal.R
+++ b/rkward/rbackend/rpackages/rkward/R/internal.R
@@ -232,22 +232,20 @@
# else, for instance, if the user names a symbol "missing", and we try to resolve it in the
# wrapper function below, evaluation would recurse to look up "missing" in the .GlobalEnv
# due to the call to "if (!missing(value))".
- get <- base::get
missing <- base::missing
- assign <- base::assign
.rk.do.call <- rkward::.rk.do.call
invisible <- base::invisible
function (value) {
if (!missing (value)) {
- assign (k, value, envir=.rk.watched.symbols)
+ x <<- value
.Call ("rk.do.command", c ("ws", k), PACKAGE="(embedding)");
# NOTE: the above is essentially the same a
# .rk.do.call ("ws", k);
# only minimally faster.
- invisible (value)
+ invisible (x)
} else {
- get (k, envir=.rk.watched.symbols)
+ x
}
}
}
@@ -255,7 +253,7 @@
#' @export
".rk.watch.symbol" <- function (k) {
f <- .rk.make.watch.f (k)
- .Call ("rk.copy.no.eval", k, globalenv(), .rk.watched.symbols, PACKAGE="(embedding)");
+ .Call ("rk.copy.no.eval", k, globalenv(), "x", environment (f), PACKAGE="(embedding)");
#assign (k, get (k, envir=globalenv ()), envir=.rk.watched.symbols)
rm (list=k, envir=globalenv ())
More information about the rkward-tracker
mailing list