mIRC Home    About    Download    Register    News    Help

Print Thread
#190494 21/11/07 04:59 PM
Joined: Mar 2007
Posts: 139
S
Solo1 Offline OP
Vogon poet
OP Offline
Vogon poet
S
Joined: Mar 2007
Posts: 139
greetings, if anyone has sometime to rewrite this little snippet it would be appreciated as it seems really slow and i feel it could be done alot better.

Code:
alias clonescan {
  if ($ial == $false) .ial on 
  var %i 1,%chan $1
  if (!$window($+(@clones,.,$network,.,%chan))) { window -Czd $+(@clones,.,$network,.,%chan) 100 50 690 460 | titlebar $+(@clones,.,$network,.,%chan) Clones list for $+($network,:) $nick(%chan,0) users currently on %chan | font $+(@clones,.,$network,.,%chan)) 12 arial bold }
  if (%chan !ischan) { aline -p $+(@clones,.,$network,.,%chan) 4ERROR no such channel $iif(%chan,as %chan) | return }
  while (%i <= $nick(%chan,0)) {
    if ($ialchan($address($nick(%chan,%i),2),%chan,0) > 1) && ($address($nick(%chan,%i),2) !isin %addr) {
      var %addr = %addr $address($nick(%chan,%i),2)
      aline -p 12 $+(@clones,.,$network,.,%chan) $timestamp $chr(42) Found ( $+ $ialchan($address($nick(%chan,%i),2),%chan,0) $+ ) Clones in $+($chr(40),%chan,$chr(41)) from ( $+ $gettok($address($nick(%chan,%i),2),2,64) $+ )
      var %cnt 1
      while (%cnt <= $ialchan($address($nick(%chan,%i),2),%chan,0)) {
        aline -p $+(@clones,.,$network,.,%chan) $timestamp $chr(42) $+(%cnt,.) $ialchan($address($nick(%chan,%i),2),%chan,%cnt).nick
        inc %cnt
      }
      aline -p $+(@clones,.,$network,.,%chan) -
    }
    inc %i
  }
  if (!%addr) { aline $+(@clones,.,$network,.,%chan) $timestamp 4,1No clones found on %chan }
}

Joined: Jul 2006
Posts: 4,149
W
Hoopy frood
Offline
Hoopy frood
W
Joined: Jul 2006
Posts: 4,149
You use a while loop to check each address on the channel, so if you have 300 nick on a channel, it's normal that it take time.

You should use the /names #channel to get each nick


#mircscripting @ irc.swiftirc.net == the best mIRC help channel
Joined: Dec 2002
Posts: 503
B
Fjord artisan
Offline
Fjord artisan
B
Joined: Dec 2002
Posts: 503
Code:
alias clonescan {
  if ($ial == $false) {
    ; note: if the IAL isn't on before this, ouch!  Nothing will be in the IAL!
    .ial on 
    return
  }
  var %i = 1, %chan = $1, %win = $+(@clones,.,$network,.,%chan), %addr
  if (!$window(%win)) {
    window -Czd %win 100 50 690 460
    titlebar %win Clones list for $+($network,:) $nick(%chan,0) users currently on %chan
    font %win 12 arial bold
  }
  if (%chan !ischan) {
    aline -p %win 4ERROR no such channel $iif(%chan,as %chan)
    return
  }
  while ($nick(%chan, %i)) {
    var %smask = $address($v1,%i)
    if ($ialchan(%smask,%chan,0) > 1) && (%smask !isin %addr) {
      %addr = %addr $address($nick(%chan,%i),2)
      aline -p 12 %win $timestamp $chr(42) Found ( $+ $ialchan(%smask,%chan,0) $+ ) Clones in $+($chr(40),%chan,$chr(41)) from ( $+ $gettok(%smask,2,64) $+ )
      var %cnt = 1
      while ($ialchan(%smask,%chan,%cnt)) {
        aline -p %win $timestamp $chr(42) $+(%cnt,.) $gettok($v1, 1, 33)
        inc %cnt
      }
      aline -p %win -
    }
    inc %i
  }
  if (!%addr) {
    aline %win $timestamp 4,1No clones found on %chan
  }
  else {
    aline %win $timestamp  4,1Scan on %chan complete!
  }

}

So, why would this be faster?

A few reasons:

Every time through the loop, you were re-evaluating the window name a minimum of 4 times. 300 people in a channel means a minimum of 1200 evaluations of that one string, which isn't changing. Slow down.

With that in mind, we do the same thing with the $address($nick(%chan,%i), 2). This is an IAL lookup to begin with, so instead of doing a few as possible lookups, you were doing double, which in a single pass would be something like 11 lookups. This cuts it in half to 3-4.

The while loops were changed as well, so that the full count isn't required for every-iteration-of-the-loop.

Anyway, my tests of the above code in a 370 user channel takes about a second on my underclocked P4.

Joined: Nov 2006
Posts: 1,559
H
Hoopy frood
Offline
Hoopy frood
H
Joined: Nov 2006
Posts: 1,559
Here's a quite similar scanner I made some time ago; for this post I did a bad translation of the output, added some comments, removed my own hotlinks, separated the colouring from the theme to variables etc - maybe it's usefull none the less...
The uper part is the scanning thingie as you'll see, the lower (messy) part is about output formatting :X

My own approach is far from being "speed optimized", but looking at yours some thougts:
- a-lining is faster if the window is hidden
- "while (%i <= $nick(%chan,0))" why not "while ($nick,%chan,%i)"? Then you could use $ifmatch / $v1 to refer to the matching nickname of that loop directly
- you are refering to "$address($nick(%chan,%i),2)" many times, you could set this to a var, do the same with the window name


Code:
; clonescan2 <#channel>
alias clonescan2 {
  var %start = $ticks, %nicks = $ialchan(*,$1,0), %nick.num = 1
  var %prefixreg = $+(/,$chr(40),[,$prefix,],$chr(41),/g), %clones, %lines, %groups
  ; • here you can modify the display colours •
  var %c1 = 07, %c2 = 11, %c3 = 10, %c4 = 14

  ; ••• cycle all nicks of that channel •••
  while ($nick($1,%nick.num)) {
    var %host = $mask($ialchan($v1,$1,1),2), %matches = $ialchan(%host,$1,0)
    ; • clones found (host has more than 1 nicks on chan) •
    if (%matches > 1) {
      ; • add the current nick to the variable of nicks for that host, inc count of total clones •
      var %clones. [ $+ [ %host ] ] $($+(%,clones.,%host),2) $nick($1,%nick.num).pnick
      inc %clones
      ; • if all clones for a host had been found •
      if ($numtok($($+(%,clones.,%host),2),32) == %matches) {
        ; • prepare the lines for the output (stored as variables) •
        var %makelines = $ceil($calc(%matches /3)), %nr = 1
        while (%nr <= %makelines) {
          inc %lines
          ; • in this messy line, the values are coloured etc •
          var %line. [ $+ [ %lines ] ] $chr(9) $iif((%nr == 1),$+ %c3 $+ $numtok($($+(%,clones.,%host),2),32)) $chr(9) $iif((%nr == 1),$gettok(%host,2,64)) $chr(9) %c3 $+ $&
            $gettok($replace($regsubex($($+(%,clones.,%host),2),%prefixreg,$+(%c1,\t,%c3)),$chr(32),$+($chr(44),$chr(32)) ),$+($calc((%nr -1) *3 +1),-,$calc(%nr *3)),32)
          inc %nr
        }
        inc %groups
        inc %lines
        var %line. [ $+ [ %lines ] ] $chr(9) %c4 $+ $str(-,163)
      }
    }
    inc %nick.num
  }
  ; ••• output •••
  ; • create window (dynamic size) •
  var %wind = $+(@,Clonescan,$chr(160),$1)
  window -hk0z -t1,4,20 %wind -1 -1 900 $round($calc(18 * $iif((%lines),%lines,0) +128),0) Arial 15
  ; • title •
  aline %wind $+($chr(9) %c3,$str(•,40) $str($chr(160),3) %c2,Clonescan %c3,at %c2,$1 %c3,$str($chr(160),3) $str(•,40))
  aline %wind $chr(9)
  ; • output "total" / "no clones" / scan time / time and date • 
  aline %wind $chr(9) $&
    $iif((%clones),$+(%c3,Total: $chr(9) $chr(91),%c2,%clones,%c3,$chr(93)),$chr(9) %c3 $+ No) Clones $+(%c3,of $chr(91),%c2,%nicks,%c3,$chr(93) Users) $iif((%clones),$+(in $chr(91),%c2,%groups,%c3,$chr(93)) $iif((%groups == 1),Group.,Groups.),found.) $&
    $chr(9) %c4 $+ (Scan time: $round($calc(($ticks - %start) /1000),2) Seconds) %c3 $+ $+([,$date(dd.mm.yyyy),$chr(44) $time,])
  aline %wind $chr(160)
  ; • output of the clones list •
  if (%clones) {
    aline %wind %c2 $+ $chr(2) $chr(9) Clones $chr(9) Host $chr(9) Nicks
    var %num = 1
    while ($($+(%,line.,$calc(%num +1)),2)) {
      aline %wind $($+(%,line.,%num),2)
      inc %num
    }
  }
  ; • end of output, show window •
  aline %wind $chr(9) %c4 $+ $str(-,163)
  window -ra %wind
}

Joined: Dec 2002
Posts: 503
B
Fjord artisan
Offline
Fjord artisan
B
Joined: Dec 2002
Posts: 503
*chuckles* same thoughts ;P

Joined: Jul 2006
Posts: 4,149
W
Hoopy frood
Offline
Hoopy frood
W
Joined: Jul 2006
Posts: 4,149
I think the best method is the /names, because you only need one while, using $*...
Here is my method, i use bekar's code :

Code:
alias clonescan {
  if ($ial == $false) {
    .ial on 
    return
  }
  var %chan = $1, %win = $+(@clones,.,$network,.,%chan)
  if (!$window(%win)) {
    window -Czd %win 100 50 690 460
    titlebar %win Clones list for $+($network,:) $nick(%chan,0) users currently on %chan
    font %win 12 arial bold
  }
  if (%chan !ischan) {
    aline -p %win 4ERROR no such channel $iif(%chan,as %chan)
    return
  } 
  set -u2 %names.win %win
  names %chan
}

raw 353:*:if (%names.win) { var %chan $3 | tokenize 32 $remove($4-,@,%,+) | haltdef | loopadd %chan $* }
raw 366:*:{
  if (%names.win) {
    haltdef
    aline %names.win $timestamp 4,1 $+ $iif(%names.addr,Scan on $2 complete!,No clones found on $2)
    unset %names.*
  }
}

alias loopadd {
  var %smask $address($2,2) ,%c $1
  if ($ialchan(%smask,%c,0) > 1) && (%smask !isin %names.addr) {
    set %names.addr %names.addr $v1
    aline -p 12 %names.win $timestamp $chr(42) Found ( $+ $ialchan(%smask,$1,0) $+ ) Clones in $+($chr(40),%c,$chr(41)) from ( $+ $gettok(%smask,2,64) $+ )
    var %cnt 1
    while ($ialchan(%smask,%c,%cnt)) {
      aline -p %names.win $timestamp $chr(42) $+(%cnt,.) $gettok($v1,1,33)
      inc %cnt
    }
    aline -p %names.win -
  }
}

On a big channel (300 person...) this method is faster than a while and not freeze mirc.


#mircscripting @ irc.swiftirc.net == the best mIRC help channel
Wims #190520 21/11/07 10:22 PM
Joined: Dec 2002
Posts: 503
B
Fjord artisan
Offline
Fjord artisan
B
Joined: Dec 2002
Posts: 503
the hell?

IRCHighway #lurk: 1358 members. 3-4 seconds..

Just how big a channel are you wanting to use it on? In any case, waiting for a REPL_NAMES makes it go 'slower'.. wink

Wims #190521 21/11/07 10:44 PM
Joined: Nov 2006
Posts: 1,559
H
Hoopy frood
Offline
Hoopy frood
H
Joined: Nov 2006
Posts: 1,559
The only advantage of "names" that I see is the de-freeze effect as you retrieve the nicks in packages, but it's not affecting the amount of processing (?)
1) loop all users (ialchan or names) and check their site for clones
2) if a site is present more than once (clones),add the nick to a group of that site
a) process the rest of the group instantly and skip this site later
or
b) process the nicks linear and add all other matches for a site to it's group
3) output the cloning nicks in groups
smile

Joined: Jul 2006
Posts: 4,149
W
Hoopy frood
Offline
Hoopy frood
W
Joined: Jul 2006
Posts: 4,149
Originally Posted By: Bekar
Just how big a channel are you wanting to use it on? In any case, waiting for a REPL_NAMES makes it go 'slower'.. ;\)
You're right, the worst is that i've already make some bench in the past and already seen that /names is slower than the loop, it's certainly the word *while* that remind me "no, it's slow!! smile "
Anyway thx for clarification.


#mircscripting @ irc.swiftirc.net == the best mIRC help channel
Joined: Mar 2007
Posts: 139
S
Solo1 Offline OP
Vogon poet
OP Offline
Vogon poet
S
Joined: Mar 2007
Posts: 139
Hi Bekar thanks for that, small problem is that at times it can pick up the same clones twice, anyway you can fix that please.

Joined: Jul 2006
Posts: 4,149
W
Hoopy frood
Offline
Hoopy frood
W
Joined: Jul 2006
Posts: 4,149
I think Bekar made some typo when he re-wrote your code.
Replace the while by this one

Code:
while ($nick(%chan, %i)) {
    var %smask = $address($v1,2)
    if ($ialchan(%smask,%chan,0) > 1) && (%smask !isin %addr) {
      %addr = %addr %smask
      aline -p 12 %win $timestamp $chr(42) Found ( $+ $ialchan(%smask,%chan,0) $+ ) Clones in $+($chr(40),%chan,$chr(41)) from ( $+ $gettok(%smask,2,64) $+ )
      var %cnt = 1
      while ($ialchan(%smask,%chan,%cnt)) {
        aline -p %win $timestamp $chr(42) $+(%cnt,.) $gettok($v1, 1, 33)
        inc %cnt
      }
      aline -p %win -
    }
    inc %i
  }




#mircscripting @ irc.swiftirc.net == the best mIRC help channel
Wims #190543 22/11/07 11:41 AM
Joined: Mar 2007
Posts: 139
S
Solo1 Offline OP
Vogon poet
OP Offline
Vogon poet
S
Joined: Mar 2007
Posts: 139
Thnaks Wims,

In really big channles i get /set: line too long (line 681, script1.mrc) because it cant set such a long variable, is there any way round this?

Joined: Jul 2006
Posts: 4,149
W
Hoopy frood
Offline
Hoopy frood
W
Joined: Jul 2006
Posts: 4,149
Yes, use hash table instead of variable :

Code:
alias clonescan {
  if ($ial == $false) {
    ; note: if the IAL isn't on before this, ouch!  Nothing will be in the IAL!
    .ial on 
    return
  }
  var %i = 1, %chan = $1, %win = $+(@clones,.,$network,.,%chan), %addr
  if (!$window(%win)) {
    window -Czd %win 100 50 690 460
    titlebar %win Clones list for $+($network,:) $nick(%chan,0) users currently on %chan
    font %win 12 arial bold
  }
  if (%chan !ischan) {
    aline -p %win 4ERROR no such channel $iif(%chan,as %chan)
    return
  }
  while ($nick(%chan, %i)) {
    var %smask = $address($v1,2)
    if ($ialchan(%smask,%chan,0) > 1) && (!$hget(addr,%smask)) {
      hadd -m addr %smask 1
      aline -p 12 %win $timestamp $chr(42) Found ( $+ $ialchan(%smask,%chan,0) $+ ) Clones in $+($chr(40),%chan,$chr(41)) from ( $+ $gettok(%smask,2,64) $+ )
      var %cnt = 1
      while ($ialchan(%smask,%chan,%cnt)) {
        aline -p %win $timestamp $chr(42) $+(%cnt,.) $gettok($v1, 1, 33)
        inc %cnt
      }
      aline -p %win -
    }
    inc %i
  }
  if (!$hget(addr)) {
    aline %win $timestamp 4,1No clones found on %chan
    
  }
  else {
    aline %win $timestamp  4,1Scan on %chan complete!
    hfree addr
  }
}


Edit : correct a mistake.

Last edited by Wims; 22/11/07 12:06 PM.

#mircscripting @ irc.swiftirc.net == the best mIRC help channel
Wims #190546 22/11/07 01:34 PM
Joined: Feb 2003
Posts: 3,432
S
Hoopy frood
Offline
Hoopy frood
S
Joined: Feb 2003
Posts: 3,432
I noticed the code in here, and i tested it, working just fine, but i never seen a window using %win = $+(@clones,.,$network,.,%chan), %addr to be created, and i was fooling around a bit with the code, and i was wondering, any way to add a @menu to a window created that way? i tested to save $+(@clones,.,$network,.,%chan), %addr to a %var, then use menu %var .. and no luck, the %var is saved the same way the window is created, how come the menu dosent work for it?


if ($me != tired) { return } | else { echo -a Get a pot of coffee now $+($me,.) }
Joined: Nov 2006
Posts: 1,559
H
Hoopy frood
Offline
Hoopy frood
H
Joined: Nov 2006
Posts: 1,559
You can use wildcards and parse the window name smile
//window $+(@clones.,$network,.,$chan(1))
Code:
menu @clones.* {
  $iif(($gettok($active,2,46)  == $network),stuff with chan $gettok($active,3-,46)) : echo $active works
}


EDIT
In addition, if it's no list window ($sline), you could use a hotlink event to store the right-clicked line ("if ($mouse.key && 16) ... stuff with $hotline") temporarily (e.g. to a hash that will be destroyed if the @window is closed),and use this data in the menu definition. (Quite a hack, but it works well for me)

Last edited by Horstl; 22/11/07 02:15 PM.
Joined: Feb 2003
Posts: 3,432
S
Hoopy frood
Offline
Hoopy frood
S
Joined: Feb 2003
Posts: 3,432
ty, got it to work.. smile


if ($me != tired) { return } | else { echo -a Get a pot of coffee now $+($me,.) }

Link Copied to Clipboard