AlliedModders

AlliedModders (https://forums.alliedmods.net/index.php)
-   Scripting Help (https://forums.alliedmods.net/forumdisplay.php?f=11)
-   -   Optimizing Plugins: Cache Results on a Larger Scale? (https://forums.alliedmods.net/showthread.php?t=87977)

MeRcyLeZZ 03-18-2009 21:01

Optimizing Plugins: Cache Results on a Larger Scale?
 
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?

Brad 03-18-2009 22:04

Re: Optimizing Plugins: Cache Results on a Larger Scale?
 
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. :wink:

MeRcyLeZZ 03-19-2009 23:07

Re: Optimizing Plugins: Cache Results on a Larger Scale?
 
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.

danielkza 03-19-2009 23:33

Re: Optimizing Plugins: Cache Results on a Larger Scale?
 
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.

stupok 03-19-2009 23:40

Re: Optimizing Plugins: Cache Results on a Larger Scale?
 
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?

Hunter-Digital 03-20-2009 09:05

Re: Optimizing Plugins: Cache Results on a Larger Scale?
 
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

xPaw 03-20-2009 09:10

Re: Optimizing Plugins: Cache Results on a Larger Scale?
 
MeRcyLeZZ where did you got this analyzing tool?

Arkshine 03-20-2009 09:32

Re: Optimizing Plugins: Cache Results on a Larger Scale?
 
http://forums.alliedmods.net/showthread.php?t=67752

SchlumPF* 03-30-2009 17:25

Re: Optimizing Plugins: Cache Results on a Larger Scale?
 
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

ot_207 03-30-2009 18:08

Re: Optimizing Plugins: Cache Results on a Larger Scale?
 
Quote:

Originally Posted by SchlumPF* (Post 793445)
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 :P.
Will do it these days :).


All times are GMT -4. The time now is 09:01.

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