Orjinalini okuyabilirsiniz; (Çeviri tıpa tıp aynısı değildir, bazıları doğru bazıları kendi eklediklerimdir)
https://wiki.alliedmods.net/Optimizing_ ... Scripting)
Giriş (Kısaltılmıştır) :
Çoğu kişi, yazılan eklenti için şunları varsaymaktadır:
* Önceden derlenmiş eklentileri daha optimize edemeyiz. Onlar zaten optimize edilmiş halde.
* Ayrıntılar, sadece "komut dosyası (sma)" olduğu için önemli değil
Öncelikle bunların hiçbiri doğru değil. Derleyici, aslında opitimize etme konusunda çok zayıftır ve eklentilerinizin hızını
ve verimliliğini birkaç kural göz önünde bulundurarak büyük ölçüde arttırabilirsiniz. Unutmayın ki;
Talimatları en aza indirmek, kod satırlarını en aza indirmekten daha iyidir.
( Yani kod satırı az olan eklentiler, çok olanlardan kesin daha hızlı çalışır diye bir şey yok.)
Derleyici Optimizasyonları :
Bu optimizasyonlar kodunuzun nasıl derleneceğini değiştirmekle ilgilidir. Sözdizimi aynı kalabilse bile,
sadece derleme süresini arttırmakla kalmaz, aynı zamanda eklentinin verimliliğini ve hızını da arttırırsınız.
* Her zaman sonuçları kayıt et :
Aşağıdaki örnek kodu inceleyiniz
Kod: Tümünü seç
if (get_user_team(player) == TEAM_T)
{
//...code
} else if (get_user_team(player) == TEAM_CT) {
//...code
} else if (get_user_team(player) == TEAM_SPECTATOR) {
//...code
}
Kod: Tümünü seç
CALL get_user_team
COMPARE+BRANCH
CALL get_user_team
COMPARE+BRANCH
CALL get_user_team
COMPARE+BRANCH
Kod: Tümünü seç
new team = get_user_team ( player )
if ( team == TEAM_T )
{
//...code
} else ise ( team == TEAM_CT ) {
//...code
} else ise ( team == TEAM_SPECTATOR ) {
//. ..code
}
Kod: Tümünü seç
CALL get_user_team
COMPARE + BRANCH
COMPARE + BRANCH
COMPARE + BRANCH
Eğer yapabiliyorsanız, if yerine switch komutunu kullanın. Bunun nedeni, derleyici aynı komutu defalarca kontrol ediyor.
Yukardaki örneği bu şekilde değiştirebiliriz.
Kod: Tümünü seç
new team = get_user_team(player)
switch (team)
{
case TEAM_T:
//code...
case TEAM_CT:
//code...
case TEAM_SPECTATOR:
//code...
}
Kod: Tümünü seç
CALL get_user_team
COMPARE
COMPARE
COMPARE
Eskiden yaygın bir hataydı. Artık o kadar kullanılmıyor fakat bunu da silmek istemedim. Sorun; dizileri yeniden diziye eklerek,
yer tasarrufu yapmaktır. Derleyicide yer tasarrufu yapıp bu şekilde eklentinizi kodlamayınız. Aşağıdaki koda bakalım;
Kod: Tümünü seç
new players[32], num, team
get_players(players, num, "h")
for (new i=0; i<num; i++)
{
team = get_user_team(players[i])
set_user_frags(players[i], 0)
}
Kod: Tümünü seç
:LOOP_BEGIN
LOAD i
LOAD players
CALC
LOAD players[i]
CALL get_user_team
LOAD i
LOAD players
CALC
LOAD players[i]
CALL set_user_frags
Bu yüzden tekrar tekrar oyuncuları kontrol etti. Bunun yerine bu şekilde kullanmak daha iyi olacaktır;
Kod: Tümünü seç
new player
for (new i=0; i<num; i++)
{
player = players[i]
team = get_user_team(player)
set_user_frags(player, 0)
}
Kod: Tümünü seç
:LOOP_BEGIN
LOAD i
LOAD players
CALC
LOAD players[i]
STORE player
CALL get_user_team
LOAD player
CALL set_user_frags
* Küresel vs Yerel (Global vs Local) ve Döngülerdeki Değişkenler :
Bu konuyu kısa bir şekilde, anlayacağınız şekilde anlatacağım. Bazı şu anlık ilk başlayanlar için anlamsız yerleri sildim.
Döngüler içindeki dizileri bildirmekten kaçının. Aşağıdaki örneğe bir bakalım.
Kod: Tümünü seç
for (new i=0; i<num; i++)
{
new message[255], name[32], player
player = players[i]
get_user_name(player, name, 31)
format(message, 254, "Hello, %s", name)
}
Bunu dizenin ilk karakterini sıfırlayarak optimize edebiliriz. Aşağıdaki koda bir bakalım.
Kod: Tümünü seç
new message[255], name[32], player
for (new i=0; i<num; i++)
{
player = players[i]
name[0] = '^0'
message[0] = '^0'
get_user_name(player, name, 31)
format(message, 254, "Hello, %s", name)
}
* Statik vs Küresel (Static vs Global) :
new yerine static anahtar kelimesiyle bildirilen bir değişken, bir global yapıda olduğu gibi çalışır.
Yani yalnızca bir kez oluşturulur. Ancak değişken işlevi yereldir; Bu kodun hızını önemli ölçüde geliştirirken okunması daha kolay
olduğu anlamına gelir; Örnek:
Kod: Tümünü seç
stock SomeBigFunction()
{
static gaben[255];
format(gaben, "%L", LANG_SERVER, "STUFF");
}
çağrılıyorsa, statik değişken kullanmamalısınız demektir. Yani değişkeni sadece salisede bir kere çalışan yığınlarda
veya herhangi bir yığında değişmeyen komut olması şartıyla kullanabilirsiniz. Bir örnek vereyim, bu örnekteki gibi kullanmayınız.
Kod: Tümünü seç
public PurposeLess_Ornek()
{
static name[32];
new players[32], inum;
static Uid;
get_players(players, inum);
for(new i=0; i<inum; i++)
{
Uid = players[i];
name[0] = '^0';
get_user_name(Uid, name, charsmax(name));
client_print_color(Uid, Uid, "Isminiz: %s", name);
}
}
* Sabit Değişkenler :
Değişken adından önce "const" anahtar sözcüğünü ekleyerek sabit değişkenini bildirebilirsiniz.
Kod: Tümünü seç
new const AMX_GABEN[] = "amx_gaben"
Ek olarak, sabit değişkenler genellikle daha hızlı ve daha küçük kodla sonuçlanacak şekilde optimize edilir.
* Döngü Karşılaştırmaları (for komutu) :
Yaygın bir hata bu şekilde kullanımdır.
Kod: Tümünü seç
new string[256] = "something long"
for (new i=0; i<strlen(string); i++)
//...code
Dize orta döngü değiştirilirse, bunun daha kötü etkileri olacaktır. Daha mantıklı bir yöntem.
Kod: Tümünü seç
new string[256] = "something long"
new len = strlen(string)
for (new i=0; i<len; i++)
//...code
Örnek olarak silah endekslerinin isimlere eleştirildiğini varsayalım.
Kod: Tümünü seç
if (weapon == CSW_AK47)
copy(name, len, "weapon_ak47")
Bu sonucu bir tabloda önceden yapabiliriz;
Kod: Tümünü seç
new g_WeaponNamesTable[TOTAL_WEAPONS][] = {
//..0 to CSW_AK47-1
"weapon_ak47",
//..CSW_AK47+1 to TOTAL_WEAPONS-1
};
Bir sabit kodlu dizeyi eklentinizde çok kez kullanırsanız çok farklı kez görünecektir (kullanılacaktır).
Örnek;
Kod: Tümünü seç
set_cvar_num("amx_gaben", get_cvar_num("amx_gaben") + 1)
Benzer olarak, bu aynı sorun var.
Kod: Tümünü seç
#define AMX_GABEN "amx_gaben"
set_cvar_num(AMX_GABEN, get_cvar_num(AMX_GABEN) + 1)
Kod: Tümünü seç
new AMX_GABEN[] = "amx_gaben"
set_cvar_num(AMX_GABEN, get_cvar_num(AMX_GABEN) + 1)
bu anahtarı kolay şekilde yapabilirsiniz.
Bunun değişmesini önlemek için, onu sürekli olarak bildirmek isteyebilirsiniz. (const kullanabilirsiniz)
Kod: Tümünü seç
new const AMX_GABEN[] = "amx_gaben"
set_cvar_num(AMX_GABEN, get_cvar_num(AMX_GABEN) + 1)
Kullanabileceğiniz Daha Hızlı Komutlar :
* Cvar Pointers :
Cvar komutunu pointer ile kullanmak düzinelerce kat daha hızlı olan kritik bir optimizasyondur. Örneğin;
Kod: Tümünü seç
new g_enabled = register_cvar("csdm_enabled", "1")
//OR
new g_enabled = get_cvar_pointer("csdm_enabled")
stock SetCSDM(num)
set_pcvar_num(g_enabled, num)
stock GetCSDM()
return get_pcvar_num(g_enabled)
get_cvar_pointer veya register_cvar ile cvarları önbelleğe alabilirsiniz.
FormatEX :
format ile formatex komutu neredeyse aynı olarak çalışır. Fakat format komutu, geri kopyalama yeteneğine sahiptir.
Bir kaynak girdisi, çıktısı arabelleği ile aynı ise, formatex kullanılamaz. Örneğin; bunlar geçersiz;
Kod: Tümünü seç
new buffer[255]
formatex(buffer, charsmax(buffer), "%s", buffer);
formatex(buffer, charsmax(buffer), buffer);
formatex(buffer, charsmax(buffer), "%d %s", buffer[2]);
daha hızlı çalışır.
FM_Touch (fakemeta.inc) | Ham_Touch (hamsandwich.inc) | register_touch(engine.inc):
Dokunanı algılama eklentisi yapacaksınız fakat hangisini kullanacağınızı bilmiyorsanız burada hangisinin daha hızlı
çalıştığını anlatacağım. Yabancı forum AMX Mod X Plugin Approver yani eklenti onaylayıcısı tarafından
denenmiştir.
[Kaynak:https://forums.alliedmods.net/showthread.php?t=213075]
register_touch aralarında en hızlı çalışan komuttur.
Eklenti yazarken register_touch kullanmanız eklentinizi biraz da olsa hızlandıracaktır.
Stock | Bool | Tagsız Komutlar [Hangisini kullanmalıyız?]
Eklentilerde bazen bir komutu veya bir düşünceyi tekrar tekrar kullanabiliyoruz. Bunun için kısayol tarzı bir şey yaptığımız da oluyor.
Peki bunlarda stock mu bool mu yoksa hiçbir tag kullanmayacak mıyız?
Öncelikle hiçbir eklentinizde stock kullanmayın. stock komutu çoğunlukla include yani kütüphanelerde kullanılıyor.
Eklentide kullanılması önerilmiyor.
; Kaynak : https://forums.alliedmods.net/showpost. ... stcount=13
You shouldn't be using "stock" in the .sma files. This tag is used only if there is a possibility that the function will not be used at all. Since this is your code and you added the function, you're probably going to use it as well, so remove the "stock" tag. Only use "stock" in include files where not all functions must be used in the code when included.
"bool" is **** self-explainatory. If the variable is tagged with "bool", then the return value of the function should also be "bool". Bools can be only true or false.
Bool ve tagsız komutlar için örneklere bakalım.
Oyuncular glow verme komutunu ele alabiliriz. 4 komutu kullanmak yerine bir komuta bağlayıp, o komutu kullanıyoruz.
Kod: Tümünü seç
rg_set_user_rendering(index, fx = kRenderFxNone, {Float,_}:color[3] = {0.0,0.0,0.0}, render = kRenderNormal, Float:amount = 0.0)
{
set_entvar(index, var_renderfx, fx);
set_entvar(index, var_rendercolor, color);
set_entvar(index, var_rendermode, render);
set_entvar(index, var_renderamt, amount);
}
daha iyi olacaktır.
Kod: Tümünü seç
bool:is_user_stuck(index)
{
static Float:origin[3];
get_entvar(index, var_origin, origin);
engfunc(EngFunc_TraceHull, origin,origin, IGNORE_MONSTERS, get_entvar(index, var_flags) & FL_DUCKING ? HULL_HEAD : HULL_HUMAN, 0, 0);
return (get_tr2(0, TR_StartSolid)) ? true:false;
}
Bunu true false olarak sabitlemek için bool kullanmaniz daha iyi olacaktır. Gömülü ise true, değilse false.
Dosya yazılımı :
Hala yaygın olarak kullanılan bir hatadır. Amx Mod X ısrarla bu komutları kullanmayın demesine rağmen hala kullanılmakta.
read_file, write_file gibi komutlar yerine fopen, fgets, fputs, fclose gibi komutlar kullanılmalıdır.
+
Verdiğim siteden hangi komutun ne işe yaradığını ve nasıl çalıştığını öğrenebilirsiniz. Sorularınızı ve anlamadığınız yerleri sorabilirsiniz.
Umarım yardımcı olabilmişimdir. Sunucular için optimize edilmiş eklentiler yapmanız dileğiyle :)
Site: https://amxx-bg.info/api/