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

help with function utilising "extended life-time" words ..

 [1/7] from: petr:krenzelok:trz:cz at: 1-Oct-2003 18:44


Hello, I am currently working with some databases and I do some steps in my script, which I measure currently for its duration time. I use something like: start: now/time/precise .... do something ... print now/time/precise - start start: now/time/precise I wanted to write myself short logger function, which will save me from repeating above sequences, as the script becomes a bit messy then. So I wanted to have following interface:
>> how-long? "Some task ..."
Total: 0:1:32 This: 0:0:1 Some task .... - Simply put - requested function should not require sending any time information, only a text message ... - it should start counter when first called - it should be possible to reset counter with /reset refinement ... I looked at some past threads and tried Joel's solution: foo: func [arg [string!] /reset /report /local ncalls][ ncalls: [0] if reset [return ncalls/1: 0] if report [return ncalls/1] ncalls/1: ncalls/1 + 1 rejoin ["call # " ncalls/1 " with " arg] ] ... but when I define something like "timer: reduce [now/time/precise 0]", it seems to me, that 'reduce causes reinitialisation of block values with each function call, while I would like to store "first run" time value somewhere to be able to count total task run time ... Anyone? Thank you very much, -pekr-

 [2/7] from: ingo:2b1 at: 1-Oct-2003 19:09


Hi Pekr, Petr Krenzelok wrote:
> Hello,
<...>
> start: now/time/precise .... do something ... print now/time/precise - > start start: now/time/precise > > I wanted to write myself short logger function, which will save me from > repeating above sequences, as the script becomes a bit messy then. So I > wanted to have following interface:
<...> Maybe this script will help a little, I normally use only profiler/test [a short snip I want to test] 10000 but it "should" be possible to set different profiler marks in your script, and test them later, but that's not tested. I hope that helps, Ingo -- Attached file included as plaintext by Ecartis -- -- File: profiler.r REBOL [ Title: "Rebol Profiler" Author: "Ingo Hohmann" ] profiler: context [ markers: [] mark: func [ "adds a profiler mark" marker [word!] ] [ insert tail markers reduce [ marker now/time/precise ] ] show: func [ "shows time since setting a profiler mark" marker [word!] /local t walk ret-val last-val tmp-val ] [ ret: copy [] t: now/time/precise if walk: find markers marker [ walk: next walk last-val: first walk while [walk: find walk marker] [ walk: next walk append ret (first walk) - last-val last-val: first walk ] ] ret ] test: func [ {tests a block for speed *!* clears the markers block *!*} block [block!] times [integer!] ] [ block: copy/deep block clear mark 't loop times [do block] mark 't show 't ] clear: func [ "Clears all markers" /only marker [word!] /local walk ] [ either only [ walk: find markers marker until [ remove/part walk 2 not found? find walk marker ] ] [ system/words/clear markers ] ] next-marker: 1 _func: function! ; ; ToDo: ; create a list of marks, find a way to name the functions ; profiling-func: func [ {Adds profiling data to a normal function} [catch] spec [block!] {Help string (opt) followed by arg words (and opt type and string)} body [block!] "The body block of the function" /local pre post ][ pre: copy [catch/name ] post: copy ['profiling-return] insert body compose [profiler/mark (to-word join 'm next-marker)] next-marker: next-marker + 1 insert tail insert/only tail pre body post probe pre ] install: func [ {Installs a profiling 'func every new func after this will create a profiling function} ][ _func: :func func: :profiling-func ] ]

 [3/7] from: maximo:meteorstudios at: 1-Oct-2003 14:02


> -----Original Message----- > From: Petr Krenzelok [] > > start: now/time/precise .... do something ... print > now/time/precise - > start start: now/time/precise
try this: it expects a block of code and even returns the value from it (and returns none for no value functions like print)... but it can easily be tweaked to work differently? ;----------------------------------------------------- rebol [] how-long?: function [codeblk [block! none!] /reset /quiet /log log-message log-string ][rval timestart timeend timelen][ if ((reset = true) OR (not value? 'how-long-accumulator)) [ how-long-accumulator: 0:00 ] if codeblk [ timestart: now/time/precise if (error? try [rval: do codeblk ]) [rval: none] timeend: now/time/precise timelen: (timeend - timestart) how-long-accumulator: how-long-accumulator + timelen if not quiet [ print ["performed in: " timelen ] print ["accumulated: " how-long-accumulator ] ] if log [ append log-string log-message append log-string rejoin [" > time: " timelen " accumulated: " how-long-accumulator "^/"] ] ] return rval ] log-string: copy "" how-long?/log [loop 1000000 [34.0 / 2.556] ] "test-block-A() " log-string how-long?/log [loop 1000000 [34.0 / 2.556] ] "test-block-B() " log-string how-long?/log [loop 1000000 [34.0 / 2.556] ] "test-block-C() " log-string how-long?/log [loop 1000000 [34.0 / 2.556] ] "test-block-D() " log-string print log-string

 [4/7] from: joel:neely:fedex at: 1-Oct-2003 13:44


Hi, Petr, Here are a couple of simple approaches (which you can complicate as desired for more functionality ;-) -jn- Petr Krenzelok wrote:
> start: now/time/precise .... do something ... print now/time/precise - > start start: now/time/precise > > I wanted to write myself short logger function, which will save me from > repeating above sequences, as the script becomes a bit messy then. So I > wanted to have following interface: > > >> how-long? "Some task ..." >
Single-task timing doesn't require any tricky state: how-long?: func [msg [string!] to-do [block!] /local timing] [ timing: now/time/precise do to-do timing: to-decimal now/time/precise - timing print [timing msg] ] Which behaves as in the following transcript: (begin transcript)
>> how-long? "count to one million" [for i 1 1000000 1 []]
3.195 count to one million
>> how-long? "count to one hundred thousand ten times" [
[ loop 10 [ [ how-long? "count to one hundred thousand" [for i 1 100000 1[]] [ ] [ ] 0.33 count to one hundred thousand 0.321 count to one hundred thousand 0.31 count to one hundred thousand 0.321 count to one hundred thousand 0.31 count to one hundred thousand 0.321 count to one hundred thousand 0.32 count to one hundred thousand 0.321 count to one hundred thousand 0.31 count to one hundred thousand 0.32 count to one hundred thousand 3.184 count to one hundred thousand ten times
>>
(end transcript) If you want accumulation of times across multiple calls, just wrap the total in a block (per the tricky approach you quoted) or do The Right Thing and represent stateful timing accumulators with objects: time-accumulator: make object! [ message: "no message?" total: 0.0 reset: func [][total: 0.0] time-this: func [to-do [block!] /local timing] [ timing: now/time/precise do to-do timing: to-decimal now/time/precise - timing total: total + timing print ["Total:" total "This:" timing message] ] ] which can be used as follows:
>> stopwatch1: make time-accumulator [message: "Watch 1"] >> stopwatch1/time-this [for i 1 1000000 1 []]
Total: 3.155 This: 3.155 Watch 1
>> stopwatch2: make time-accumulator [message: "smaller chunks"] >> loop 10 [stopwatch2/time-this [for i 1 100000 1 []]]
Total: 0.32 This: 0.32 smaller chunks Total: 0.631 This: 0.311 smaller chunks Total: 0.941 This: 0.31 smaller chunks Total: 1.262 This: 0.321 smaller chunks Total: 1.582 This: 0.32 smaller chunks Total: 1.893 This: 0.311 smaller chunks Total: 2.203 This: 0.31 smaller chunks Total: 2.514 This: 0.311 smaller chunks Total: 2.834 This: 0.32 smaller chunks Total: 3.144 This: 0.31 smaller chunks
>>
I prefer to represent stateful entities via objects rather than functions. Among other reasons, stateful functions depend on aspects of REBOL (persistence of mutations to "literal" series values) that are very mysterious to REBOL newbies. There's no point in being obscure, just for the sake of obscurity! ;-) -jn- -- ---------------------------------------------------------------------- Joel Neely joelDOTneelyATfedexDOTcom 901-263-4446 Counting lines of code is to software development as counting bricks is to urban development.

 [5/7] from: petr::krenzelok::trz::cz at: 1-Oct-2003 21:42


Thanks all for answers! I was just thinking in a bit different way - I did not want to enclose measured task into special block to prevent myself from forgetting to include ending bracket :-) So, my initial intention was to have how-long? just marking current time substracted from last function call ... From the various aproaches I saw I like object based the most probably ... do not why though :-) Cheers, -pekr-

 [6/7] from: maximo:meteorstudios at: 1-Oct-2003 15:54


man, just swap the variable names and our example are almost identical... ;-) I didn't use an object, just because I tought he really just wanted a function... it uses one global word for accumulated do times... it also safely returns a value, which can be cool if you also wish to test the validity of returned data in addition to speed gains. for example, you could more easily trap floating point problems... when testing different floating point tricks, cause you can then compare the value... -MAx --- You can either be part of the problem or part of the solution, but in the end, being part of the problem is much more fun.

 [7/7] from: joel:neely:fedex at: 2-Oct-2003 7:04


Hi, Petr, Petr Krenzelok wrote:
> Thanks all for answers! I was just thinking in a bit different way - I > did not want to enclose measured task into special block to prevent > myself from forgetting to include ending bracket :-) >
However, the presence of explicit brackets makes it clear precisely what you mean when inserting or removing a call to the timer. Without that hint, presence/absence of a call could affect the results of other calls in hard-to-track-down ways.
> So, my initial intention was to have how-long? just marking current time > substracted from last function call ... From the various aproaches I saw > I like object based the most probably ... do not why though :-) >
I prefer to use objects to manage persistent state precisely because that is what objects were intended for in the first place. The amount of state can scale up gracefully as one's design evolves (e.g. add one more attribute to the object) without requiring lots of tricky digital plumbing (e.g. the REDUCE... issue at the beginning of this thread). Just MHO, of course! ;-) -jn-