Raised This Month: $51 Target: $400
 12% 

Optimizing Plugins: Cache Results on a Larger Scale?


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
MeRcyLeZZ
Veteran Member
Join Date: Dec 2007
Old 03-18-2009 , 21:01   Optimizing Plugins: Cache Results on a Larger Scale?
Reply With Quote #1

Surely many of you have read the article on the Wiki about how saving results helps optimize your plugins. Now I'm wanting to know what you guys think about applying such method on a larger scale (sort of).

Let's say I have the following code:
Code:
public fw_PlayerPreThink( id ) {     if ( get_pcvar_num( cvar_affectBots ) && is_user_bot( id ) && is_user_alive( id ) )     {         // Do stuff...     } }
So if the forward gets called 100 times a second, that means the plugin will be checking the CVar value, whether the player is alive, and whether it's a bot 100 times per second per player (this assuming they all pass the checks). However there is no need for that, since stuff like that doesn't change that often.

So the idea would be to:

1. Cache the CVar on new round events (since there is no forward for detecting the exact moment it's changed). Then we can just add to the plugin's documentation: "CVar changes will take effect after a new round". Usually, end-users won't be upset by this restriction IMO.

2. Cache whether the user is a bot on client connect forwards (since the "bot" property will only change whenever a new player joins the server).

3. Cache whether the player is alive on client spawn, death, and disconnect events (since... well you get the point).

So this is what the final code would look like:
Code:
#include <amxmodx> #include <cstrike> #include <fakemeta> #include <hamsandwich> new cvar_affectBots new g_cachedAffectBots, g_isBot[33], g_isAlive[33] public plugin_init() {     register_plugin( "Cache Results", "0.0", "Example" )         register_event("HLTV", "event_round_start", "a", "1=0", "2=0")         RegisterHam( Ham_Spawn, "player", "fw_PlayerSpawn", 1 )     RegisterHam( Ham_Killed, "player", "fw_PlayerKilled", 1 )         register_forward( FM_PlayerPreThink, "fw_PlayerPreThink" )         cvar_affectBots = register_cvar( "amx_affect_bots", "1" ) } public plugin_cfg() {     // Cache CVARs after configs are loaded     set_task(0.5, "event_round_start") } public event_round_start() {     g_cachedAffectBots = get_pcvar_num( cvar_affectBots ) } public client_putinserver( id ) {     if ( is_user_bot( id ) )         g_isBot[id] = true } public client_disconnect( id ) {     g_isAlive[id] = false     g_isBot[id] = false } public fw_PlayerSpawn( id ) {     // Filter out false Ham_Spawn triggers (please ignore the fact I didn't     // add CZ bots support for this, that's beyond the scope of this thread)     if ( !is_user_alive( id ) || !cs_get_user_team( id ) )         return;         g_isAlive[id] = true } public fw_PlayerKilled( id /*, attacker, shouldgib*/ ) {     g_isAlive[id] = false } public fw_PlayerPreThink( id ) {     if ( g_cachedAffectBots && g_isBot[id] && g_isAlive[id] )     {         // Do stuff...     } }
Yeah, it looks more complex, I know. But it should actually be more efficient. And I've seen some plugins already doing this.

So what do you think? Is this really an optimization? If so, is it worth it the work? And when?
__________________

Last edited by MeRcyLeZZ; 03-21-2009 at 17:31. Reason: fixed link
MeRcyLeZZ is offline
Brad
AMX Mod X Team Member
Join Date: Jun 2004
Old 03-18-2009 , 22:04   Re: Optimizing Plugins: Cache Results on a Larger Scale?
Reply With Quote #2

I'd reckon that in this case, if it's faster, it'd be that much better. With that in mind, you could do some benchmarks to see which method is faster and by what degree.

Looking forward to your findings.
__________________
Brad is offline
MeRcyLeZZ
Veteran Member
Join Date: Dec 2007
Old 03-19-2009 , 23:07   Re: Optimizing Plugins: Cache Results on a Larger Scale?
Reply With Quote #3

Quote:
Originally Posted by Brad
I'd reckon that in this case, if it's faster, it'd be that much better. With that in mind, you could do some benchmarks to see which method is faster and by what degree.
Results speak for themselves.

Test 1 - FM_PlayerPreThink forward

Normal:
Code:
date: Thu Mar 19 23:26:04 2009 map: de_dust2
type |                             name |      calls | time / min / max
-------------------------------------------------------------------
   n |                  register_plugin |          1 | 0.000004 / 0.000004 / 0.000004
   n |                 register_forward |          1 | 0.000010 / 0.000010 / 0.000010
   n |                    register_cvar |          1 | 0.000076 / 0.000076 / 0.000076
   n |                    get_pcvar_num |      18979 | 0.053471 / 0.000001 / 0.000456
   n |                      is_user_bot |      18979 | 0.263113 / 0.000003 / 0.000557
   n |                    is_user_alive |      18979 | 0.029252 / 0.000001 / 0.000208
   p |                fw_PlayerPreThink |      18979 | 0.119988 / 0.000003 / 0.001141
   p |                      plugin_init |          1 | 0.000004 / 0.000004 / 0.000004
0 natives, 0 public callbacks, 2 function calls were not executed.
Optimized:
Code:
date: Thu Mar 19 23:26:04 2009 map: de_dust2
type |                             name |      calls | time / min / max
-------------------------------------------------------------------
   n |                  register_plugin |          1 | 0.000002 / 0.000002 / 0.000002
   n |                   register_event |          1 | 0.000019 / 0.000019 / 0.000019
   n |                      RegisterHam |          2 | 0.000218 / 0.000054 / 0.000164
   n |                 register_forward |          1 | 0.000004 / 0.000004 / 0.000004
   n |                    register_cvar |          1 | 0.000006 / 0.000006 / 0.000006
   n |                         set_task |          1 | 0.000004 / 0.000004 / 0.000004
   n |                    get_pcvar_num |          2 | 0.000003 / 0.000001 / 0.000001
   n |                      is_user_bot |          1 | 0.000003 / 0.000003 / 0.000003
   n |                    is_user_alive |          3 | 0.000004 / 0.000001 / 0.000002
   n |                 cs_get_user_team |          2 | 0.000004 / 0.000002 / 0.000002
   p |                client_disconnect |          1 | 0.000002 / 0.000002 / 0.000002
   p |               client_putinserver |          1 | 0.000002 / 0.000002 / 0.000002
   p |                event_round_start |          2 | 0.000007 / 0.000003 / 0.000004
   p |                fw_PlayerPreThink |      18979 | 0.032394 / 0.000001 / 0.000389
   p |                   fw_PlayerSpawn |          3 | 0.000012 / 0.000003 / 0.000004
   p |                       plugin_cfg |          1 | 0.000002 / 0.000002 / 0.000002
   p |                      plugin_init |          1 | 0.000007 / 0.000007 / 0.000007
6 natives, 2 public callbacks, 9 function calls were not executed.
Test 2 - FM_AddToFullPack forward

Normal:
Code:
date: Thu Mar 19 23:42:00 2009 map: de_dust2
type |                             name |      calls | time / min / max
-------------------------------------------------------------------
   n |                  register_plugin |          1 | 0.000004 / 0.000004 / 0.000004
   n |                 register_forward |          1 | 0.000010 / 0.000010 / 0.000010
   n |                    register_cvar |          1 | 0.000076 / 0.000076 / 0.000076
   n |                    get_pcvar_num |    1641431 | 1.646760 / 0.000001 / 0.001176
   n |                      is_user_bot |    1641431 | 4.036367 / 0.000002 / 0.001273
   n |                    is_user_alive |    1641431 | 1.651495 / 0.000001 / 0.001062
   p |                 fw_AddToFullPack |    1641431 | 6.402578 / 0.000003 / 0.001015
   p |                      plugin_init |          1 | 0.000004 / 0.000004 / 0.000004
0 natives, 0 public callbacks, 2 function calls were not executed.
Optimized:
Code:
date: Thu Mar 19 23:42:00 2009 map: de_dust2
type |                             name |      calls | time / min / max
-------------------------------------------------------------------
   n |                  register_plugin |          1 | 0.000002 / 0.000002 / 0.000002
   n |                   register_event |          1 | 0.000011 / 0.000011 / 0.000011
   n |                      RegisterHam |          2 | 0.000153 / 0.000028 / 0.000125
   n |                 register_forward |          1 | 0.000003 / 0.000003 / 0.000003
   n |                    register_cvar |          1 | 0.000004 / 0.000004 / 0.000004
   n |                         set_task |          1 | 0.000005 / 0.000005 / 0.000005
   n |                    get_pcvar_num |          2 | 0.000003 / 0.000001 / 0.000002
   n |                      is_user_bot |          1 | 0.000003 / 0.000003 / 0.000003
   n |                    is_user_alive |          3 | 0.000004 / 0.000001 / 0.000002
   n |                 cs_get_user_team |          2 | 0.000004 / 0.000002 / 0.000002
   p |                client_disconnect |          1 | 0.000002 / 0.000002 / 0.000002
   p |               client_putinserver |          1 | 0.000002 / 0.000002 / 0.000002
   p |                event_round_start |          2 | 0.000007 / 0.000003 / 0.000004
   p |                 fw_AddToFullPack |    1641431 | 1.707666 / 0.000001 / 0.000867
   p |                   fw_PlayerSpawn |          3 | 0.000011 / 0.000003 / 0.000004
   p |                       plugin_cfg |          1 | 0.000002 / 0.000002 / 0.000002
   p |                      plugin_init |          1 | 0.000007 / 0.000007 / 0.000007
6 natives, 2 public callbacks, 9 function calls were not executed.
Guess I'll be having a busy week with ZP...


* Special thanks to sawce for his magnificent profiler.
__________________
MeRcyLeZZ is offline
danielkza
AMX Mod X Plugin Approver
Join Date: May 2007
Location: São Paulo - Brasil
Old 03-19-2009 , 23:33   Re: Optimizing Plugins: Cache Results on a Larger Scale?
Reply With Quote #4

One thing you should not forget though is that the extra work of that approach only brings benefits on forwards called multiple times a second. I don't doubt we'll see people caching everything for a 10s task, like it happened with the fakemeta-conversion fad.
__________________

Community / No support through PM
danielkza is offline
stupok
Veteran Member
Join Date: Feb 2006
Old 03-19-2009 , 23:40   Re: Optimizing Plugins: Cache Results on a Larger Scale?
Reply With Quote #5

If I'm doing the calculations correctly...

FM_PlayerPreThink:
The optimized version is 14.38 times faster overall than the normal version.

Normal version spends an average of 24.54 microseconds per call.
Optimized version spends an average of 1.71 microseconds per call.

FM_AddToFullPack:
The optimized version is 8.04 times faster overall than the normal version.

Normal version spends an average of 8.37 microseconds per call.
Optimized version spends an average of 1.04 microseconds per call.

So, this technique reduces the time spent by roughly one order of magnitude.

I love to see this kind of data ^___________________^. Thanks, MeRcyLeZZ!

In the end, we're dealing with microseconds. How noticeable will this optimization be for the end user?
__________________
stupok is offline
Hunter-Digital
Veteran Member
Join Date: Aug 2006
Location: In the Game [ro]
Old 03-20-2009 , 09:05   Re: Optimizing Plugins: Cache Results on a Larger Scale?
Reply With Quote #6

Quote:
In the end, we're dealing with microseconds. How noticeable will this optimization be for the end user?
well... microseconds for one forward... but if the plugin has a couple of forwards like that on each player (that's maximum of 32) ... they eventually turn into seconds and results lag also it's best to optimize them just for the good coding habbits, also on low-end hardware it's quite noticeable
__________________
Hunter-Digital is offline
xPaw
Retired AMX Mod X Moderator
Join Date: Jul 2008
Old 03-20-2009 , 09:10   Re: Optimizing Plugins: Cache Results on a Larger Scale?
Reply With Quote #7

MeRcyLeZZ where did you got this analyzing tool?
__________________
xPaw is offline
Arkshine
AMX Mod X Plugin Approver
Join Date: Oct 2005
Old 03-20-2009 , 09:32   Re: Optimizing Plugins: Cache Results on a Larger Scale?
Reply With Quote #8

http://forums.alliedmods.net/showthread.php?t=67752
Arkshine is offline
Old 03-21-2009, 18:19
MeRcyLeZZ
This message has been deleted by MeRcyLeZZ. Reason: redundant
Old 03-30-2009, 01:15
MeRcyLeZZ
This message has been deleted by MeRcyLeZZ.
SchlumPF*
Veteran Member
Join Date: Mar 2007
Old 03-30-2009 , 17:25   Re: Optimizing Plugins: Cache Results on a Larger Scale?
Reply With Quote #9

should be added to the efficiency tutorial!!!
i already used it but i couldnt imagine that there is such a difference in using it in fast ticking things such as preThink :O
__________________
SchlumPF* is offline
Send a message via ICQ to SchlumPF*
ot_207
Veteran Member
Join Date: Jan 2008
Location: Romania The Love Country
Old 03-30-2009 , 18:08   Re: Optimizing Plugins: Cache Results on a Larger Scale?
Reply With Quote #10

Quote:
Originally Posted by SchlumPF* View Post
should be added to the efficiency tutorial!!!
i already used it but i couldnt imagine that there is such a difference in using it in fast ticking things such as preThink :O
Roger that .
Will do it these days .
__________________
My approved plug-ins | Good for newbies! | Problems?

Back, will come around when I have time.
ot_207 is offline
Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 03:41.


Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Theme made by Freecode