Mailing List Archive: 49091 messages
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

[REBOL] Re: About Standards and Best Practices

From: greggirwin:mindspring at: 2-Sep-2003 9:18

Hi Reboler, R> I know that Rebol is cool!!, but what I was thinking is that any programmer R> has his view of Rebol. Some of them use a lot of objects, others use just R> function calls. By the other hand, Rebol is so handy that we can also use a R> procedural approach. But what are you missing here? the performance!! Your questions aren't dumb at all, just hard to answer. :) The problem is that, with REBOL, you can do things in so many different ways that it's hard to define "general" optimizations, as Brett said. Sometimes rethinking the solution in an entirely different way--maybe not possible in other languages--will yield a simpler and much more efficient implementation. That said, there are some obvious, and not-so-obvious rules you can follow. 1) Premature optimization is a big problem is software development. Only optimize things you *know* will make a significant difference. To find those things, you have to profile and measure. I profile things in different ways, but here's a little function I use to test isolated blocks of code. time-it: func [block /count ct /local t] [ if not count [ct: 1] t: now/time/precise loop ct [do block] now/time/precise - t ] print time-it [] 1'000'000 i: 0 print time-it [i: i + 1] 1'000'000 fn: func [/ref val][] print time-it/count [fn] 1'000'000 print time-it/count [fn/ref none] 1'000'000 print time-it/count [make object! []] 1'000'000 print time-it/count [ make object! [a: none b: "test" c: copy []] ] 1'000'000 2) Optimize algorithms before you optimize code. In REBOL, we're already working at a high level, but this can also mean using the right data structure or datatype. For example, list! values are faster than blocks if you are inserting and removing a lot of items, and hash! values are much faster than blocks if you're doing a lot of lookups (i.e. finding or selecting items). 3) Function calls take time. You will sometimes see people inline the source of the APPEND function (which is basically INSERT TAIL) to save a little time. If you have a loop that will make lots of calls, it can *sometimes* be worth eliminating function calls this way, but remember that it can also lead to more bugs and more code. 4) Path evaluation takes time. REBOL is interpreted, so sometimes it can pay to cache values that are part of a deep path (in nested blocks for example) if you're going to use them many times inside a loop. This applies to functions inside objects as well. 5) For dynamic code, build blocks rather than strings if you're going to DO them. It can be much easier, cleaner, and more efficient. 6) Use natives when you can. REBOL's natives are very fast. Rather than looping over a series yourself, looking for values, try to figure out a way to use natives like FIND and SELECT. Let REBOL do all the heavy lifting when you can. 6.1) Get to know how some mezzanines work and which functions are native. The FOR function is a good example. I see a lot of code that uses FOR with a lower bound of 1 and a step size of 1. In those cases, REPEAT is much more efficient. Loop constructs in REBOL are not all native, and certainly not all equal in how they work, so they're worth investigating. 7) If you're processing text, don't forget about PARSE (even if you think it's not applicable to your situation). R> 4) clear, reset vars.. This can make a substantial difference in some cases. If you're creating buffers to use over and over again, particularly large ones, rather than doing a "make string! 1'000'000" on every pass, do it once and then just CLEAR the string on each pass. For me, the big gains come when I can refactor a solution. Often times stripping out my own code when I find a native alternative will be all it takes. HTH! -- Gregg