Bug 380580 - Speed up assignments in globalenv()
Summary: Speed up assignments in globalenv()
Status: REPORTED
Alias: None
Product: rkward
Classification: Applications
Component: general (show other bugs)
Version: unspecified
Platform: unspecified All
: NOR wishlist
Target Milestone: ---
Assignee: RKWard Team
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-10-09 09:03 UTC by Thomas Friedrichsmeier
Modified: 2018-04-07 19:58 UTC (History)
0 users

See Also:
Latest Commit:
Version Fixed In:


Attachments
approach and testcase (1.33 KB, text/plain)
2007-10-09 14:28 UTC, Thomas Friedrichsmeier
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Thomas Friedrichsmeier 2007-10-09 09:03:02 UTC
-- This ticket was imported from http://sourceforge.net/p/rkward/feature-requests/46 on 2017-05-31 14:48:55 +0100 --
Assignments inside globalenv\(\) are slow due to modification detection. Run this code:

\# first create an object in a single command
x <- 1

\# now assign to it many times
for \(i in 1:100000\) x <- 2

\# in contrast, try this:
local \(\{for \(i in 1:100000\) x <- 2; x <<- x\}\)

The latter is tremendously faster. In a plain R session, there is no such difference.

Probably we can improve on this by implementing .rk.watch.symbol\(\), and esp. the watch function created by .rk.make.watch.f\(\) in C, and also fine-tuning it in the process.
Comment 1 Thomas Friedrichsmeier 2007-10-09 14:28:36 UTC
approach and testcase
-- Created an attachment --
Comment 2 Thomas Friedrichsmeier 2007-10-09 14:28:36 UTC
Logged In: YES 
user\_id=300591
Originator: YES

The attached code is not quite correct \(dealing with promises\) or clean, and will need further adjustments in .rk.watch.globalenv\(\), but illustrates a first approach.

This speeds up the testcase by around factor 2.5, but is still 30-40 times slower than without watching the object \(note that this isn't really a real world testcase, though, in that it's really just assignments without any computation\). For assignments only \(not the reads\), more than half of the time is spent inside the C callback, and we can likely cut down on this considerably.

The markable difference between reads and writes \(beyond the times spent in .Call\) suggest that the "<<-" operator is still fairly expensive. If we could implement the entire assignment part in C, then we might gain even more performance. We key would be to know where to look for x, and assign there, directly.
File Added: watchtest.R
Comment 3 Thomas Friedrichsmeier 2010-06-08 13:31:54 UTC
Here's a new idea on how to approach this problem:

1\) Instead of using active bindings for all objects, use active bindings only for object which are already active bindings \(i.e. add a layer of indirection to those as before\).
2\) For all other objects, copy them to a storage environment as before, but then:
3\) After each command simply check, whether the object in globalenv\(\) is still the same as in the storage envionrment. Simply pointer comparison should be good enough\!
Comment 4 Thomas Friedrichsmeier 2018-04-07 19:58:38 UTC
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().

M  +5    -4    rkward/rbackend/rkrbackend.cpp
M  +4    -6    rkward/rbackend/rpackages/rkward/R/internal.R

https://commits.kde.org/rkward/92d979a868706ac5b17226a5a939c96559fce09e