[REBOL] Speeding up code
From: sunandadh::aol::com at: 13-Feb-2002 6:14
I recently tried to put some zip into some sluggish code.
I was surprised just how fast a lot of Rebol is. I instrumented several of my
suspect functions and found they were almost too fast to meter.
The slowest thing I found was (perhaps not surprisingly) Layout.
To soup up the code, I wrote an elapse timer function. It's listed below with
some samples of use. Feel free to use it.
The code is reasonably Rebollish (it uses a persistent local variable), but
I'd appreciate feedback on better ways of acheiving the same, particularly:
1. Can I avoid having to define the same refinement variable (unit-name)
twice (unit-name-start and unit-name-end)?
2. Any better suggestions for those awkward Pokes?
Thanks,
Sunanda
>>>>Sample console session:
loop 5 [
unit-timer/start "A code unit"
wait (0.001 * random 50) ;; your code here!!
unit-timer/start "Another code unit"
wait (0.02 * random 20)
print unit-timer/end "A code unit"
wait (0.1 * random 10)
print unit-timer/end "Another code unit"
print unit-timer/end "A unit with no start"
]
print mold unit-timer/report
help unit-timer
<snipped>
>>>>>The code:
rebol []
Unit-Timer: func [
{Records elapse time for named units of code
Returns:
>> False -- /End called without /Start for same unit
>> True -- /Start okay
>> decimal -- /End only: cumulative elapse time for unit
>> block -- /Report only: history block.
Known problems:
1. Doesn't check for start/end straddling midnight(s)
2. Watch out if you use this in a function -- putting
an /End call as the last thing in a function that uses an
implicit Return will send the elapse time back to your caller.
}
/Report
{Return units history block
Format is:
[string time decimal integer ...] (repeats in groups of four)
where:
>> string -- is the unit name
>> time -- is the latest start time (0 = not being timed)
>> decimal -- culmulative elapse time for unit name
>> integer -- number of times unit has been timed.
}
/Start Unit-name-start [String!]
{Start a unit.}
/End Unit-name-end [String!]
{End a unit.}
/local Units-block
Unit-data] [
Units-block: []
;; -------------------------
;; Handle /Report refinement
;; -------------------------
If Report [Return Units-block]
;; ------------------------
;; Handle /Start refinement
;; ------------------------
;;
;; For a new unit, add a history group.
;; If the unit already exists, simply
;; reset its start time. This will lose
;; some elapse time if there was an
;; outstanding /End.
if Start [
unit-data: find units-block unit-name-start
either none? unit-data [
append units-block
compose [(unit-name-start) ;; unit-name
(now/time/precise) ;; start time
0.0 ;; cumulative elapse
0 ;; invocations
]
][
poke units-block ;; (re)set start time
(1 + index? unit-data) now/time/precise
]
Return true
] ; if-start
;; ----------------------
;; Handle /End refinement
;; ----------------------
unit-data: find units-block unit-name-end
if any [none? unit-data
decimal? pick units-block (1 + index? unit-data)
] [return false] ;; End without a start
poke units-block (2 + index? unit-data)
to-decimal (unit-data/3
+ (now/time/precise - Unit-data/2))
poke units-block (3 + index? unit-data) unit-data/4 + 1
poke units-block (1 + index? unit-data) 0.0
Return unit-data/3 ;; Return cumulative elapse time for unit
] ; func