mIRC Home    About    Download    Register    News    Help

Print Thread
Page 1 of 3 1 2 3
#142551 18/02/06 04:00 PM
Joined: Oct 2003
Posts: 9
S
Suntop Offline OP
Nutrimatic drinks dispenser
OP Offline
Nutrimatic drinks dispenser
S
Joined: Oct 2003
Posts: 9
How do I make the timestamp output work with milliseconds?

I was told I have to make a script to make that work,
but how should i make that work with the default timestamp output
without messing it up?

and how do i even make mirc count milliseconds?
The only thing I know of that uses milliseconds is timers,
but I cant get the timestamp to work with that...or?

Thanx in advance smile


--==> Wizard Suntop <==--
Joined: Dec 2002
Posts: 28
P
Ameglian cow
Offline
Ameglian cow
P
Joined: Dec 2002
Posts: 28
mIRC's timestamp feature uses the formatting parameters from $asctime() identifier (/help $asctime), and there are no identifiers for milliseconds. Actually, there are no identifiers that can return the current time in milliseconds.

Ping and timers can use milliseconds only because they compute the DIFFERENCE between two moments in time expressed in milliseconds - actually, in "ticks" elapsed since the computer was started. But $ticks in itself has no meaning, as it didn't have a precise reference point; only difference between two values of $ticks is useful, to accurately determine the duration of a process.

Out of curiosity, what do you need such a high precision timestamping for? How is it useful to you, considering how many other factors can influence the delay of messages appearing on your screen, like lag and even processor load that slows down refreshing mIRC windows?

Joined: Oct 2003
Posts: 9
S
Suntop Offline OP
Nutrimatic drinks dispenser
OP Offline
Nutrimatic drinks dispenser
S
Joined: Oct 2003
Posts: 9
Quote:
mIRC's timestamp feature uses the formatting parameters from $asctime() identifier (/help $asctime), and there are no identifiers for milliseconds. Actually, there are no identifiers that can return the current time in milliseconds.


I know, thats why I asked in the first place..

Quote:
Ping and timers can use milliseconds only because they compute the DIFFERENCE between two moments in time expressed in milliseconds - actually, in "ticks" elapsed since the computer was started. But $ticks in itself has no meaning, as it didn't have a precise reference point; only difference between two values of $ticks is useful, to accurately determine the duration of a process.


So how can i make a script convert this to milliseconds, and how
can I make it replace the current $timestamp value without making
the settings in options overwrite the script?
..as well as to replace the values in all windows.. confused

Quote:
Out of curiosity, what do you need such a high precision timestamping for? How is it useful to you, considering how many other factors can influence the delay of messages appearing on your screen, like lag and even processor load that slows down refreshing mIRC windows?


It's for testing perposes..
I need the exact output time in milliseconds for several tasks i'm trying to perform..
and it will make fixing some of my scripts alot easier as well..

And I'm testing this on a private network, where lag and proccessor load isnt much of
an issue wink


--==> Wizard Suntop <==--
Joined: Sep 2003
Posts: 4,230
D
Hoopy frood
Offline
Hoopy frood
D
Joined: Sep 2003
Posts: 4,230
pre mirc6.17
Code:
;usage /ctimems : well revaluate the the offset values used to produce the $identifier results (2 second delay during this processing)
;usage $ctimems : returns $ctime and 3 digit decimal place being miliseconds, (2 second delay if no /ctimems call is made prior to this $identifier being used)
alias ctimems {
  if (!$var(%milliseconds.ticks,0) || !$var(%milliseconds.ctime,0) || (!$isid)) {
    var %ctime = $calc($ctime + 1)
    while (%ctime &gt;= $ctime) { }
    set -u1000000000 %milliseconds.ticks $calc($ticks - 1000)
    set -u1000000000 %milliseconds.ctime $calc($ctime - 1)
  }
  return $left($calc(%milliseconds.ctime + (($ticks - %milliseconds.ticks) / 1000) + .0001),-1)
}


mirc 6.17 only
Code:
;usage /ctimems : well revaluate the the offset values used to produce the $identifier results (2 second delay during this processing)
;usage $ctimems : returns $ctime and 3 digit decimal place being miliseconds, (2 second delay if no /ctimems call is made prior to this $identifier being used)
alias ctimems {
  if (!$var(%milliseconds.ticks,0) || !$var(%milliseconds.ctime,0) || (!$isid)) {
    var %ctime = $calc($ctime + 1)
    while (%ctime &gt;= $ctime) { }
    set -e %milliseconds.ticks $calc($ticks - 1000)
    set -e %milliseconds.ctime $calc($ctime - 1)
  }
  return $left($calc(%milliseconds.ctime + (($ticks - %milliseconds.ticks) / 1000) + .0001),-1)
}


* this was old code i wrote some time back , yell out if its not working right.

Joined: Oct 2003
Posts: 9
S
Suntop Offline OP
Nutrimatic drinks dispenser
OP Offline
Nutrimatic drinks dispenser
S
Joined: Oct 2003
Posts: 9
Thanx, this works the way i want if i implement this:
Code:
alias tpms { return $right($ctimems,3) }


but the main issue is still: how to get this to work in every window,
as a replacement of the actual $timestamp value ..without getting the
actual timestamp value in options to overrun it.. :-/


--==> Wizard Suntop <==--
Joined: Sep 2003
Posts: 4,230
D
Hoopy frood
Offline
Hoopy frood
D
Joined: Sep 2003
Posts: 4,230
unfortunetly the optiosn timestamp value doesnt allow u to insert identifiers like $x in else i would have said rename the alias to x and insert $x, maybve this should be a feature suggestion for the future who knows.

i wacked this together for you

Code:
alias ms.timestampfmt {
  var %ctime = $calc($ctime + 1)
  while (%ctime &gt;= $ctime) { }
  set -u1000000000 %ms.timestampfmt.fix $calc($ticks % 1000)
  .timer.ms.timestampfmt.fix -imo 0 15 ms.timestampfmt.fix
}
alias ms.timestampfmt.fix {
  var %timestampfmt = $timestampfmt
  if ($pos(%timestampfmt,s.,1)) {
    var %pos = $v1
    if ($mid(%timestampfmt,$calc(%pos + 2),3) isnum) {
      .timestamp -f $+($left(%timestampfmt,%pos),.,$right($calc($ticks - %ms.timestampfmt.fix),3),$mid(%timestampfmt,$calc(%pos + 5)))
    }
  }
}


First run /MS.TIMESTAMPFMT and it well start it off, it well have that 1 to 2 second delay anytime you run it
After that you well notice no change, unless you go into the timestamp format and insert ".000" (actually fullstop and any 3 numbers), ex [HH:nn:ss] to [HH:nn:ss.123]
Next time the timestamp is displayed the 3 digits are adjusting to the ms, im actually going in and reseting the timestamp 67 or so times a second ( /me is a resource hog! )

* now becuase this is done on a timer, if you are doing your own large looping (aka mirc freeze) then the timer doesnt get a chance to go off, thus the ms value well not update, so if your got a /echo -t in your loop the ms well jam, only way to fix that is to call MS.TEMPSTAMPFMT.FIX from inside your loop. This however is not major in my opion as from what i gather your after getting accurate time stamps on channels etc.

* again if u have mirc6.17 you can replace the -u1000000000 with a -e

--- edit ---
Calling out to REGEXERS!

Actually to any good regexer out there it would be nice if you could do a regsub on it, and thus reduce my code over head replacing all my ifs etc, and it would also allow replacing of more than one s.000 value
What i think is needed is to locate in $timestampfmt any occurance of s.### (# being a digit) and replace it with $+(s.,$right($calc($ticks - %ms.timestampfmt.fix),3)), Maybe also only set the timestamp if at least one was found, since im sure its resource hoggy to keep setting it if its not changed smile
Maybe along the lines of....
Code:
alias ms.timestampfmt.fix {
  var %timestampfmt = $timestampfmt 
  if ($regsub(%timestampfmt,[color:blue]&lt;re&gt;[/color],$+(s.,$right($calc($ticks - %ms.timestampfmt.fix),3)),%timestampfmt)) { timestamp -f %timestampfmt }
}


<re> to match s.###

Last edited by DaveC; 19/02/06 12:53 AM.
Joined: Oct 2003
Posts: 9
S
Suntop Offline OP
Nutrimatic drinks dispenser
OP Offline
Nutrimatic drinks dispenser
S
Joined: Oct 2003
Posts: 9
First.. i'm using mIRC 6.16
Will upgrade to 6.17 after a while, when more people have
tested it, and possible bugfixes has been released =)


And your code dont work...the actual replacement of the timestamp.

And I was wondering..is it easier to make hundreds?
(not sure what thats called)
like for every second, 0-99 is counted..
That is enough actually for what i need it for..
And both types would be nice to have the code of...
i might not be needing both, but would be nice to learn them anyway =)


--==> Wizard Suntop <==--
Joined: Sep 2003
Posts: 4,230
D
Hoopy frood
Offline
Hoopy frood
D
Joined: Sep 2003
Posts: 4,230
Quote:
And your code dont work...the actual replacement of the timestamp.


You mean YOU cant get it to work, not it doesnt work. Becuase im using exactly that code right now.

And no hundreds would take an extra mids to get the value, and it would only be cutting the last digit off.

Regardless, rather than say "it dont work" , what part of my code are you having trouble with?

Did you start it using /ms.timestampfmt
Did the timer start (check using /timer)
Is there a s.000 in the timestamp format itself?

Joined: Oct 2003
Posts: 9
S
Suntop Offline OP
Nutrimatic drinks dispenser
OP Offline
Nutrimatic drinks dispenser
S
Joined: Oct 2003
Posts: 9
Quote:
You mean YOU cant get it to work, not it doesnt work. Becuase im using exactly that code right now.

I tested it on mirc 6.16 without any other scripts
(except for one small one that simply shows help for uno (a script game of course))

Quote:
Regardless, rather than say "it dont work" ,
what part of my code are you having trouble with?

The replacement of the actual timestamp in options.
I did exactly as you said, went to options and replaced the
current value with [HH:nn:ss.000]
(even tried .123 to see if that helped)
but the timestamp simply didnt update..
or it DID display HH:nn:ss right..but showing only: .000
(or .123) repeatedly.
..so in other words...the milliseconds didnt update AT ALL..

Quote:
Did you start it using /ms.timestampfmt
Did the timer start (check using /timer)
Is there a s.000 in the timestamp format itself?

yes to all that :-)
Everything seemed to work, but as i said, the actual update
of the milliseconds never took place, and simply echoed what i typed in options..


--==> Wizard Suntop <==--
Joined: Sep 2003
Posts: 4,230
D
Hoopy frood
Offline
Hoopy frood
D
Joined: Sep 2003
Posts: 4,230
Code:
alias ms.timestampfmt {
  var %ctime = $calc($ctime + 1)
  while (%ctime &gt;= $ctime) { }
  set -u1000000000 %ms.timestampfmt.fix $calc($ticks % 1000)
  .timer.ms.timestampfmt.fix -imo 0 15 ms.timestampfmt.fix
}
alias ms.timestampfmt.fix {
  ///echo -s Stage 1/3
  var %timestampfmt = $timestampfmt
  if ($pos(%timestampfmt,s.,1)) {
    var %pos = $v1
    ///echo -s Stage 2/3 : %pos
    if ($mid(%timestampfmt,$calc(%pos + 2),3) isnum) {
      .timestamp -f $+($left(%timestampfmt,%pos),.,$right($calc($ticks - %ms.timestampfmt.fix),3),$mid(%timestampfmt,$calc(%pos + 5)))
      ///echo -s Stage 3/3 : $timestampfmt ********************************************************************************************************************
    }
  }
}


try that then and track what it gets to stage 1 2 or 3
PS: its gonna flood the status window like hell!

Joined: Dec 2002
Posts: 29
H
Ameglian cow
Offline
Ameglian cow
H
Joined: Dec 2002
Posts: 29
alias ms.timestampfmt.fix {

var %timestampfmt = $timestampfmt

if ($regsub(%timestampfmt,<re>,$+(s.,$right($calc($ticks - %ms.timestampfmt.fix),3)),%timestampfmt)) { timestamp -f %timestampfmt }

}

Code:
\d{2}:\d{2}:\d{2}.\d{3}

this will match ##:##:##.###

but it sounds like you want
Code:
\w{2}:\w{2}:\w{2}.\d{3}

this will match !!:!!:!!.### where ! is anything a-z,A-Z,0-9

alternatively, you could have
Code:
[A-Z]:[a-z]:[a-z].\d{3}

this will only match AA:aa:aa.### where AA is upper, and aa are lower, letters only

I'm not sure what exactly you require, and there may be a better expression to use, I've never really played with regex before, but I did test these to confirm they match how I stated.

hope this helps,

HobophobE

Joined: Sep 2003
Posts: 4,230
D
Hoopy frood
Offline
Hoopy frood
D
Joined: Sep 2003
Posts: 4,230
I needed a regsub that would find s.000 through to s.999 aka s.### where # is a digit.

PS: . (dot) has a special meaning in a regsub.

Joined: Oct 2005
Posts: 1,741
G
Hoopy frood
Offline
Hoopy frood
G
Joined: Oct 2005
Posts: 1,741
To find s.000 to s.999 you would use a regex like this:

/s\.\d{3,3}/

- Literal 's'
- Literal '.'
- Exactly 3 digits (0-9)
* Case sensitive

This would NOT match s.0 or S.000 . It will match s.183 s.724 s.025 etc. anywhere in the string.

-genius_at_work

Joined: Sep 2003
Posts: 4,230
D
Hoopy frood
Offline
Hoopy frood
D
Joined: Sep 2003
Posts: 4,230
Thanks man, from that i got this....

Code:
alias ms.timestampfmt.fix {
  var %timestampfmt = $timestampfmt , %re = /s\.\d{3,3}/ 
  if ($regsub(%timestampfmt,%re,$+(s.,$right($calc($ticks - %ms.timestampfmt.fix),3)),%timestampfmt)) { .timestamp -f %timestampfmt }
}


however in a time stamp such as [HH:nn:ss.123 s.123] only the first instance of s.123 is updating.

Am I missing some switch on the regex to do all matches (that i dont know about)?

/me looks at feet shucks them around and wishes he had more time to waste learning regex, but sleeping is ment to be important as well!

Joined: Oct 2005
Posts: 1,741
G
Hoopy frood
Offline
Hoopy frood
G
Joined: Oct 2005
Posts: 1,741
To have it replace all instances, you need to use the 'g' (global) switch in the regex match:

/s\.\d{3,3}/g

BTW, if you want to learn some regex (even just the basics) you should try http://www.regular-expressions.info .

-genius_at_work

Joined: Sep 2003
Posts: 4,230
D
Hoopy frood
Offline
Hoopy frood
D
Joined: Sep 2003
Posts: 4,230
most excellent dude.

Joined: Feb 2004
Posts: 2,019
Hoopy frood
Offline
Hoopy frood
Joined: Feb 2004
Posts: 2,019
Actually, using {3,3} doesn't help at all for ensuring that there may only be 3 consecutive digits. All it ensures is that the regex engine will only match the first 3 consecutive digits, but it will not result in a failing match when there are more digits.

Observe:

//echo -a $regex(1234,/(\d{3,3})/) -> $regml(1)

echoes 1 -> 123, even though it is clear that you only wanted the regex to match in case there are only 3 consecutive digits, no more, no less. The thing is that the engine did only match 3 digits, which is shown by the regml, but it didn't make the regex match fail even with that extra 4th one.

If you want to enforce this regex to only match in case of 3 and no more, you need to use some kind of boundary check like for instance:

\d{3}(?!\d) -> makes sure that whatever comes after the 3 digits isn't a digit, but can be every other char or the end of the string.

\d{3}(?= |$) -> enforces that any sequence of 3 digits is followed by either a space or the end of the string.

...

Typing this post was a drag with one hand, as I had an accident yesterday and broke my shoulder. I need speech technology frown


Gone.
Joined: Oct 2005
Posts: 1,741
G
Hoopy frood
Offline
Hoopy frood
G
Joined: Oct 2005
Posts: 1,741
You are correct. In fact I was only trying to match the 3 digits. Other digits (if they happened to exist for some reason in this example) would remain unchanged as there is nothing for them to be replaced with.

Could this example have worked? (I'm not positive on how \b works)
/s\.\d{3,3}\b/g
Using the \b word border to make sure the digits ended at a space/end of line. Obviously that wouldn't work if someone did s.123hh:nn:ss (for whatever reason).

-genius_at_work

Joined: Sep 2003
Posts: 4,230
D
Hoopy frood
Offline
Hoopy frood
D
Joined: Sep 2003
Posts: 4,230
Well its not often i get to say Fiberoptics is mistaken, but he is, I asked for it to replace any occurance of "s.###" # being a digit. I never speciified that there can not be a digit following it.
Its a simple search and replace, no care needing to be taken with surrounding info.
The usage was in a timer to replace "s.###" with a new "s.###" that represents the current ms in the timestamp. This allowing anyone to dynamicly set there time stamp to anything they like and any occurrance of a "s" followed by ".###" would imediately add the ms. Its the userrs choice if they want to put something silly like "[HH.ss.0001234567:mm:dd]" in there.

/me waits for the envertable come back as im proven wrong frown

Last edited by DaveC; 20/02/06 06:41 PM.
Joined: Feb 2004
Posts: 2,019
Hoopy frood
Offline
Hoopy frood
Joined: Feb 2004
Posts: 2,019
Everything I stated was correct, but the mixup is that you think I was taking into account your code, while I wasn't. I only saw his regex and the explanation of the parameters, including what {3,3} does, which is the basis of my post. Note how my code examples strictly centered around showing how {N,N} really works, not necessarily a regex to apply to whatever situation you need it in. I don't even know what your code does, as I only skimmed this thread.

Many people using regex are tricked when they assume that {N,N} will mean the regex will fail to match cases where there are more than N consecutive occurences. I don't even know if g_at_work knew it already, but if he did, it still contains some good info for other people, as it's an extremely common pitfall for people relatively new at regex.


Gone.
Joined: Aug 2003
Posts: 319
P
Pan-dimensional mouse
Offline
Pan-dimensional mouse
P
Joined: Aug 2003
Posts: 319
Slightly faster initialisation (<1s rather than 2s):
Code:
alias ctimems {
  if (!$var(%ctimems.ticks,0) || !$var(%ctimems.ctime,0) || (!$isid)) {
    var %ctime = $calc($ctime + 1), %ticks
    while (%ctime > $ctime) %ticks = $ticks
    set -e %ctimems.ticks %ticks
    set -e %ctimems.ctime $ctime
  }
  return $left($calc(%ctimems.ctime + (($ticks - %ctimems.ticks) / 1000) + .0001),-1)
}


And $timestampms:
Code:
alias timestampms {
  var %tsfmt = $timestampfmt
  if (s isin %tsfmt) {
    %tsfmt = $replacex(%tsfmt,ss,ss.xxx,s,s.xxx)
    var %ct = $ctimems
    return $replacex($asctime(%ct,%tsfmt),.xxx,$right(%ct,4))
  }
  else return $timestamp
}

Last edited by Protopia; 31/08/17 07:05 PM.
Joined: Apr 2010
Posts: 969
F
Hoopy frood
Offline
Hoopy frood
F
Joined: Apr 2010
Posts: 969
1. there's a bug in that where $ctimems always returns the ctime value for when the variables were initialized

2. If speed is what you are after, you'll want something such as:
Code:
;; Builtin command & identifier calls are forced via ! and ~ respectively. Doing so bypasses script-equivalent lookups

;; same usage as $ctime, and the above $ctimems
alias ctimeex {

  ;; Use hashtables over global variables, can be quite a bit faster
  ;; No need to track $ctime
  ;; $ticks can overflow and roll back to zero, so check for overflow condition
  !if (!$~isid || !$~hget(misc,milliseconds.ticks) == $~null || $~v1 > $~ticks) {
  
    ;; create the hashtable
    !if (!$hget(misc)) hmake misc 1
    
    ;; Use inline arthmatic to avoid the overhead of calling $calc()
    !var %ctime $~ctime + 1
    
    ;; Use $v1 to store $ticks instead of a tracking variable
    !while ($~ctime < %ctime && $~ticks) { !noop }
    
    ;; store the ticks
    !hadd misc milliseconds.ticks $~v1
    
    ;; if used as command, stop processing
    !if (!$~isid) return
  }

  ;; Inline arthmatic to, yet again, avoid the overhead of $calc()
  ;; Done immediately to increase accuracy of the return value
  !var %ms $~ticks - $~hget(misc, milliseconds.ticks), %ms %ms % 1000

  ;; Return ctime with 3 digits of ticks in the decimal position; $calc is avoided
  !return $~+($~ctime, ., $~base(%m,10,10,3))
}

;; Uses the same formatting as $asctime with the addition of the following format items:
;      x: milliseconds as-is, so if the millisecond value is 95ms, x is replaced with "95"
;    xxx: milliseconds padded to 3 places so if the millisecond value is 95ms, xxx is replaced with "095"
alias timestampex {

  ;; existence & overflow check 
  !if ($~hget(misc, milliseconds.ticks) == $null || $v1 > $ticks) { ctimeex }
  
  ;; Immediately calculate the offset
  !var %ms $~ticks - $~hget(misc, milliseconds.ticks), %ms %ms % 1000

  ;; Using $replacexcs so only a single pass is made over the input AND the x/xxx replace matching is case-sensitive
  ;;   Replace xxx with the padded milliseconds
  ;;   Replace x with non-padded milliseconds value
  !return $~replacexcs($~asctime($~ctime, $~timestampfmt), xxx, $~base(%ms, 10, 10, 3), x, %ms)
}



;; initialization events
on *:LOAD:ctimems
on *:START:ctimems



Without comments, blank lines, or verbose var names:
Code:
alias ctimeex {
  !if (!$~isid || !$~hget(misc,milliseconds.ticks) == $~null || $~v1 > $~ticks) {
    !if (!$hget(misc)) hmake misc 1
    !var %c $~ctime + 1
    !while ($~ctime < %c && $~ticks) { !noop }
    !hadd misc milliseconds.ticks $~v1
    !if (!$~isid) !return
  }
  !var %m $~ticks - $~hget(misc,milliseconds.ticks),%m %m % 1000
  !return $~+($~ctime,.,$~base(%m,10,10,3))
}
alias timestampex {
  !if ($~hget(misc,milliseconds.ticks) == $~null || $~v1 > $~ticks) ctimeex
  !var %m $~ticks - $~hget(misc,milliseconds.ticks),%m %m % 1000
  !return $~replacexcs($~asctime($~ctime,$~timestampfmt),xxx,$~base(%m,10,10,3),x,%m)
}
on *:LOAD:ctimeex
on *:START:ctimeex



Note: $ticks is the best that can be done with pure mSL, but by its nature the accuracy can very substantially. I would not suggest using $ticks, or methods involving it if doing anything that requires time precision.

Last edited by FroggieDaFrog; 01/09/17 11:58 AM.

I am SReject
My Stuff
Joined: Aug 2003
Posts: 319
P
Pan-dimensional mouse
Offline
Pan-dimensional mouse
P
Joined: Aug 2003
Posts: 319
Many thanks for this optimised version.

I don't find the $ctimems bug you report.

But I found this morning that there was considerable drift between $ctime and the integer part of $ctimems. But no idea why.

If the ticks-based calculation can drift, then you cannot append the ms calc to the end of $ctime either.

That said, I really appreciate the ideas about speed. Of course the big delay is the loop waiting for $ctime to click over which can be up to a second. But the speed optimisations might be useful for the whole of the rest of my script which processes practically every message as an event - and if it takes too long it can be overwhelmed by the quantity of messages in one or several busy channels.

How much benefit is there from !command and $~identifier and use of a hash table rather than variable lookup and using several inline calculations rather than one $calc? Is this something I should be doing throughout my script?

Joined: Apr 2010
Posts: 969
F
Hoopy frood
Offline
Hoopy frood
F
Joined: Apr 2010
Posts: 969
Originally Posted By: Protopia
I don't find the $ctimems bug you report.
In your ctimems alias, you make use of the value stored in %ctimems.ctime but its only updated when the variable is first created: $left($calc(%ctimems.ctime + (($ticks - %ctimems.ticks) / 1000) + .0001),-1)



Originally Posted By: Protopia
How much benefit is there from !command and $~identifier
For a single call its VERY MINOR; as in pico-seconds faster. Across multiple calls it can trim off milliseconds or even, depending on the script, seconds to minutes in the case of long-running loops.



Originally Posted By: Protopia
and use of a hash table rather than variable lookup
This is dependent on the mIRC environment. The more variables in use the slower referencing variables becomes. By creating a hashtable with only related variables, non-related data doesn't have to be skipped over before getting to the desired value. This is a small time save(if any at all if there's no variables) but can be impactful on heavy-processing scripts if there's alot of variables in play.



Originally Posted By: Protopia
using several inline calculations rather than one $calc?
Given the context, $calc is very slow. It has to parse brackets, process the identifiers & variables fed into it, etc etc. That parsing takes a fair bit of time. Inline arithmetic is much faster but very limited: can only be done in variable-setting statements, only one math operation can be done, neither side of the operator can contain spaces.



Originally Posted By: Protopia
Is this something I should be doing throughout my script?
The short answer is no. The methodologies used above are to push processing time as low as possible; many of which come from scripting speed-challenges from back in the day. Instead I recommend coding the way that makes sense to you with the following guidelines:
  • Always use ()'s around conditions and {}'s around code-blocks for if-then-else statements, while statements, events, and alias declarations. There's some wonkiness with condition resolution that the brackets fix. Also makes your code far more readable
  • Spaces after commas. If you are passing parameters into an identifier, use a space after the comma to separate the parameters. It doesn't affect the code in any way but does make the code alot clearer.
  • Don't use pipes(|) to separate commands unless forced; instead use a new line. Again, makes your code quite a bit easier to read

Last edited by FroggieDaFrog; 01/09/17 11:46 AM.

I am SReject
My Stuff
Joined: Aug 2003
Posts: 319
P
Pan-dimensional mouse
Offline
Pan-dimensional mouse
P
Joined: Aug 2003
Posts: 319
Originally Posted By: FroggieDaFrog
Originally Posted By: Protopia
I don't find the $ctimems bug you report.
In your ctimems alias, you make use of the value stored in %ctimems.ctime but its only updated when the variable is first created: $left($calc(%ctimems.ctime + (($ticks - %ctimems.ticks) / 1000) + .0001),-1)

No - because $ticks-%ctimems.ticks makes up the difference.

Originally Posted By: FroggieDaFrog
Originally Posted By: Protopia
How much benefit is there from !command and $~identifier
For a single call its VERY MINOR; as in pico-seconds faster. Across multiple calls it can trim off milliseconds or even, depending on the script, seconds to minutes in the case of long-running loops.

I would hope that mIRC keep a record of what aliases are defined and where so it doesn't have to scan every script every time it needs to scan for a script alias. But if it does, that could be a significant amount of time, especially with large and complex scripts..

Originally Posted By: FroggieDaFrog
Originally Posted By: Protopia
and use of a hash table rather than variable lookup
This is dependent on the mIRC environment. The more variables in use the slower referencing variables becomes. By creating a hashtable with only related variables, non-related data doesn't have to be skipped over before getting to the desired value. This is a small time save(if any at all if there's no variables) but can be impactful on heavy-processing scripts if there's a lot of variables in play.

Worth doing then.

Originally Posted By: FroggieDaFrog
Originally Posted By: Protopia
using several inline calculations rather than one $calc?
Given the context, $calc is very slow. It has to parse brackets, process the identifiers & variables fed into it, etc etc. That parsing takes a fair bit of time. Inline arithmetic is much faster but very limited: can only be done in variable-setting statements, only one math operation can be done, neither side of the operator can contain spaces.

So for a very big $calc, it would be quite unreadable if split into multiple inline %x %y + %z lines. But for simple calc's (esp. those embedded in a string, it could be quite beneficial without losing readability.

Originally Posted By: FroggieDaFrog
Originally Posted By: Protopia
Is this something I should be doing throughout my script?
The short answer is no. The methodologies used above are to push processing time as low as possible; many of which come from scripting speed-challenges from back in the day. Instead I recommend coding the way that makes sense to you with the following guidelines:
  • Always use ()'s around conditions and {}'s around code-blocks for if-then-else statements, while statements, events, and alias declarations. There's some wonkiness with condition resolution that the brackets fix. Also makes your code far more readable
  • Spaces after commas. If you are passing parameters into an identifier, use a space after the comma to separate the parameters. It doesn't affect the code in any way but does make the code alot clearer.
  • Don't use pipes(|) to separate commands unless forced; instead use a new line. Again, makes your code quite a bit easier to read

I already follow most of these because I value readability. I did find a gotcha with missing brackets, so my code now has brackets everywhere. I don't currently use spaces after commas, but I will start doing this.

P.S. $ticks appear to increment in 15-16ms steps. So the first tick after ctime clicks over will be on average 8ms pas the second. Adjusting the $tick by 8 will stop you getting ms = 000 with ctime not clicked over.I will post revised code here a bit later for people to look at.

Joined: Jul 2006
Posts: 4,149
W
Hoopy frood
Offline
Hoopy frood
W
Joined: Jul 2006
Posts: 4,149
The math operation trick with /var is extremely useful and much much faster than $calc, $calc is terribly slow, if you want to speed up processing you should do that as it matters.

Prefixing command with ! and identifier with $~ has not proven to be speed up anything processing for me (tested with an A* algorithm which is quite heavy). You also don't need to prefix keyword command such as /if /elseif /else /while /break /continue /return /var as you can't override them with an alias (unsure if /goto is overridable)

Edit: maroon pointed out /return is overridable.

Last edited by Wims; 01/09/17 07:34 PM.

#mircscripting @ irc.swiftirc.net == the best mIRC help channel
Joined: Aug 2003
Posts: 319
P
Pan-dimensional mouse
Offline
Pan-dimensional mouse
P
Joined: Aug 2003
Posts: 319
A few more optimisation techniques I have used:

Use token functions to do string functions. For example, to get the extension of a file name use
Code:
$gettok(%fn,-1,$asc(.))


Try to search token lists or hash tables or custom listbox lines using wild matches like $wildtok or $fline or regex for more complex searches.

The key here is that the fewer script instructions you run to achieve your functionality the faster it runs. When you use token functions or wild-matches or regex or hash table searches to achieve your functionality you use fewer but more powerful instructions which run in compiled mIRC code rather than achieving it through many more mIRC script lines being interpreted, so it should be substantial faster.

Joined: Feb 2003
Posts: 2,812
Hoopy frood
Offline
Hoopy frood
Joined: Feb 2003
Posts: 2,812
Just ask Khaled to add support for a $ctimems or $ctimex identifier with millisecond resolution. He's already working with 100-nanosecond resolution coming back from the Windows API for SystemTimeInfo/LocalTimeInfo clock polling. It would be trivial to make this available to mSL.

You might even convince him to add milliseconds to $asctime(), and auto-detect the presence of 'ms' to treat the input ctime as millisecond ctimex.


Well. At least I won lunch.
Good philosophy, see good in bad, I like!
Joined: Apr 2010
Posts: 969
F
Hoopy frood
Offline
Hoopy frood
F
Joined: Apr 2010
Posts: 969
Fixed bugs:
Code:
alias ctimeex {
  if (!$~isid || !$~hget(misc,milliseconds.ticks) == $~null || $~v1 > $~ticks) {
    if (!$hget(misc)) hmake misc 1
    !var %c $~ctime + 1
    while ($~ctime < %c) { !noop }
    !hadd misc milliseconds.ticks $~ticks
    if (!$~isid) !return
  }
  !var %m $~ticks - $~hget(misc,milliseconds.ticks),%m %m % 1000
  !return $~+($~ctime,.,$~base(%m,10,10,3))
}
alias timestampex {
  if ($~hget(misc,milliseconds.ticks) == $~null || $~v1 > $~ticks) ctimeex
  !var %m $~ticks - $~hget(misc,milliseconds.ticks),%m %m % 1000
  !return $~replacexcs($~asctime($~ctime,$~timestampfmt),xxx,$~base(%m,10,10,3),x,%m)
}
on *:LOAD:ctimeex
on *:START:ctimeex


I'll mention again; ticks is not really viable if your want is accuracy. There's quite a bit of overhead that costs precious milliseconds using this methodology. Between the scripted calculations and mIRC's internal lookups ticks can be off by upto 100ms in some cases.


I am SReject
My Stuff
Joined: Jul 2006
Posts: 4,149
W
Hoopy frood
Offline
Hoopy frood
W
Joined: Jul 2006
Posts: 4,149
Here is an illustration of the incorrect result that can be produced by such code:

Code:
//window -h @timestamp | var %a $asctime($calc($ctime + 60),nn) | .timer -ho $asctime(HH) $+ : $+ %a 1 0 .timera -ho 1000 0 aline @timestamp $!!timestampex $!(|) if ($timer(a).reps == 0) $!({) savebuf @timestamp timestamp.txt $!(|) window -c @timestamp $!(})
Note that in this case I made the alias timestampex returning $timestamp $+ : $+ %ms for the sake of that test (my $timestampfmt is [HH:nn:ss]). This code creates a timer executing on the top of the next minute (if my timestamp is 22:50:18, it executes at 22:51) and then create a high-res timer which will execute 1000 times as fast as possible, echoing the value of $timestampex, here are the result: https://pastebin.com/MH7Vq1Nq and line 128 you can read:
Quote:
[05:34:01]:990
[05:34:01]:6
[05:34:02]:21



#mircscripting @ irc.swiftirc.net == the best mIRC help channel
Joined: Dec 2008
Posts: 1,515
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2008
Posts: 1,515
That feature has been already suggested - ignored.

https://forums.mirc.com/ubbthreads.php/ub...ds_i#Post257052


Need Online mIRC help or an mIRC Scripting Freelancer? -> https://irc.chathub.org <-
Joined: Aug 2003
Posts: 319
P
Pan-dimensional mouse
Offline
Pan-dimensional mouse
P
Joined: Aug 2003
Posts: 319
Originally Posted By: Wims
Here is an illustration of the incorrect result that can be produced by such code:

Code:
//window -h @timestamp | var %a $asctime($calc($ctime + 60),nn) | .timer -ho $asctime(HH) $+ : $+ %a 1 0 .timera -ho 1000 0 aline @timestamp $!!timestampex $!(|) if ($timer(a).reps == 0) $!({) savebuf @timestamp timestamp.txt $!(|) window -c @timestamp $!(})
Note that in this case I made the alias timestampex returning $timestamp $+ : $+ %ms for the sake of that test (my $timestampfmt is [HH:nn:ss]). This code creates a timer executing on the top of the next minute (if my timestamp is 22:50:18, it executes at 22:51) and then create a high-res timer which will execute 1000 times as fast as possible, echoing the value of $timestampex, here are the result: https://pastebin.com/MH7Vq1Nq and line 128 you can read:
Quote:
[05:34:01]:990
[05:34:01]:6
[05:34:02]:21



This is because $ticks increments in 15ms or 16ms jumps - presumably because that is the rate of the windows timer currently used. So unless there is a way of using a higher resolution timer in windows, it is less of a bug and more of a feature.

Joined: Aug 2003
Posts: 319
P
Pan-dimensional mouse
Offline
Pan-dimensional mouse
P
Joined: Aug 2003
Posts: 319
Originally Posted By: FroggieDaFrog
I'll mention again; ticks is not really viable if your want is accuracy. There's quite a bit of overhead that costs precious milliseconds using this methodology. Between the scripted calculations and mIRC's internal lookups ticks can be off by up to 100ms in some cases.

I agree - if you want real ms accuracy, then $ticks is not good enough for several reasons:
  1. If you are trying to calculate the time between mIRC events accurately, the resolution for $ticks is only 15ms or 16ms, so the interval could be as much as 32ms out.
  2. If you are wanting accuracy against an external clock, then not only do you have the above, but you also have to account for mIRC's overhead, the accuracy of the Windows clock etc.


But if all you want is a ms timestamp which gives greater accuracy that integer seconds and shows an approximate ms time, of if you want e.g. to measure 10ths of a second, then it is quite good enough.

Joined: Jul 2006
Posts: 4,149
W
Hoopy frood
Offline
Hoopy frood
W
Joined: Jul 2006
Posts: 4,149
It's more related to the fact that $ticks and $ctime are not related. You can calculate time passing with $ticks to an accuracy of $ticks's accuracy, and that would work fine. Here you are doing just that but you stick the result to $ctime without 'sync'.


#mircscripting @ irc.swiftirc.net == the best mIRC help channel
Joined: Aug 2003
Posts: 319
P
Pan-dimensional mouse
Offline
Pan-dimensional mouse
P
Joined: Aug 2003
Posts: 319
Originally Posted By: Wims
It's more related to the fact that $ticks and $ctime are not related. You can calculate time passing with $ticks to an accuracy of $ticks's accuracy, and that would work fine. Here you are doing just that but you stick the result to $ctime without 'sync'.

$ticks are not actually "timer ticks" - timer ticks are (on my system) every 15-16ms. $ticks is a ms timer which is updated by 15 or 16ms every time a timer tick occurs.

When you get $ctime clicking over, then the $tick value could be anywhere from 0 to 16ms old. So if you add (say) 8 to the tick value, then that will be more likely to be accurate. But more importantly, this also ensures you don't get $ctimems like:
  • 45678.985
  • 45678.000
  • 45679.016
but instead:
  • 45678.977
  • 45678.992
  • 45679.008
You can then save ($tick + 8) % 1000 as an offset and do $ctime + ((($tick - offset) % 1000) / 1000) to get the $ctimems.

Last edited by Protopia; 02/09/17 08:56 PM.
Joined: Jul 2006
Posts: 4,149
W
Hoopy frood
Offline
Hoopy frood
W
Joined: Jul 2006
Posts: 4,149
Quote:
$ticks are not actually "timer ticks" - timer ticks are (on my system) every 15-16ms. $ticks is a ms timer which is updated by 15 or 16ms every time a timer tick occurs.
I have no idea what you are trying to say, $ticks is based on your system timer:
Originally Posted By: https://msdn.microsoft.com/fr-fr/library/windows/desktop/ms724408(v=vs.85).aspx
The resolution of the GetTickCount function is limited to the resolution of the system timer, which is typically in the range of 10 milliseconds to 16 milliseconds.

Quote:
then that will be more likely to be accurate. But more importantly, this also ensures
So first it's more likely to be accurate, and then it ensures it will work? that's contradictory.
Getting lower chances to get a buggy display by adding 8 to $ticks does not solve the problem. Getting rid of the problem and having a timestamp correctly handling millisecond are two different things!


#mircscripting @ irc.swiftirc.net == the best mIRC help channel
Joined: Aug 2003
Posts: 319
P
Pan-dimensional mouse
Offline
Pan-dimensional mouse
P
Joined: Aug 2003
Posts: 319
Originally Posted By: Wims
Quote:
$ticks are not actually "timer ticks" - timer ticks are (on my system) every 15-16ms. $ticks is a ms timer which is updated by 15 or 16ms every time a timer tick occurs.
I have no idea what you are trying to say, $ticks is based on your system timer:
Originally Posted By: https://msdn.microsoft.com/fr-fr/library/windows/desktop/ms724408(v=vs.85).aspx
The resolution of the GetTickCount function is limited to the resolution of the system timer, which is typically in the range of 10 milliseconds to 16 milliseconds.

Exactly! We are saying the same thing even if my terminology was not great.
Originally Posted By: Wims
Quote:
then that will be more likely to be accurate. But more importantly, this also ensures
So first it's more likely to be accurate, and then it ensures it will work? that's contradictory.
Getting lower chances to get a buggy display by adding 8 to $ticks does not solve the problem. Getting rid of the problem and having a timestamp correctly handling millisecond are two different things!

By adding 8, the range of inaccuracy goes from 0-16 ms early to +/- 8ms. In other words it is correct to within 8ms instead of correct to within 16ms.

However, you may be right that adding 8 makes it less buggy rather than definitely not buggy. I will need to think about this when I am less tired. It may be that we need to use the following $ticks value as the offset which will be 10-16 greater.

Joined: Aug 2003
Posts: 319
P
Pan-dimensional mouse
Offline
Pan-dimensional mouse
P
Joined: Aug 2003
Posts: 319
I was still getting drift. So in the end I switched to a different approach to my event trace log where I store $ticks at the start of an event and then show the increment as various trace entries are made during the event handling.

Events almost always take < 1s to execute so this approach is just fine for my requirement.

Joined: May 2018
Posts: 1
B
Mostly harmless
Offline
Mostly harmless
B
Joined: May 2018
Posts: 1
i couldn't get the following script to work in mIRC 7.52 . i've set the timestamp to both [hh:nn:ss.x] and [hh:nn:ss.xxx] and neither work. am i missing something?

Originally Posted By: FroggieDaFrog
Fixed bugs:
Code:
alias ctimeex {
  if (!$~isid || !$~hget(misc,milliseconds.ticks) == $~null || $~v1 > $~ticks) {
    if (!$hget(misc)) hmake misc 1
    !var %c $~ctime + 1
    while ($~ctime < %c) { !noop }
    !hadd misc milliseconds.ticks $~ticks
    if (!$~isid) !return
  }
  !var %m $~ticks - $~hget(misc,milliseconds.ticks),%m %m % 1000
  !return $~+($~ctime,.,$~base(%m,10,10,3))
}
alias timestampex {
  if ($~hget(misc,milliseconds.ticks) == $~null || $~v1 > $~ticks) ctimeex
  !var %m $~ticks - $~hget(misc,milliseconds.ticks),%m %m % 1000
  !return $~replacexcs($~asctime($~ctime,$~timestampfmt),xxx,$~base(%m,10,10,3),x,%m)
}
on *:LOAD:ctimeex
on *:START:ctimeex


Joined: Jan 2004
Posts: 2,127
Hoopy frood
Offline
Hoopy frood
Joined: Jan 2004
Posts: 2,127
It depends on what you mean by "doesn't work."

If you mean setting your timestamp format to contain .x or .xxx and expecting the channel window to show milliseconds in your timestamp instead of x's, then no it doesn't, because that timestamp only recognizes parameters defined for $asctime.

But if you mean using $timestampex in a script then getting the string where your timestamp format is replaced by the milliseconds, then yes it does work.

If you want to use $timestampex without having .xxx showing in your [timestamp], you can change that last line of the alias to not reference $timestampfmt at all, and instead hard-code the string into the alias.

Code:
old:
!return $~replacexcs($~asctime($~ctime,$~timestampfmt),xxx,$~base(%m,10,10,3),x,%m)
new:
!return $~replacexcs($~asctime($~ctime,HH:nn:ss.xxx),xxx,$~base(%m,10,10,3),x,%m)


As an aside, when testing this just now, I see that in spite of the script attempting to identify the variance between where $ticks/1000 rolls-over differently than $ctime does, I've found that it doesn't completely eliminate the .nnn number rolling over from .99something to .00something without changing $ctime.

To prevent this completely, your hash table would instead need to hold a long-term constant that's a value that would be added to $ticks to obtain the number of ticks since 1/1/1970. The hashtable constant would be calculated something like:

old
!hadd misc milliseconds.ticks $~ticks
new
!hadd misc milliseconds.ticks $calc($~ctime * 1000 - $~ticks)

Then %m would be created like:

var %m $~hget(misc,milliseconds.ticks) + $ticks

You'd then use $left(%m,-3) as a parameter to $asctime in place of $ctime, and use $right(%m,3) in place of the xxx milliseconds. This would be zero-padded already, so wouldn't need to use $base to add the leading zeroes.

This would still have the same milliseconds error as before, occasionally showing the wrong ctime value, but it would never cycle milliseconds past 999 to 000 without displaying the higher ctime time string.

Joined: Jul 2020
Posts: 3
H
Self-satisfied door
Offline
Self-satisfied door
H
Joined: Jul 2020
Posts: 3
Originally Posted by Protopia
Slightly faster initialisation (<1s rather than 2s):
Code
alias ctimems {
  if (!$var(%ctimems.ticks,0) || !$var(%ctimems.ctime,0) || (!$isid)) {
    var %ctime = $calc($ctime + 1), %ticks
    while (%ctime > $ctime) %ticks = $ticks
    set -e %ctimems.ticks %ticks
    set -e %ctimems.ctime $ctime
  }
  return $left($calc(%ctimems.ctime + (($ticks - %ctimems.ticks) / 1000) + .0001),-1)
}


And $timestampms:
Code
alias timestampms {
  var %tsfmt = $timestampfmt
  if (s isin %tsfmt) {
    %tsfmt = $replacex(%tsfmt,ss,ss.xxx,s,s.xxx)
    var %ct = $ctimems
    return $replacex($asctime(%ct,%tsfmt),.xxx,$right(%ct,4))
  }
  else return $timestamp
}


I have been trying for a few hours to make this work but thus far no joy. (I am brand new to mIRC. I am just copying the code into the script editor under the alias heading. Should I be doing something else?

I also saw this comment in the thread "If you mean setting your timestamp format to contain .x or .xxx and expecting the channel window to show milliseconds in your timestamp instead of x's, then no it doesn't, because that timestamp only recognizes parameters defined for $asctime.

But if you mean using $timestampex in a script then getting the string where your timestamp format is replaced by the milliseconds, then yes it does work."

I sadly have no idea what the bold part means?
Any help hugely, massively appreciated. Please be gentle.

Page 1 of 3 1 2 3

Link Copied to Clipboard