[REBOL] Re: Speeding up code
From: joel:neely:fedex at: 13-Feb-2002 7:36
Hi, Sunanda,
[SunandaDH--aol--com] wrote:
> 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?
>
I'd refactor the code to separate the behavior of an individual
watch (as an object with its own state) from the behavior of
the total collection of watches in existence at a given time
(given a just-for-fun name ;-). Watches know how to start, stop,
and report their total times (in seconds), while the watchmaker
knows how to make a new watch, find a watch by the label placed
on it when he made it, and get reports from all of the watches.
The code below is fairly minimal, but I think it addresses most
of the capabilities you had in UNIT-TIMER (or could be extended
easily to include any I missed in a quick read-through).
It performs as follows...
The watchmaker can create new watches on demand, and a reference
to a watch *can* be kept to allow it to be used individually:
>> a: watchmaker/new "frushlinger"
>> a/start
== 7:18:24.53
>> b: watchmaker/new "schlocken"
>> b/start
== 7:18:38.37
>> c: watchmaker/new "fleegle"
>> c/start
== 7:18:58.09
The watchmaker can provide a consolidated report (each watch can
return total elapsed time whether running or not):
>> watchmaker/report-all
== ["frushlinger" 46.03 "schlocken" 32.19 "fleegle" 12.47]
>> watchmaker/report-all
== ["frushlinger" 47.95 "schlocken" 34.11 "fleegle" 14.39]
>> watchmaker/report-all
== ["frushlinger" 49.43 "schlocken" 35.59 "fleegle" 15.87]
Watches can be individually operated:
>> b/stop
== 46.25
>> watchmaker/report-all
== ["frushlinger" 61.9 "schlocken" 46.25 "fleegle" 28.34]
>> watchmaker/report-all
== ["frushlinger" 63.16 "schlocken" 46.25 "fleegle" 29.6]
The watchmaker manages the entire collection, so it's not
necessary for watch references to be kept around when not
needed -- the watchmaker can find the watch (by label) for
later operation:
>> a: b: c: none
== none
>> x: watchmaker/fetch "fleegle"
>> x/stop
== 85.96
>> watchmaker/report-all
== ["frushlinger" 125.78 "schlocken" 46.25 "fleegle" 85.96]
>> y: watchmaker/fetch "frushlinger"
>> y/stop
== 140.99
The default REPORT-ALL just returns label/time pairs in the
order the watches were created. However, the watchmaker can
provide the timings in other potentially-useful orders:
>> watchmaker/report-all
== ["frushlinger" 140.99 "schlocken" 46.25 "fleegle" 85.96]
>> watchmaker/report-all/by-label
== ["fleegle" 85.96 "frushlinger" 140.99 "schlocken" 46.25]
>> watchmaker/report-all/by-time
== ["schlocken" 46.25 "fleegle" 85.96 "frushlinger" 140.99]
Of course, the result could be processed by something like
foreach [lab tot] watchmaker/report-all [ ... ]
for whatever purpose...
After all that blabbing, here's the code:
8<------------------------------------------------------------
watchmaker: make object! [
collection: []
watch: make object! [
label: ""
total: began: ended: 0
reset: func [] [total: began: 0]
start: func [] [began: now/time/precise]
to-seconds: func [t [time!]] [
t/hour * 60 + t/minute * 60 + t/second
]
stop: func [/local ended] [
ended: now/time/precise - began
if time? began [
began: 0
total: total + to-seconds ended
]
]
report: func [] [
if time? began [stop start]
reduce [label total]
]
]
reset: func [] [collection: copy []]
new: func [lbl [string!]] [
last back insert tail collection make watch [label: lbl]
]
fetch: func [lbl [string!]] [
foreach this-watch collection [
if lbl = this-watch/label [return this-watch]
]
none
]
report-all: func [/by-label /by-time /local rpt] [
rpt: make block! length? collection
foreach this-watch collection [
insert tail rpt this-watch/report
]
if by-label [sort/skip rpt 2]
if by-time [sort/skip/compare rpt 2 2]
rpt
]
]
8<------------------------------------------------------------
HTH!
-jn-
--
; sub REBOL {}; sub head ($) {@_[0]}
REBOL []
# despam: func [e] [replace replace/all e ":" "." "#" "@"]
; sub despam {my ($e) = @_; $e =~ tr/:#/.@/; return "\n$e"}
print head reverse despam "moc:xedef#yleen:leoj" ;