logo logo

 Back to main page

The NWNX Community Forum

 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 
 
Interesting performance numbers
Goto page 1, 2  Next
 
Post new topic   Reply to topic    nwnx.org Forum Index -> Development
View previous topic :: View next topic  
Author Message
Grinning Fool



Joined: 12 Feb 2005
Posts: 264

PostPosted: Thu Dec 14, 2006 18:43    Post subject: Interesting performance numbers Reply with quote

So I was doing some informal testing last night on how long it took to perform a simple key-value lookup in mysql, vs string comparisons. Testing was done on a T7400. Performance results as recorded from the TIME plugin.


Loop 320 times through 11 if/then/else string == value comparisons (total 3520 comparisons), where value is a 5-byte string and string is a constant with nothing in common. On average 7 ms or .002ms for one string comparison.


Loop 320 times through the same comparison as above, but using StringCompare: average 15.5 ms or .004ms for one string comparison. I didn't test it, but I suspect if I made that case sensitive, it would be the same as the "==" comparison.

Perform a single key/value lookup on an indexed mysql table containing 320 records (none of which match the key), perform SQLFetch(). On average 4ms.

So basically - if you need to do a key-value lookup, it will be faster to hard-code string compares for up to about 2000 values. This of course will vary slightly depending on database speed; too, my database was hosted elsewhere on my LAN.

Separately, I found that executing if/then/else to compare an int variable against 11 integer constants in a loop for 320 times ran about .1 ms slower on average than using a switch/case statement to do the same. (0.6 ms if/then/else, 0.5 switch/case)

Anyway... just some numbers I found interesting and figured to share. I will also probably be testing storing string data in a hashmap through a plugin, and running the same perf test. I just need time to write the plugin...
_________________
Khalidine, a NWN2 persistent world

Looking for volunteers.
Back to top
View user's profile Send private message
caloup



Joined: 29 Sep 2006
Posts: 59
Location: albi (france)

PostPosted: Thu Dec 14, 2006 18:56    Post subject: Reply with quote

Thanks for your work ! If someone could do the same with a MySQL server on the same computer...
Back to top
View user's profile Send private message
Grinning Fool



Joined: 12 Feb 2005
Posts: 264

PostPosted: Fri Dec 15, 2006 3:19    Post subject: Reply with quote

Quote:

Anyway... just some numbers I found interesting and figured to share. I will also probably be testing storing string data in a hashmap through a plugin, and running the same perf test. I just need time to write the plugin...


So I hacked a quick nwnx_util plugin that handles the hashmap. So far, testing against a map loaded with four hundred elements, iterating the lookup 320 times: averages a very consistent 7.4 ms; or 0.0225 ms per lookup. This was the same whether the lookup succeeded or failed.

With this in mind, to continue the earlier train of thought: looks like whene a map contains 200 or more string values, it's more efficient than doing string compares on a miss.
_________________
Khalidine, a NWN2 persistent world

Looking for volunteers.
Back to top
View user's profile Send private message
Papillon
x-man


Joined: 28 Dec 2004
Posts: 1060
Location: Germany

PostPosted: Fri Dec 15, 2006 22:05    Post subject: Reply with quote

Hold on, there is something I do not get here: You said you were doing 11 if-then-else comparisons, 320 times, and that took 7ms. Now you do 320 lookups in the hashset, but that contains 400 entries, not only 11, right ? Is that even comparable ?

Anyway, very interesting stuff! I'd like to add that the plugin hashmap solution scales with constant O, while the if-then-else construct only scales with O(n) - until it runs into a TMI error Smile.

Btw, the overhead of calling nwnx functions is likely to go down in the future.

I know you are busy with the demo modules, but would you be interested in porting the hashset plugin over to nwnx4 ?
_________________
Papillon
Back to top
View user's profile Send private message Visit poster's website MSN Messenger
Grinning Fool



Joined: 12 Feb 2005
Posts: 264

PostPosted: Fri Dec 15, 2006 22:35    Post subject: Reply with quote

Quote:
Hold on, there is something I do not get here: You said you were doing 11 if-then-else comparisons, 320 times, and that took 7ms. Now you do 320 lookups in the hashset, but that contains 400 entries, not only 11, right ? Is that even comparable ?

Not directly, but I actually tested with both higher and lower numbers (600, 100) and found no appreciable difference in performance.
[edit] Blergh -- no wonder there was no appreciable difference. I was using the default hash size of ten Wink


Quote:
Btw, the overhead of calling nwnx functions is likely to go down in the future.

Cool - does this involve cooperation from OE?

Quote:
I know you are busy with the demo modules, but would you be interested in porting the hashset plugin over to nwnx4 ?

Sure if there's not an immediate need - especially since they're likely to be more robust than the roll-your-own I've been working on for testing and my own project. I've also added two new functions I can include if you don't think they're too specialized.
- "load from file" functionality which populates a hashset from the specified text file containing comma-separated key-value pairs.
- tokenize string lookups in a hashset. First call, you pass in the string to tokenize, and the name of the map to search. Second and subsequent calls return the hashmapped value associated with individual matching words. (Using this for emote processing in a speech/command system ). Example:

input string: "*laughs as he sits down*"
hash content:
laugh => 1
laughs => 1
sit => 2
sits => 2

First call: examines token "laughs", checks the specified map, and returns "1"
Second call: loops through "as", "he", (no matches), "sits" and returns "2"
Third call: checks "down" and returns "" (indicating no more matches)

When there are a couple hundred possible emotes, this should be way faster than testing for substring after substring in script.
_________________
Khalidine, a NWN2 persistent world

Looking for volunteers.


Last edited by Grinning Fool on Sat Dec 16, 2006 8:57; edited 1 time in total
Back to top
View user's profile Send private message
Grinning Fool



Joined: 12 Feb 2005
Posts: 264

PostPosted: Sat Dec 16, 2006 2:23    Post subject: Reply with quote

Hm -- went to download the hashtable plugin, but didn't see the source anywhere?
_________________
Khalidine, a NWN2 persistent world

Looking for volunteers.
Back to top
View user's profile Send private message
Papillon
x-man


Joined: 28 Dec 2004
Posts: 1060
Location: Germany

PostPosted: Sat Dec 16, 2006 21:49    Post subject: Reply with quote

I've added the source to the hash plugin. It seems like I forgot to add it when I uploaded the archive last year.

But beware, the source code is likely a mess and it might be better to implement something like this with STL containers. You could use the include file and the plugin as a working set of functions and methods, and extend from there.
_________________
Papillon
Back to top
View user's profile Send private message Visit poster's website MSN Messenger
Grinning Fool



Joined: 12 Feb 2005
Posts: 264

PostPosted: Sat Dec 16, 2006 23:05    Post subject: Reply with quote

Quote:
've added the source to the hash plugin. It seems like I forgot to add it when I uploaded the archive last year.

But beware, the source code is likely a mess and it might be better to implement something like this with STL containers. You could use the include file and the plugin as a working set of functions and methods, and extend from there.

Cool -- that's actually what I ended up doing last night. Most of it is coded, except for next/prev keys -- was working on a non-cumbersome way to maintain state for each of the hashsets. I've done the implementation using the wx map classes for the time being. Mostly I was interested in seeing how maps were associated with specific objects -- I've done it by converting object pointer to text and appending it ot the provided key name, which turns out not too disimilar from what you had done.

Hmm -- is there any way to know when an object goes invalid? If someone calls DestroyObject on something that has a hashmap associated, there's currently no way for us to free up the memory used.
_________________
Khalidine, a NWN2 persistent world

Looking for volunteers.
Back to top
View user's profile Send private message
Papillon
x-man


Joined: 28 Dec 2004
Posts: 1060
Location: Germany

PostPosted: Sun Dec 17, 2006 0:42    Post subject: Reply with quote

Since DestroyObject is not hooked, you can not know when an object is destroyed. Therefore, it has to be the user's responsibility to clean up properly. IMHO, hooking DestroyObject just for that reason is not really worth it... but of course, it could be done.

Another way would be to add a function that inspects all known objects in memory. Maybe DestroyObject marks the objects in memory somehow ? Not sure. Anyway, the gameObject pointer in the Payload function is not valid right now, so this would be an option for the future.
_________________
Papillon
Back to top
View user's profile Send private message Visit poster's website MSN Messenger
FunkySwerve



Joined: 02 Jun 2005
Posts: 377

PostPosted: Tue Dec 19, 2006 4:36    Post subject: Reply with quote

Can someone explain the advantages of hashes vs other data storage setups, to a nonprogrammer? I'm planning to do a nwnx4 version of my legendary level system, and I need to store large masses of 2da data in faster-access format. With nwn1, I simply scripted the data into scripts, which was acceptable because it was fast and there were no more expansions coming at that point to worry about. With nwn2, there are (hopefully) expansions coming, and I'd like a data setup that's fast and easy to update. Options I've thought of to date:

1) A custom 2da. I have to access too many 2das for the data I need, but the last 2 2das accessed are cached, assuming nwn2 carried over that little bit of optimization. Having all the data in one table would make a standard scripted 2da lookup fast, or at least fast enough, I think.
2) A nwnx database. Not sure how many values I'd have to select in a go, but I'm confident it would outpace 2da reads substantially.
3) Script functions. While this is what I went with in 1, it'd be a pain to update.

Would a hash be better than the above options?

Thanks,
Funky
Back to top
View user's profile Send private message
Lokey



Joined: 02 Jan 2005
Posts: 158

PostPosted: Tue Dec 19, 2006 11:06    Post subject: Reply with quote

You still need to populate the hash from one of your options at say module load, but reading it will probably be fastest/lowest overhead among them depending on how fast the NWNx connection is. That's probably what counts most.
_________________
Neversummer PW NWNx powered mayhem Wink
Back to top
View user's profile Send private message
FunkySwerve



Joined: 02 Jun 2005
Posts: 377

PostPosted: Tue Dec 19, 2006 20:39    Post subject: Reply with quote

Again, I'm a non-programmer - I have no idea what 'populating' the hash entails - loading data into it? Wouldn't it be possible to store the data permanetnly in it as wioth a database, or is that the difference between them, other than speed?
Funky
Back to top
View user's profile Send private message
Grinning Fool



Joined: 12 Feb 2005
Posts: 264

PostPosted: Tue Dec 19, 2006 22:42    Post subject: Reply with quote

That would be the other difference between them. Hash tables aren't persistent -- they exist only in memory. So at the module startup, you'd need to populate them. THe NWNX4 hashtable plugin will provide a way to do so using a file; or you can load it from a database through nwscript.
_________________
Khalidine, a NWN2 persistent world

Looking for volunteers.
Back to top
View user's profile Send private message
FunkySwerve



Joined: 02 Jun 2005
Posts: 377

PostPosted: Wed Dec 20, 2006 4:48    Post subject: Reply with quote

Ok, thanks, both of you. Smile
Funky
Back to top
View user's profile Send private message
abraxas77



Joined: 17 Nov 2006
Posts: 15

PostPosted: Thu Dec 21, 2006 13:23    Post subject: Reply with quote

That timer is a nifty little tool, eh.

I ran a few test comparing two methods of storing/retrieving a list of 256 (pregenerated) random names. First method was storing them as local strings on a single waypoint. In the second method, I stored one local string on 256 waypoints.

I can't compare the population times b/c I was testing a cache system ... my bit field tracking methods about doubled my population times. Anyways, the access times suprised me a little. (but again ... my cache has to translate the index into bucket+bucketindex).

I used a stardard for loop to iterate over 256 strings: get the string and write it to a log.

Local Strings on one waypoint did it in ~9ms.
My cache of waypoints did it in ~10ms. (using GetWaypointByTag)
Using GetObjectByTag, the cache did it in ~11ms.

The local string populated 256 strings ~5ms.

It took ~100ms to create 256 waypoints.
It took ~450ms to create 1024 waypoints.


I did run a few test on an earlier version of my cache ... before I implemented the bucket structute and a bit fields. My test data wasn't as uniform as my latest test which caused inconsistant results ... but on average it seemed the cache method was slightly faster ... at best 1ms faster access time over 128 elements.
_________________
aka. twp_andrew

:: Lead Script Design :: The World of Paladium II ::
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    nwnx.org Forum Index -> Development All times are GMT + 2 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group