One of the changes in R3 is that some of the more frequently used mezzanines are becoming native.
The append function is an example.
If I time the loop:
a: make string! 10000
loop 1000 [
loop 10000 [append a "x"]
It takes 15.3 seconds in R2, and 2.9 seconds in R3. So, about 500 percent faster in R3.
Here's the autodoc for the new append:
APPEND series value /part length /only /dup count
Inserts a value at tail of series and returns the series at head. (Modifies)
APPEND is an action value.
series -- Series at point to insert (Type: series! gob! port! object! bitset! typeset!)
value -- The value to insert (Type: any-type!)
/part -- Limits to a given length or position
length -- (Type: number! series! port! pair!)
/only -- Inserts a series as a series
/dup -- Duplicates the insert a specified number of times
count -- (Type: number! pair!)
I didn't notice the "(Modifies)" part of help before. Is that new?
Carl Sassenrath 16-Mar-2007 14:04:25
In R3 it has been added to all "modifying" functions (as opposed to "copying" or "constructive" functions) to help users notice such side effects.
Robert 16-Mar-2007 14:40:22
Carl, that "modifies" thing a VERY good!! Implicit side effects are hell if you forget about them.
Oldes 17-Mar-2007 6:41:25
Don't know about something else at this moment. The append issue was the most visible. Anyway it looks nice as the R3 version is 2x faster than using "insert tail" in R2 :-) What interests me is, how the append works with the new gob! datatype.
-pekr- 17-Mar-2007 6:48:28
Oldes, how do you know ho much faster the R3 append is in comparison to its R2 equivalent? Do you have R3 already? And - what do you mean by 'append in relation to gfx objects? :-)
-pekr- 17-Mar-2007 6:50:42
Oldes, sorry, I missed Carl's blog notice about the speed. I thought that in latest R2s we have already append being native, but it does not seem so ...
Oldes 17-Mar-2007 12:35:44
Carl is not the only one who can time code evaluation:-) if he says that append costs 15.3s and I have 16s, I can count with insert tail, which I have about 6s fast => R3 append seems to be now 2x faster than insert tail in R2:-)
Oldes 17-Mar-2007 12:39:10
And with the gxf objects - I don't know, but I see the gob! datatype as an argument for appending values. I Hope that Carl will explain it soon:-) And no, I don't have R3 yet:(
Brian Tiffin 17-Mar-2007 14:27:02
Inside tight loops, I use these quite a bit
join, rejoin, reform, remold
for, forall, forskip
size?, dir?, exists? (a lot), suffix?, split-path
switch (already done? except for us stubborn linux users)
There are probably a few others, but not many.
And from reading Ashley's performance docs with RebGUI, I rarely use to-type words now, and use to type! instead.
Jerry 18-Mar-2007 11:30:56
In the autodoc for the new append,
APPEND is an action value.
APPEND is a native value.
Brian Hawley 18-Mar-2007 16:14
Jerry, action values are native code, just invoked through type-specific indirection. APPEND would likely be an action value because its implementation would be different for each type you are appending to.
Brian Hawley 18-Mar-2007 22:44:19
It's hard for me to look through my code and see which mezzanines I need most to be made native. In most of my existing code I've already optimized away many calls to mezzanines in time-critical areas for just that reason. I can't necessarily guess which of the mezzanines I would have used there if they were native. At the least, I do notice that I avoid mezzanine loop functions, particularly FOR. I would probably use EXTRACT and REPLACE more if they were native too - I use REMOVE-EACH for that reason.
As for the others, here's a few guidelines that I would suggest:
There are a lot of basic mezzanines that are just wrappers around INSERT and such that use REDUCE or COMPOSE to create intermediate values. If the generated block is going to be put into another block it is excess allocation. You could speed up REBOL greatly and cut down on memory usage by having some of these functions be native so that they can just put their data directly into the final return value. Some examples of this are the joins and all of the non-native RE* functions.
There are some helper functions that are used internally by a lot of mezzanine code. If some of these functions were replaced by natives it would speed up all of the code that calls them. Some examples of this are ATTEMPT, FOUND? and THROW-ON-ERROR.
There are some functions that would be used more often by mezzanine and user code if they were native, but aren't yet because they aren't. Previous examples of this are SWITCH and CASE (thanks!). I'm sure there are other functions waiting to be used as well - the recent INCREMENT/DECREMENT discussion comes to mind as an example. Functions that people would expect to be low-level would be good candidates, as would type and binary conversion functions.
There are many mezzanine functions that are simple, efficient wrappers around a few other functions. If you make these internal functions more efficient, all of the wrappers can stay the way they are with minimal optimization as long as they don't generate too many temporary values. The worst example of this that I can think of is INFO?, the function underlying SIZE?, DIR? and such. INFO? just seems to be there to fix the results of QUERY to be more useful; why not make it native, or just change QUERY to return the results you need directly?
Some functions are clearly intended to be used inside tight loops, such as graphics code. Those seem like obvious candidates for natives, or perhaps rebcode operations. The pair functions Brian Tiffin mentioned would be good examples of this.
For that matter, take a look at the loops themselves. Most of them are pretty fast but any extra overhead adds up quick. The worst offender is FOR, of course. The overhead of FOR is part of the reason that I was so interested in that sequences proposal - a native FOR would handle the main reason for the numeric sequence type. I've noticed that slow loops are the source of most of the requests for rebcode.
I'm sure that there are other good guidelines that I missed. The good news about all this is that many of these changes can be made to the 2.7 series of REBOL without requiring major changes to the runtime, letting us benefit right away!
Jerry 19-Mar-2007 7:02:45
Since there is no difference between action! and native! for REBOL programmers, why not just keep action! an internal type, like symbol!, and keep it out of REBOL programmers' knowledge. They don't need to know what they don't need to know.
Anton Rolls 22-Mar-2007 0:21:20
+1 to both Brians above.
Regarding INFO?, see also:
Oldes 27-Mar-2007 11:41:51
ok... I have one as well: round
Oldes 27-Mar-2007 12:10:55
hmm... I take my wish back... I rather want faster rates as it's more important to make nice tweening animations than rounding.