View Single Post
Author Message
Timiditas
Senior Member
Join Date: Apr 2009
Old 07-29-2010 , 10:49   weapon string to index
Reply With Quote #1

Is this what you call "expensive", if called everytime a bullet is fired ingame... ?

PHP Code:

#pragma semicolon 1

#include <sourcemod>
#include <sdktools>
#include <profiler>

#define PLUGIN_VERSION "1.1c"
new Stringweaponlist[][] = { "ak47""m4a1""awp""deagle""mp5navy""aug",
                                                                
"p90""famas""galil""scout""g3sg1""hegrenade",
                                                                
"usp""glock""m249""m3""elite""fiveseven",
                                                                
"mac10""p228""sg550""sg552""tmp""ump45",
                                                                
"xm1014""knife" };
new 
hashlist[] = { 322312328610725317226520521558425931344,
                                        
528283163531971403280382386337452433525 };
//hashlist is generated by adding up all ascii chars PLUS the numeric value of each char if they are numeric
//e.g. m3 = 109+51+3
//this will certainly not work on much strings, but does not generate any collisions on this short weapon list

get_weapon_hash(const Stringweapon_name[])
{
    new 
hashWPlen strlen(weapon_name);
    for(new 
0;WPlen;I++)
    {
        
decl String:inmid[2];
        
strcopy(inmid,2,weapon_name[i]);
        
//new char:inmid = weapon_name[i];
        
hash += inmid[0];
        if(
IsCharNumeric(inmid[0]))
            
hash += StringToInt(inmid);
    }
    
    new 
loop_break 0index 0hWPsize sizeof(hashlist);
    
    while ((
loop_break == 0) && (index hWPsize))
    {
        if (
hash == hashlist[index])
            
loop_break++;
        
index++;
    }

    if (
loop_break == 0)
        return -
1;
    else
        return 
index 1;
}

get_weapon_index(const Stringweapon_name[])
{
    new 
loop_break 0index 0sWPsize sizeof(weaponlist);
    
    while ((
loop_break == 0) && (index sWPsize))
    {
        if (
strcmp(weapon_nameweaponlist[index], true) == 0)
            
loop_break++;
        
index++;
    }

    if (
loop_break == 0)
        return -
1;
    else
        return 
index 1;
}








public 
Plugin:myinfo = {
    
name "stringtest",
    
author "Timiditas",
    
description "string hashing",
    
version PLUGIN_VERSION,
    
url "nowhere to run"
};

public 
OnPluginStart() {
    
RegConsoleCmd("hash"fhash);
    
RegConsoleCmd("find"find);
}

public 
Action:fhash(clientargs)
{
    if (
args != 1)
    {
        
ReplyToCommand(client"usage: hash <anystring>");
        return 
Plugin_Handled;
    }
    
decl String:argument[255];
    
GetCmdArg(1argument255);
    new 
Handle:myProf CreateProfiler();
    
decl IDX;
    
StartProfiling(myProf);
    
IDX get_weapon_hash(argument);
    
StopProfiling(myProf);
    new 
Float:TheTime GetProfilerTime(myProf);
    
CloseHandle(myProf);
    
ReplyToCommand(client"Returned index: %i, HPT needed in seconds: %f",IDX,TheTime);
    return 
Plugin_Handled;
}

public 
Action:find(clientargs)
{
    if (
args != 1)
    {
        
ReplyToCommand(client"usage: find <anystring>");
        return 
Plugin_Handled;
    }
    
decl String:argument[255];
    
GetCmdArg(1argument255);
    new 
Handle:myProf CreateProfiler();
    
decl IDX;
    
StartProfiling(myProf);
    
IDX get_weapon_index(argument);
    
StopProfiling(myProf);
    new 
Float:TheTime GetProfilerTime(myProf);
    
CloseHandle(myProf);
    
ReplyToCommand(client"Returned index: %i, HPT needed in seconds: %f",IDX,TheTime);
    return 
Plugin_Handled;

Performance results below:

Code:
] find ak47
Returned index: 0, HPT needed in seconds: 0.000001
] hash ak47
Returned index: 0, HPT needed in seconds: 0.000003
] find knife
Returned index: 25, HPT needed in seconds: 0.000002
] hash knife
Returned index: 25, HPT needed in seconds: 0.000003
] find m3
Returned index: 15, HPT needed in seconds: 0.000002
] hash m3
Returned index: 15, HPT needed in seconds: 0.000003
] find fiveseven
Returned index: 17, HPT needed in seconds: 0.000002
] hash fiveseven
Returned index: 17, HPT needed in seconds: 0.000003
] find UNKNOWNSTRING
Returned index: -1, HPT needed in seconds: 0.000002
] hash UNKNOWNSTRING
Returned index: -1, HPT needed in seconds: 0.000004
So simply comparing the INTs is faster of course, but the required hashing at the beginning of get_weapon_hash() makes it slower.


~~edit

Actually, if you pack it into two loops, the results differ significantly.
PHP Code:
public Action:fhash(clientargs)
{
    if (
args != 1)
    {
        
ReplyToCommand(client"usage: hash <anystring>");
        return 
Plugin_Handled;
    }
    
decl String:argument[255];
    
GetCmdArg(1argument255);
    new 
Handle:myProf CreateProfiler();
    
decl IDXFloat:Times;
    for(new 
1;j<1001;j++)
    {
        
StartProfiling(myProf);
        for(new 
1;i<1001;i++)
        {
            
IDX get_weapon_hash(argument);
        }
        
StopProfiling(myProf);
        
Times += GetProfilerTime(myProf);
    }
    
Times /= 1000.0;
    
CloseHandle(myProf);
    
ReplyToCommand(client"Returned index: %i, HPT needed in seconds: %f",IDX,Times);
    return 
Plugin_Handled;
}

public 
Action:find(clientargs)
{
    if (
args != 1)
    {
        
ReplyToCommand(client"usage: find <anystring>");
        return 
Plugin_Handled;
    }
    
decl String:argument[255];
    
GetCmdArg(1argument255);
    new 
Handle:myProf CreateProfiler();
    
decl IDXFloat:Times;
    for(new 
1;j<1001;j++)
    {
        
StartProfiling(myProf);
        for(new 
1;i<1001;i++)
        {
            
IDX get_weapon_index(argument);
        }
        
StopProfiling(myProf);
        
Times += GetProfilerTime(myProf);
    }
    
Times /= 1000.0;
    
CloseHandle(myProf);
    
ReplyToCommand(client"Returned index: %i, HPT needed in seconds: %f",IDX,Times);
    return 
Plugin_Handled;

Results:
Code:
] find no
Returned index: -1, HPT needed in seconds: 0.001577
] hash no
Returned index: -1, HPT needed in seconds: 0.000444
] find no
Returned index: -1, HPT needed in seconds: 0.001581
] hash no
Returned index: -1, HPT needed in seconds: 0.000444
] find ak47
Returned index: 0, HPT needed in seconds: 0.000078
] hash ak47
Returned index: 0, HPT needed in seconds: 0.000750
] find knife
Returned index: 25, HPT needed in seconds: 0.001606
] hash knife
Returned index: 25, HPT needed in seconds: 0.000791
] find UNKNOWNSTRING
Returned index: -1, HPT needed in seconds: 0.001584
] hash UNKNOWNSTRING
Returned index: -1, HPT needed in seconds: 0.001692
] find m3
Returned index: 15, HPT needed in seconds: 0.001077
] hash m3
Returned index: 15, HPT needed in seconds: 0.000498
] find glock
Returned index: 13, HPT needed in seconds: 0.000948
] hash glock
Returned index: 13, HPT needed in seconds: 0.000729
] find hegrenade
Returned index: 11, HPT needed in seconds: 0.000764
] hash hegrenade
Returned index: 11, HPT needed in seconds: 0.001162
] find g3sg1
Returned index: 10, HPT needed in seconds: 0.000728
] hash g3sg1
Returned index: 10, HPT needed in seconds: 0.000960
The wiki says:
Quote:
The compiler, in fact, is very poor at optimizing
I wonder how much of the 'poor' optimizations kick in in the above loops.
__________________


Last edited by Timiditas; 07-29-2010 at 12:24. Reason: extended code to fully functional plugin
Timiditas is offline