Stunt Performance Enhamcement (and New Features)

5 views
Skip to first unread message

Todd Sundsted

unread,
Feb 8, 2012, 3:16:08 PM2/8/12
to MOO Talk
The `stunt' branch on GitHub (https://github.com/toddsundsted/stunt)
contains a list/map performance enhancement based on Josh Benner's
feedback late last year.

If you are using nested lists (or maps), the latest code will
dramatically improve indexed assignment (code like `foo[x][y][x] =
"blah"'). In my specific case (package import in the Stunt core), it
knocked off ~20% of the overall time required to import a large
package (LambdaCore, for example). Given the numbers below, some
applications will see far greater improvement.

Bottom line, the LambdaMOO VM is very conservative, and copies data
more than necessary to ensure values are immutable. Specifically,
when using indexed assignment of a variable holding a collection (list
or map) value, the VM copies data instead of modifying the data in
place, even when the VM is the only thing holding on to the
collection.

Commit c97ac2807caf869f67d5ee1dd234e3f09c6f05f2 fixes this. The
commit is specific to the Stunt server, but could be easily ported to
the stock LambdaMOO server (minus a few lines specific to the map
datatype).

The performance improvement is significant:

Here is a small insert test running on the Stunt server before the fix
(BYTECODE_REDUCE_REF is enabled). The list case is faster than the
map case because list insertion is faster than map insertion, however
when you crank up the number of inserts you will see the performance
delta on lists, as well.

Feb 8 14:22:45: > map tests
Feb 8 14:22:45: > map: initializing map: m = []
Feb 8 14:22:45: > map: running test: m[i] = i
Feb 8 14:22:45: > map: 10000 inserts took 0 sec.
Feb 8 14:22:45: > map: initializing map: m = [1 -> []]
Feb 8 14:22:45: > map: running test: m[1][i] = i
Feb 8 14:23:41: > map: 10000 inserts took 56 sec.
Feb 8 14:23:41: > list tests
Feb 8 14:23:41: > list: initializing list: l = {@l, 0}
Feb 8 14:23:41: > list: running test: l[i] = i
Feb 8 14:23:41: > list: 10000 inserts took 0 sec.
Feb 8 14:23:41: > list: initializing list: l[1] = {@l[1], 0}
Feb 8 14:23:42: > list: running test: l[1][i] = i
Feb 8 14:23:43: > list: 10000 inserts took 1 sec.
Feb 8 14:23:43: > (done)

Enabling BYTECODE_REDUCE_REF speeds up the "m[i] = i" case all by
itself (without this option, the first test in a set is as slow as the
second run). Focus on the nested collection case ("m[1][i] = i").
When faced with nested collections, the LambdaMOO VM performs copies
even when those copies are not strictly necessary (in order to ensure
that values are immutable).

Here's the trace after the fix (for 100 times as many inserts).

Feb 8 14:32:43: > map tests
Feb 8 14:32:43: > map: initializing map: m = []
Feb 8 14:32:43: > map: running test: m[i] = i
Feb 8 14:32:47: > map: 1000000 inserts took 4 sec.
Feb 8 14:32:47: > map: initializing map: m = [1 -> []]
Feb 8 14:32:47: > map: running test: m[1][i] = i
Feb 8 14:32:51: > map: 1000000 inserts took 4 sec.
Feb 8 14:32:51: > list tests
Feb 8 14:32:51: > list: initializing list: l = {@l, 0}
Feb 8 14:32:51: > list: running test: l[i] = i
Feb 8 14:32:51: > list: 1000000 inserts took 0 sec.
Feb 8 14:32:51: > list: initializing list: l[1] = {@l[1], 0}
Feb 8 14:32:51: > list: running test: l[1][i] = i
Feb 8 14:32:51: > list: 1000000 inserts took 0 sec.
Feb 8 14:32:51: > (done)

The latest code also includes a few enhancements to index and range
access.

* Added `^' as an alias for the first element in a sequence (to go
along with `$').
* Added `^' and `$' support to the map datatype (previously these
only worked for lists).
* Added support for range operations on maps.
* Added new syntax to the `for' loop.

The `for' loop now sports the following syntax:

`for v, i in (...)'

When used like this, the first variable is assigned the value from the
collection and the second variable is assigned the index (the position
in the case of lists) or key (in the case of maps).

This change makes iterating over a map more performant. Iteration no
longer requires a lengthly call to get the keys in a map before
actually performing the iteration.

m = [… map … ];
for v, k in (m)
...
endfor

Todd

michael munson

unread,
Feb 8, 2012, 5:05:23 PM2/8/12
to MOO Talk
This looks great, Todd.

michael


Todd

--
You received this message because you are subscribed to the Google Groups "MOO Talk" group.
To post to this group, send email to MOO-...@googlegroups.com.
To unsubscribe from this group, send email to MOO-talk+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/MOO-talk?hl=en.


michael munson

unread,
Feb 8, 2012, 5:12:25 PM2/8/12
to Todd Sundsted, MOO Talk
I might be one of the few people active in MOO who still likes WAIFs but if you could ever make a WAIF subbranch for stunt I would love you.

I have used your stunt map primitive overloading (making a :* verb on the $map_proto delegate) to make a sort a frob, but in some situations the fact that WAIFs are referenced is much better for certain situations where you want a light object -- using the map datatype as a frob involves a lot of copying.

michael

On Wed, Feb 8, 2012 at 1:16 PM, Todd Sundsted <todd.s...@gmail.com> wrote:

Todd

Todd Sundsted

unread,
Feb 8, 2012, 5:47:54 PM2/8/12
to MOO Talk
Thanks for the positive feedback!

Yeah, frobs are not a perfect replacement for waifs. For me the lack
of permissions checking and encapsulation are the biggest problems.
Frobs are really a stop-gap until I get to a lightweight-object
replacement. Unfortunately, it won't be waifs, but I have thought
long and hard about some sort of migration path if there was enough
interest.

I hate to publish my plans for fear of not delivering on them, but
here's my current roadmap, for comments and feedback:

1) Lambdas (blocks, anonymous functions, etc.). It's ironic that
LambdaMOO does not sport lambdas. I have to fix that.
2) Lightweight-objects (reference counted, object numberless,
lightweight).
3) Modern persistent object database.

Somewhere in there is a re-vamp of the MOO language itself, although
this will happen as an in-MOO translation layer at first. My current
core already has the language-to-language machinery in place, I just
have to start working on the language itself.

Todd



On Feb 8, 5:12 pm, michael munson <michael.d.mun...@gmail.com> wrote:
> I might be one of the few people active in MOO who still likes WAIFs but if
> you could ever make a WAIF subbranch for stunt I would love you.
>
> I have used your stunt map primitive overloading (making a :* verb on the
> $map_proto delegate) to make a sort a frob, but in some situations the fact
> that WAIFs are referenced is much better for certain situations where you
> want a light object -- using the map datatype as a frob involves a lot of
> copying.
>
> michael
>
Reply all
Reply to author
Forward
0 new messages