Hướng dẫn này là dành cho tất cả các scripters arround amxx, đề nghị cho scripters trung gian.
Một plugin hiệu quả là đầu tiên của tất cả những gì?
Một plugin hiệu quả là sử dụng ít CPU và bộ nhớ.
Hãy để tôi đưa ra một ví dụ:
Chúng ta hãy cố gắng nghĩ ra một phương pháp để xem thời tiết một người chơi đã bị giết chết. Phương pháp này có thể được thực hiện nhiều cách khác nhau nhưng tôi sẽ chỉ ra 2 trong số họ, một tốt và một xấu.
Một trong những tốt là khi chúng ta nối các sự kiện DeathMsg
PHP Code:
register_event("DeathMsg", "event_death", "a")
public event_death()
{
new attacker = read_data(1)
new victim = read_data(2)
}
PHP Code:
public client_PreThink(id)
{
if (!is_user_alive(id))
{
new attacker = get_user_attacker(id)
}
}
Vâng vấn đề là PreThink được gọi là> 30 lần mỗi giây và điều đó có nghĩa rằng chúng tôi đang kiểm tra quá nhiều lần người chơi đã bị giết chết. Đây là một vấn đề bởi vì nó sẽ gây ra rất nhiều sử dụng CPU, một vấn đề mà các máy tính nhỏ không thể xử lý. Bởi rất nhiều sử dụng CPU có nghĩa là chúng tôi sẽ có rất nhiều lag.
Chúng ta hãy một lần nữa cho một ví dụ tốt hơn inefficency nhưng một subtile hơn.
Chúng ta hãy cố gắng hook các sự kiện DeathMsg và nhận được tất cả các thông tin mà chúng tôi cần.
Đây là phương pháp tốt nhất của việc lấy các thông tin chúng ta cần là trong ví dụ đầu tiên. Điều thứ hai sẽ sử dụng quá nhiều hàm trong trường hợp này là không cần thiết ...
PHP Code:
register_event("DeathMsg", "event_death", "a")
public event_death()
{
new attacker = read_data(1)
new victim = read_data(2)
new weapon_name[33],weapon_id
// get the weapon name
read_data(4,weapon_name,32)
format(weapon_name,32,"weapon_%s",weapon_name)
weapon_id = get_weaponid(weapon_name)
}
PHP Code:
register_event("DeathMsg", "event_death", "a")
public event_death()
{
new victim = read_data(2)
new attacker = get_user_attacker(victim)
new weapon = get_user_weapon(attacker)
}
Vâng vấn đề là cho đến khi tất cả các forwards event_death sẽ được gọi là, các dữ liệu mà chúng tôi có sẽ được lưu trữ trong lõi, và nó sẽ được truy cập thông qua read_data () chức năng. Vì vậy, trong trường hợp này là không cần thiết để truy cập vào các công cụ một lần nữa để có được thông tin này từ cốt lõi đã chuẩn bị cho chúng tôi.
Các mô-đun hiệu quả nhất là gì?
Vâng câu hỏi này phụ thuộc vào những điều bạn muốn làm trong một plugin.
Hầu hết mọi người nói rằng FakeMeta là module tốt nhất arround nhưng nó không phải là hiệu quả nhất! Module này sử dụng rất nhiều CPU bởi vì cơ sở dữ liệu lớn của chức năng mà nó cung cấp. Cho câu hỏi này là câu trả lời: tất cả các mô-đun có những điều tốt đẹp để cung cấp, chúng ta phải sử dụng các chức năng đặc biệt được cung cấp bởi mỗi mô-đun.
Điều đó có nghĩa là khi chúng ta có thể làm một điều trong engine hoặc fun, ham nó sẽ là tốt nhất để sử dụng engine / fun / ham thay vì fakemeta do rất nhiều sử dụng CPU.
Tôi sẽ cung cấp cho bạn một ví dụ.
Nếu chúng ta sử dụng fm_is_in_viewcone, tôi sẽ đánh dấu những nơi mà các plugin liên lạc với các mô-đun:
PHP Code:
stock bool:fm_is_in_viewcone(index, const Float:point[3]) {
new Float:angles[3];
pev(index, pev_angles, angles); // COMUNICATION WITH MODULE
engfunc(EngFunc_MakeVectors, angles); // COMUNICATION WITH MODULE
global_get(glb_v_forward, angles); // COMUNICATION WITH MODULE
angles[2] = 0.0;
new Float:origin[3], Float:diff[3], Float:norm[3];
pev(index, pev_origin, origin); // COMUNICATION WITH MODULE
xs_vec_sub(point, origin, diff);
diff[2] = 0.0;
xs_vec_normalize(diff, norm);
new Float:dot, Float:fov;
dot = xs_vec_dot(norm, angles);
pev(index, pev_fov, fov); // COMUNICATION WITH MODULE
if (dot >= floatcos(fov * M_PI / 360))
return true;
return false;
}
Khi chúng ta sử dụng engine ví dụ:
PHP Code:
is_in_viewcone ( entity, Float:origin[3] ) // COMUNICATION WITH MODULE
Đây là những gì sẽ xảy ra khi chúng tôi sử dụng fakemeta:
PLUGIN -> FAKEMETA -> METAMOD -> GAME ENGINE -> METAMOD -> FAKEMETA -> PLUGIN
Nhân với 5 lần và chúng ta sẽ thấy thời gian thực hiện của fm_is_in_viewcone.
Đây là những gì sẽ xảy ra khi chúng tôi sử dụng mô-đun engine:
PLUGIN -> ENGINE -> METAMOD -> GAME ENGINE -> METAMOD -> ENGINE -> PLUGIN
Chỉ có một lần.
Nó cũng phụ thuộc vào dữ liệu chúng tôi muốn nhận hoặc thiết lập.
Đây là lý do tại sao trong một số trường hợp chúng ta nên sử dụng fun hoặc engine hơn fakemeta. Chúng không sử dụng nhiều CPU và có sử dụng bộ nhớ thấp trong tình huống này.
Để xác nhận những gì tôi đã nói về Liên lạc module tôi sẽ trả lời ở đây một số tiêu chuẩn sẽ so sánh fakemeta với các mô-đun cstrike và engine mô-đun natives / stocks. Bạn sẽ thấy rằng điều này làm cho sự khác biệt.
Entity_set_origin vs. fm_entity_set_origin [fakemeta vs engine]
Code:
type | name | calls | time / min / max
-------------------------------------------------------------------
n | register_plugin | 1 | 0.000008 / 0.000008 / 0.000008
n | register_clcmd | 1 | 0.000017 / 0.000017 / 0.000017
n | random_float | 60000 | 0.134438 / 0.000001 / 0.000116
n | server_cmd | 1 | 0.000006 / 0.000006 / 0.000006
p | plugin_init | 1 | 0.000010 / 0.000010 / 0.000010
p | profile | 1 | 0.182920 / 0.182920 / 0.182920
n | entity_set_origin | 10000 | 0.035055 / 0.000002 / 0.000082
n | pev | 20000 | 0.044686 / 0.000001 / 0.000183
n | engfunc | 20000 | 0.052677 / 0.000002 / 0.000073
f | fm_entity_set_origin | 10000 | 0.113504 / 0.000008 / 0.000373
0 natives, 0 public callbacks, 2 function calls were not executed.
Code:
type | name | calls | time / min / max
-------------------------------------------------------------------
n | server_cmd | 1 | 0.000008 / 0.000008 / 0.000008
p | plugin_init | 1 | 0.000007 / 0.000007 / 0.000007
p | profile | 1 | 0.112695 / 0.112695 / 0.112695
n | register_plugin | 1 | 0.000004 / 0.000004 / 0.000004
n | register_clcmd | 1 | 0.000016 / 0.000016 / 0.000016
n | floatsqroot | 10000 | 0.022363 / 0.000001 / 0.000038
n | floatdiv | 10000 | 0.022110 / 0.000001 / 0.000036
n | pev | 30000 | 0.067148 / 0.000001 / 0.000086
n | engfunc | 10000 | 0.025055 / 0.000001 / 0.000011
n | global_get | 10000 | 0.022244 / 0.000001 / 0.000031
n | floatcos | 10000 | 0.022657 / 0.000001 / 0.000209
n | random_float | 30000 | 0.066903 / 0.000001 / 0.000035
f | operator/(Float:,_:) | 10000 | 0.022434 / 0.000001 / 0.000077
f | operator>=(Float:,Float:) | 10000 | 0.021916 / 0.000001 / 0.000011
f | xs_rsqrt | 10000 | 0.067513 / 0.000004 / 0.000110
f | xs_vec_sub | 10000 | 0.021978 / 0.000001 / 0.000009
f | xs_vec_normalize | 10000 | 0.045749 / 0.000003 / 0.000073
f | xs_vec_dot | 10000 | 0.022200 / 0.000001 / 0.000047
f | fm_is_in_viewcone | 10000 | 0.271947 / 0.000022 / 0.000220
n | is_in_viewcone | 10000 | 0.025373 / 0.000002 / 0.000104
6 natives, 0 public callbacks, 2 function calls were not executed.
Code:
type | name | calls | time / min / max
-------------------------------------------------------------------
n | register_plugin | 1 | 0.000008 / 0.000008 / 0.000008
n | register_clcmd | 1 | 0.000016 / 0.000016 / 0.000016
n | server_cmd | 1 | 0.000004 / 0.000004 / 0.000004
p | plugin_init | 1 | 0.000011 / 0.000011 / 0.000011
p | profile | 1 | 0.046530 / 0.046530 / 0.046530
n | entity_range | 10000 | 0.022555 / 0.000001 / 0.000056
f | fm_entity_range | 10000 | 0.092081 / 0.000006 / 0.000087
n | pev | 20000 | 0.044973 / 0.000001 / 0.000037
n | get_distance_f | 10000 | 0.022852 / 0.000001 / 0.000025
0 natives, 0 public callbacks, 2 function calls were not executed.
Code:
type | name | calls | time / min / max
-------------------------------------------------------------------
n | get_pdata_int | 300000 | 0.647404 / 0.000001 / 0.000253
n | set_pdata_int | 150064 | 0.328161 / 0.000001 / 0.000331
n | get_user_msgid | 2 | 0.000006 / 0.000003 / 0.000004
n | emessage_begin | 150064 | 0.379386 / 0.000002 / 0.000309
n | ewrite_long | 100000 | 0.238946 / 0.000001 / 0.000458
n | ewrite_byte | 225160 | 0.518973 / 0.000001 / 0.000357
n | emessage_end | 150064 | 0.374745 / 0.000002 / 0.000218
n | set_pev | 50064 | 0.110391 / 0.000001 / 0.000077
n | ewrite_string | 50064 | 0.121614 / 0.000001 / 0.000250
n | register_plugin | 1 | 0.000007 / 0.000007 / 0.000007
n | register_clcmd | 1 | 0.000016 / 0.000016 / 0.000016
n | random | 300000 | 0.648347 / 0.000001 / 0.000217
n | server_cmd | 1 | 0.000004 / 0.000004 / 0.000004
p | benchmark | 1 | 2.511592 / 2.511592 / 2.511592
p | plugin_init | 1 | 0.000007 / 0.000007 / 0.000007
n | cs_get_user_money | 100000 | 0.220167 / 0.000001 / 0.000414
f | fm_cs_get_user_money | 100000 | 0.446478 / 0.000003 / 0.000413
n | cs_set_user_money | 100000 | 0.276739 / 0.000002 / 0.000329
f | fm_cs_set_user_money | 100000 | 1.344050 / 0.000010 / 0.001747
n | cs_get_user_defuse | 100000 | 0.220294 / 0.000001 / 0.000094
f | fm_cs_get_user_defuse | 100000 | 0.452164 / 0.000003 / 0.000161
n | cs_set_user_defuse | 100000 | 0.336809 / 0.000002 / 0.000270
f | fm_cs_set_user_defuse | 100000 | 1.294073 / 0.000003 / 0.000333
Sự khác biệt giữa các mô-đun forwards là gì? Vâng sự khác biệt chính của forwards là phương pháp đăng ký.
Mô-đun cung cấp Những tiền đạo hiệu quả nhất?
Sự khác biệt khi chúng ta nói về hiệu quả * sẽ được gần như không đáng kể.
Code:
type | name | calls | time / min / max
-------------------------------------------------------------------
n | register_plugin | 1 | 0.000010 / 0.000010 / 0.000010
n | register_forward | 1 | 0.000008 / 0.000008 / 0.000008
n | server_cmd | 1 | 0.000016 / 0.000016 / 0.000016
p | playerPreThink | 2001 | 0.004775 / 0.000002 / 0.000007
p | plugin_init | 1 | 0.000007 / 0.000007 / 0.000007
0 natives, 0 public callbacks, 2 function calls were not executed.
date: Mon Mar 30 15:46:09 2009 map: de_dust2
type | name | calls | time / min / max
-------------------------------------------------------------------
n | register_plugin | 1 | 0.000005 / 0.000005 / 0.000005
n | server_cmd | 1 | 0.000016 / 0.000016 / 0.000016
p | client_PreThink | 2001 | 0.004718 / 0.000002 / 0.000018
p | plugin_init | 1 | 0.000004 / 0.000004 / 0.000004
Code:
type | name | calls | time / min / max
-------------------------------------------------------------------
n | register_plugin | 1 | 0.000009 / 0.000009 / 0.000009
n | register_clcmd | 1 | 0.000013 / 0.000013 / 0.000013
n | random_float | 300000 | 0.665777 / 0.000001 / 0.000323
n | set_pev | 100000 | 0.222021 / 0.000001 / 0.000154
n | entity_set_vector | 100000 | 0.220881 / 0.000001 / 0.000152
n | server_cmd | 1 | 0.000008 / 0.000008 / 0.000008
p | plugin_init | 1 | 0.000007 / 0.000007 / 0.000007
p | profile | 1 | 1.132186 / 1.132186 / 1.132186
0 natives, 0 public callbacks, 2 function calls were not executed.
Code:
type | name | calls | time / min / max
-------------------------------------------------------------------
n | precache_model | 1 | 0.015410 / 0.015410 / 0.015410
n | register_plugin | 1 | 0.000007 / 0.000007 / 0.000007
n | register_clcmd | 1 | 0.000016 / 0.000016 / 0.000016
n | server_cmd | 1 | 0.000007 / 0.000007 / 0.000007
p | plugin_init | 1 | 0.000008 / 0.000008 / 0.000008
p | plugin_precache | 1 | 0.000008 / 0.000008 / 0.000008
p | profile | 1 | 0.466186 / 0.466186 / 0.466186
n | pev_valid | 100000 | 0.228750 / 0.000001 / 0.000165
n | is_valid_ent | 100000 | 0.226901 / 0.000001 / 0.000095
Lợi thế đó sẽ xuất hiện một khi chúng ta bộ nhớ đệm chúng là gì?
Tốt lợi thế là nó sẽ sử dụng ít CPU và nó sẽ làm cho một sự khác biệt lớn khi chúng ta nói về kiểm tra lặp đi lặp lại (như forwards prethink), bất lợi là nó sử dụng bộ nhớ.
Có nghĩa là gì để kết quả bộ nhớ đệm?
Ví dụ chúng tôi muốn biết một người chơi là một bot.
Thay vì sử dụng chức năng này tất cả các thời gian:
PHP Code:
is_user_bot(id)
PHP Code:
new bool:cl_is_bot[33]
public client_putinserver(id)
{
if (is_user_bot(id))
cl_is_bot[id] = true;
}// now we only use cl_is_bot[id] not is_user_bot(id)
Bạn phải nhớ rằng việc này sẽ làm cho bạn Plugin khó khăn hơn để thực hiện.
Đây là một ví dụ với kết quả bộ nhớ cache và các bài kiểm tra, bạn sẽ thấy rằng chúng ta sẽ có một sự khác biệt lớn, vì vậy nó sẽ được khuyến khích sử dụng bộ nhớ đệm để làm cho một plugin hiệu quả.
Đây là ý tưởng chính của những gì MeRcyLeZZ muốn làm để cải thiện các plugin của mình.
http://forums.alliedmods.net/showpos...91&postcount=1
Đây là kết quả
http://forums.alliedmods.net/showpos...28&postcount=3
Tôi sẽ trích quan điểm về Fakemate của Hawk552s (fakemeta sử dụng chung).
Quote:
I didn't say that. Porting stuff to Fakemeta is not a be-all end-all solution. There are many, many reasons not to use Fakemeta. Here are some of them:
Why are we fretting over these trivial optimizations (which you're actually largely part wrong about being faster in the first place) as opposed to making code legible? Why should I write code that is 4x as long and is slower just because the API I'm using is more capable? Why don't we just use ASM, under that reasoning? We've had this debate before. GHW_Chronic made it a requirement for plugins to only use Fakemeta. This makes absolutely no sense. There's no reason we can't use Fun and Engine for everything other than the things only Fakemeta can do. I've written many APIs (see Apollo RP in my signature); I can guarantee you, far more than you have. From that experience, I know that capability is not the most important quality of an API. An API, especially for something like AMXX, should be simple. The way we have the APIs divided up is great. We should only encourage people to use Fakemeta when it is necessary and no other module can accomplish the task at hand. There is absolutely no reason to make a point of using Fakemeta exclusively unless you're trying to appear intelligent or you actually know it better than Engine and Fun. Stop telling beginners to use Fakemeta, it will only confuse them and makes things more complicated than they have to be. |
We must use the module when it has a specific good function that others don't provide.
The less module comunications the better!!!
And remember this tutorial does not want to say not to use fakemeta! It advises to use it only when it needs to be used!
A plugin isn't bad if it uses 10 modules instead of just 2...
If you propose to cache some results in a plugin, it will be more efficient but there will be a problem when we talk about easy scripting.
Good tutorials that fit in with this one:
http://forums.alliedmods.net/showthread.php?t=43049
http://forums.alliedmods.net/showthread.php?t=40340
http://forums.alliedmods.net/showthr...296#post809296
Benchmark tool, for the people who want to do some more tests, if you want feel free to post the results in the efficency tutorial:
http://forums.alliedmods.net/showthread.php?t=67752
My comment: Hope that it is ok, if you would like to add some more please tell me. I'm not used on writing such long posts... [Hope that my english was fine ...]
I thank all that spend their time reading this tutorial, suggested improvements and contributed to this tutorial!