View previous topic :: View next topic |
Author |
Message |
Grinning Fool
Joined: 12 Feb 2005 Posts: 264
|
Posted: Thu Dec 14, 2006 18:43 Post subject: Interesting performance numbers |
|
|
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 |
|
|
caloup
Joined: 29 Sep 2006 Posts: 59 Location: albi (france)
|
Posted: Thu Dec 14, 2006 18:56 Post subject: |
|
|
Thanks for your work ! If someone could do the same with a MySQL server on the same computer... |
|
Back to top |
|
|
Grinning Fool
Joined: 12 Feb 2005 Posts: 264
|
Posted: Fri Dec 15, 2006 3:19 Post subject: |
|
|
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 |
|
|
Papillon x-man
Joined: 28 Dec 2004 Posts: 1060 Location: Germany
|
Posted: Fri Dec 15, 2006 22:05 Post subject: |
|
|
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 .
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 |
|
|
Grinning Fool
Joined: 12 Feb 2005 Posts: 264
|
Posted: Fri Dec 15, 2006 22:35 Post subject: |
|
|
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
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 |
|
|
Grinning Fool
Joined: 12 Feb 2005 Posts: 264
|
Posted: Sat Dec 16, 2006 2:23 Post subject: |
|
|
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 |
|
|
Papillon x-man
Joined: 28 Dec 2004 Posts: 1060 Location: Germany
|
Posted: Sat Dec 16, 2006 21:49 Post subject: |
|
|
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 |
|
|
Grinning Fool
Joined: 12 Feb 2005 Posts: 264
|
Posted: Sat Dec 16, 2006 23:05 Post subject: |
|
|
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 |
|
|
Papillon x-man
Joined: 28 Dec 2004 Posts: 1060 Location: Germany
|
Posted: Sun Dec 17, 2006 0:42 Post subject: |
|
|
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 |
|
|
FunkySwerve
Joined: 02 Jun 2005 Posts: 377
|
Posted: Tue Dec 19, 2006 4:36 Post subject: |
|
|
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 |
|
|
Lokey
Joined: 02 Jan 2005 Posts: 158
|
Posted: Tue Dec 19, 2006 11:06 Post subject: |
|
|
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 |
|
Back to top |
|
|
FunkySwerve
Joined: 02 Jun 2005 Posts: 377
|
Posted: Tue Dec 19, 2006 20:39 Post subject: |
|
|
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 |
|
|
Grinning Fool
Joined: 12 Feb 2005 Posts: 264
|
Posted: Tue Dec 19, 2006 22:42 Post subject: |
|
|
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 |
|
|
FunkySwerve
Joined: 02 Jun 2005 Posts: 377
|
Posted: Wed Dec 20, 2006 4:48 Post subject: |
|
|
Ok, thanks, both of you.
Funky |
|
Back to top |
|
|
abraxas77
Joined: 17 Nov 2006 Posts: 15
|
Posted: Thu Dec 21, 2006 13:23 Post subject: |
|
|
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 |
|
|
|
|
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
|