LPMuds.net
February 09, 2010, 12:19:26 PM *
Welcome, Guest. Please login or register.

Login with username, password and session length
News: This is the forum page. For the main LPMuds page, visit http://lpmuds.net
 
   Home   SITE FAQ INTERMUD DOWNLOADS LINKS Help Search Login Register  
Pages: 1 [2]   Go Down
  Print  
Author Topic: efficiency of functions  (Read 2340 times)
chaos
BFF
***
Offline Offline

Posts: 212


Job, school, social life, sleep. Pick 2.5.


View Profile WWW
« Reply #15 on: September 09, 2008, 10:43:12 AM »

Want something done right, do it yourself...
Code:
> eval object array inside; for(int ix = 0; ix < 1000; ix++) { inside = ({}); foreach(object who : users()) { object who_env = environment(who); if(who_env && who_env->query_terrain(Terrain_Building)) inside += ({ who }); } } return inside;
[ Result    : ] [Array] 6:
                  [Object] /usr/takoror (/usr/atman/grundy) (Takoror)
                  [Object] /usr/protax (/usr/atman/jensendied) (Protax)
                  [Object] /usr/clericon (/usr/atman/deomer) (Clericon)
                  [Object] /usr/morgana (/usr/atman/oboklob) (Morgana)
                  [Object] /usr/grumpy (/usr/atman/chadnoe) (Grumpy)
                  [Object] /usr/dyne (/usr/atman/cyrus) (Dyne)
[ Eval Cost : ] 2135023
[ Exec Time : ] 0.106469 sec
[ Compile   : ] 0.144924 sec

Code:
> eval object array inside; for(int ix = 0; ix < 1000; ix++) inside = filter(users(), (: object who_env = environment($1); return who_env && who_env->query_terrain(Terrain_Building); :)); return inside
[ Result    : ] [Array] 6:
                  [Object] /usr/takoror (/usr/atman/grundy) (Takoror)
                  [Object] /usr/protax (/usr/atman/jensendied) (Protax)
                  [Object] /usr/clericon (/usr/atman/deomer) (Clericon)
                  [Object] /usr/morgana (/usr/atman/oboklob) (Morgana)
                  [Object] /usr/grumpy (/usr/atman/chadnoe) (Grumpy)
                  [Object] /usr/dyne (/usr/atman/cyrus) (Dyne)
[ Eval Cost : ] 2035021
[ Exec Time : ] 0.110267 sec
[ Compile   : ] 0.140591 sec

I had it do the loop 1000 times to amplify the picture, since one pass took about a tenth of a millisecond.

Conclusion: the explicit loop is about 3.5% faster than a filter() in this instance.  Wodan's version that refrains from using += on an array will probably be faster yet; I would test it if I had any interest in packing all that into an eval.

Note that it achieves this faster speed while costing more LP eval units.  This is one of the many, many illustrations available of why eval units are good for one thing only, the eval limit (and they're barely good for that).

So, yeah.  This is enough speed difference to worry about in situations where you're already worrying about speed.
« Last Edit: September 09, 2008, 10:45:50 AM by chaos » Logged

zortek
Acquaintance
*
Offline Offline

Posts: 13


View Profile
« Reply #16 on: September 09, 2008, 05:36:05 PM »

Forest and trees.
Logged
cratylus
Your favorite and best
Administrator
***
Offline Offline

Posts: 871


Cratylus@Dead Souls <ds> np


View Profile WWW
« Reply #17 on: September 09, 2008, 05:40:21 PM »

Liver and onions.

Logged
Nulvect
Friend
**
Offline Offline

Posts: 67


View Profile
« Reply #18 on: September 09, 2008, 06:57:16 PM »

Using wodan's version with no += and using time_expression gives me this:
Code:
eval return time_expression { object *inside = allocate(sizeof(users())); object pl, env; int i=0; foreach (pl in users()) { env = environment(pl); if (env && env->query_property("indoors")) inside[i++] = pl; } inside = inside[0..i-1]; write(identify(inside)+"\n"); }

({ OBJ(uzamaki /std/user#1), OBJ(cyan /std/user#991), OBJ(geddoe /std/user#5375), OBJ(nulvect
/std/user#6247) })

Result = 243

({ OBJ(uzamaki /std/user#1), OBJ(cyan /std/user#991), OBJ(geddoe /std/user#5375), OBJ(nulvect
/std/user#6247) })

Result = 205

({ OBJ(uzamaki /std/user#1), OBJ(cyan /std/user#991), OBJ(geddoe /std/user#5375), OBJ(nulvect
/std/user#6247) })

Result = 222

({ OBJ(uzamaki /std/user#1), OBJ(cyan /std/user#991), OBJ(geddoe /std/user#5375), OBJ(nulvect
/std/user#6247) })

Result = 220

({ OBJ(uzamaki /std/user#1), OBJ(cyan /std/user#991), OBJ(geddoe /std/user#5375), OBJ(nulvect
/std/user#6247) })

Result = 235

({ OBJ(uzamaki /std/user#1), OBJ(cyan /std/user#991), OBJ(geddoe /std/user#5375), OBJ(nulvect
/std/user#6247) })

Result = 221

({ OBJ(uzamaki /std/user#1), OBJ(cyan /std/user#991), OBJ(geddoe /std/user#5375), OBJ(nulvect
/std/user#6247) })

Result = 220


Code:
eval return time_expression { object *inside = filter(users(), (: environment($1) && environment($1)->query_property("indoors") :) ); write(identify(inside)+"\n"); }

({ OBJ(uzamaki /std/user#1), OBJ(cyan /std/user#991), OBJ(geddoe /std/user#5375), OBJ(nulvect
/std/user#6247) })

Result = 212

({ OBJ(uzamaki /std/user#1), OBJ(cyan /std/user#991), OBJ(geddoe /std/user#5375), OBJ(nulvect
/std/user#6247) })

Result = 217

({ OBJ(uzamaki /std/user#1), OBJ(cyan /std/user#991), OBJ(geddoe /std/user#5375), OBJ(nulvect
/std/user#6247) })

Result = 217

({ OBJ(uzamaki /std/user#1), OBJ(cyan /std/user#991), OBJ(geddoe /std/user#5375), OBJ(nulvect
/std/user#6247) })

Result = 215

({ OBJ(uzamaki /std/user#1), OBJ(cyan /std/user#991), OBJ(geddoe /std/user#5375), OBJ(nulvect
/std/user#6247) })

Result = 206

({ OBJ(uzamaki /std/user#1), OBJ(cyan /std/user#991), OBJ(geddoe /std/user#5375), OBJ(nulvect
/std/user#6247) })

Result = 214

({ OBJ(uzamaki /std/user#1), OBJ(cyan /std/user#991), OBJ(geddoe /std/user#5375), OBJ(nulvect
/std/user#6247) })

Result = 216

That's 7 runs each. With filter had an average of 213 microseconds, without had an average of 223. I guess my driver is just weird; I understand that this is supposed to be abnormal... Either way though, I'm not going to worry about 10 microseconds.
« Last Edit: September 09, 2008, 07:01:14 PM by Nulvect » Logged
wodan
BFF
***
Offline Offline

Posts: 245


View Profile
« Reply #19 on: September 09, 2008, 10:20:29 PM »

try larger arrays Smiley
Logged
Nulvect
Friend
**
Offline Offline

Posts: 67


View Profile
« Reply #20 on: September 10, 2008, 12:42:57 AM »

I tried it with testing each of objects() for ->is_weapon(), sizeof(objects()) == 2974. There are 365 weapons loaded. 7 passes of each again, filter averaged 4646 and foreach averaged 5146 microseconds.

I know I am probably sounding argumentative, but I'm really not trying to be. I'm very interested in making my code as efficient as possible, so I just like to know these things. Any ideas why my driver seems to be so odd??


The evals I typed, one right after the other (but formatted so they are readable):
Code:
eval int total=0; int *times = allocate(7);
for (int j = 0; j < 7; j++) {
  times[j] = time_expression {
    object *weapons = allocate(sizeof(objects()));
    object ob; int i=0;
    foreach (ob in objects())
      if (ob->is_weapon())
        weapons[i++] = ob;
    weapons = weapons[0..i-1];
    write(sizeof(weapons)+"\n");
  };
  total += times[j];
}
return total/7;

//---

eval int total=0; int *times = allocate(7);
for (int j = 0; j < 7; j++) {
  times[j] = time_expression {
    object *weapons = filter(objects(), (: $1->is_weapon() :) );
    write(sizeof(weapons)+"\n");
  };
  total += times[j];
}
return total/7;
Logged
chaos
BFF
***
Offline Offline

Posts: 212


Job, school, social life, sleep. Pick 2.5.


View Profile WWW
« Reply #21 on: September 10, 2008, 02:42:38 AM »

I'd be interested in knowing what sorts of results you get using my code (the plain old += version) rather than Wodan's with the pre-allocate.

Pre-allocating sizeof(objects()) seems pretty scary to me...
Logged

wodan
BFF
***
Offline Offline

Posts: 245


View Profile
« Reply #22 on: September 10, 2008, 10:49:44 AM »

I'd love to know what is scary about that. Anyway if for some weird reason filter is faster, in this case you're still doing it wrong  Cheesy

object *weapons = filter(objects(), (: $1->is_weapon() Smiley );

is shorter and at least in theory faster when written as
object *weapons = objects( (: $1->is_weapon() Smiley );

This functionality of objects() is quite handy when you have more objects than your max array size Smiley
Logged
Nulvect
Friend
**
Offline Offline

Posts: 67


View Profile
« Reply #23 on: September 10, 2008, 04:51:52 PM »

Ah, cool. I never use objects() so I didn't know it could do that.
Logged
detah
BFF
***
Offline Offline

Posts: 154


Ruler of 2D


View Profile
« Reply #24 on: September 10, 2008, 04:58:18 PM »

PLEASE use the code tags.
Ironically, it is the pound sign button right above the row of smilies in the text box.
Logged
chaos
BFF
***
Offline Offline

Posts: 212


Job, school, social life, sleep. Pick 2.5.


View Profile WWW
« Reply #25 on: September 10, 2008, 06:04:39 PM »

Wodan: it's scary because objects(), in my world at least, is pretty damned large.  So it's scary in that it's more likely to break array limit than other methods (irrelevantly to performance) and is more likely to trigger an sbrk() than other methods (relevantly to performance).

Nulvect: Eval test?  Pretty please?  I could theorize about what's going on in differences between our drivers, but I'd like an apples-to-apples comparison first.
Logged

Tricky
BFF
***
Offline Offline

Posts: 168


I like what I code and I code what I like!


View Profile
« Reply #26 on: September 10, 2008, 06:44:05 PM »

Ah, cool. I never use objects() so I didn't know it could do that.

You can actually do that with any array of objects.

Code:
object *nonidle = filter(users(), (: query_idle($1) < 60 :) );
string *names = nonidle->GetKeyName(); /* DS lib specific. */

Tricky
Logged

chaos
BFF
***
Offline Offline

Posts: 212


Job, school, social life, sleep. Pick 2.5.


View Profile WWW
« Reply #27 on: September 10, 2008, 07:20:26 PM »

Pretty sure he meant the form of objects() where you pass it the filter.
Logged

Pages: 1 [2]   Go Up
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.11 | SMF © 2006-2009, Simple Machines LLC Valid XHTML 1.0! Valid CSS!