Optimizare, simplitate şi stil
5/3/2017, 13:17
Salutare, astăzi vreau să discut cu voi nişte lucruri legate de optimizarea unui GM şi tot în acelaşi timp cum să faci lucrurile mai simple în GM.
Q: Mai simple? Cum mai simple?
A: Urmăreşte-mă şi vei află.
În primul rând să discutăm despre optimizare.
Optimizarea este esenţială pentru un GM, adică reduce timpul de execuţie a unei/unor functi.
Q: Bun, şi dacă îl reduce ce?
A: În timpul de executare a unei/unor funcţii lagul va creşte, şansă de crash devine mai mare şi nimeni nu e mulţumit.
Dacă optimizăm, timpul de lag va fi redus substanţial cea ce scade şansă de crash.
Q: Dar lagul acela de ce se produce?
A: Că să înţelegeţi mai bine imaginativă un calculator mai vechi, cu componente slabe de genu: 1 GB ram , placă video 64 , procesor AMD 2.0 GH.
Acum ganditiva că el lucrează. cu cât deschizi mai multe programe cu atât funcţionează din ce în ce mai greu , până se blochează.
Acum imaginativă un calculator mai bun de genu 4GB ram , placă video 1GB, procesor i3 şi punetil să ruleze aceleaşi programe. Cu siguranţă veţi observă diferenţa şi anume că se mişcă mai rapid la acele programe şi nu se mai blochează aşa de repede.
Aşa ceva este şi cu GM-ul. El trebuie să gândească în acelaşi timp ce face fiecare player în parte. Dacă GM nu este optimizat atunci clientul(adică voi) de a se bloca(crash) este mai mare.
Acum că am lămurit aceste aspecte haideţi să discutăm despre cum putem face un GM mai optim şi totodată introducem şi simplitatea.
Mai întâi voi începe cu sistemul de stocare a datelor MYSQL.
MYSQL
Observ că mulţi se plâng că nu mai sunt GM-uri pe ini(dini, yini sau alte derivări ale acestuia).Dacă tot am pomenit de derivările lui ini, pentru cei care nu ştiu sistemul de stocare a datelor ini este cel care crează un fişier .txt în scriptfiles>user(account/conturi/akk/etc). Dini, yini şi mai sunt câteva derivări sunt pentru a face puţină parformantă, adică să fie creat fişierul .txt mai rapid.
Ok , am lămurit şi acest aspect, acum hai să facem diferenţa mai întâi între ini şi mysql.Mai există şi SQLLite, dar habar nu am cu ce se mânca ăla...
Mysql este în momentul actual cel mai rapid şi mai de folos sistem de creare a datelor. Este cel mai avantajos dintre toate, iar conturile sunt într-o deplină siguranţă.
Q: Ok , şi ce treaba are cu siguranţă conturilor?
A: Hai să va zic ce mi să întâmplat mie personal după un restart. Eram pe un server de să-mp, şi numai văd că se da restart la server, eu aveam nivelul 5 , aveam 2.000.000 $ , 2 maşini, totul bine şi frumos , dar după ce să dat restart , mă văd că trb să mă înregistrez din nou, singurul de pe server, m-am înregistrat şi văd că am lvl 1 şi cele 2 maşini, iar ceilalţi nu aveau contul afectat. La mysql nu să întâmplat nici odată această.
Am zis că e şi mai rapid. Da este mult mult mai rapid decât ini , deoarece un cont pe mysql poate fi creat în baza de date într-un interval scurt de timp (0.0001-0.0010 secunde, tastaţi o comandă şi vedeţi timpul de execuţie dacă nu mă credeţi), iar la dini este undeva la 0.1 - 0.9 secunde , poate ajunge dacă este lag pe server chiar şi la 1 - 1.3 - 1.5 secunde.
Personal cred că este şi mai uşor de folosit. La mysql trebuie să fi atent la query-uri, pentru că ele trimit în baza de date informaţiile, în rest conturile se verifică cu if(Rows)- adică dacă se găsesc rânduri la acel cont, la dini de exemplu se verifică cu if(dini_Exists(file)) şi , personal mă bucur că e mai greu de făcut legătură cu baza de date, deoarece nu tot puştiul poate să-şi deschidă server.
Acum să vorbim despre procesoarele de comenzi.
ZCMD(cel mai cunoscut) şi altele
Văd că încă se foloseşte strcmp pe unele GM-uri. STRCMP este extrem de lent. STRCMP este o funcţie ce verifică mesajul din chat.
Adică, uitaţi cum arată o comandă pe strcmp: if (strcmp("/mycommand", cmdtext, true, 10) == 0) - verifică dacă a fost scris /mycomand.
Aici intervine zcmd, care e are 2 avantaje. Aici se poate spune de simplitate, adică e mai simplu să scri CMD:mycomand(playerid,params[]) decât if (strcmp("/mycommand", cmdtext, true, 10) == 0) , clar e mult mai simplu de scris.
Acum , haideţi să va vorbesc de ce strcmp e mult mai lent.
Să zicem că eu am 100 de comenzi pe strcmp. Eu folosesc ultima comandă, adică comandă cu numărul 100. STRCMP verifică 99 de comenzi şi când ajunge la a 100-a se aplică. În timp ce se verifică se produce lag, într-adevăr , lag-ul ăla se nu e vizibil , dar el există.
ZCMD e conceput să fie mai rapid. El foloseşte CallLocalFunction cea ce "se aruncă" direct în comandă şi nu stă să verifice cele 99 de comenzi , cea ce e vizibil mai rapidă comandă la executare.
Acum există nenumărate procesoare de comenzi LIFE-CMD MCMD(cel mai rapid la ora actuală), aceste procesoare au nevoie de plugin, iar în pluginul respectiv, este folosit memory hack, cea ce îl face mult mai rapid decât zcmd, dar e puţin vizibil ochiului că e mai rapid , dar că lag, e redus substanţial.
SSCANF
Când vorbim de sscanf putem spune clar simplitate în folosire. Sscanf este un strtok dar cu mai multe atribuiri şi este mult mult mai rapid în verificare. Am să va dau o comandă care foloseşte strtok să vedeţi şi cum se foloseşte.
CMD:givemoney(playerid,params[])
{
if(IsPlayerConnected(playerid))
{
tmp = strtok(cmdtext, idx);
if(!strlen(tmp))
{
SendClientMessage(playerid, COLOR_GRAD2, "USAGE: /givemoney [playerid/PartOfName] [money]");
return 1;
}
new playa;
new money;
playa = ReturnUser(tmp);
tmp = strtok(cmdtext, idx);
money = strval(tmp);
if (PlayerInfo[playerid][pAdmin] >= 1339)
{
if(IsPlayerConnected(playa))
{
if(playa != INVALID_PLAYER_ID)
{
GivePlayerMoney(playa, money);
}
}
}
else
{
SendClientMessage(playerid, COLOR_GRAD1, "Nu esti autorizat sa folosesti aceasta comanda");
}
}
return 1;
}
Vedeţi voi, în comandă există 2 strtok-uri şi acele strtok-uri se leagă şi de strlen. Strtok-ul , în comandă are atribuţia de a îi pune un parametru, în cazul nostru, la comandă de mai sus, avem 2 parametri şi anume "playerid/PartOfName" şi "money". Ele sunt definite în felul următor cu strtok: tmp = strtok(cmdtext, idx); - face legătură cu money, adică pune că parametru şi money(suma de bani pe care o atribuim) playa = ReturnUser(tmp); - transformă playa în jucător, adică oricare playa este jucător(playa este ţintă, persoană pe care aplicăm comandă) tmp = strtok(cmdtext, idx); - cu strtok îl definim că parametru în comandă money = strval(tmp); - cu strval money este definită că număr. Deci avem nevoie de 4 functi pentru o comandă simplă. Pare inutil să le scri , dar sunt esenţiale şi fără ele nu poţi face comandă corectă, mai ales că trebuie să transformăm definirile în valori playa - jucător, money - suma de bani şi să le facem că parametru. Aici intervine sscanf care e mult mult mai simplu de folosit şi mai rapid, adică noi transformăm definirile în valori şi totodată le facem şi parametri. Putem face în felul următor comandă, în loc să scriem atât o simplificăm şi o şi optimizăm.
CMD:givemoney(playerid,params[])
{
if(IsPlayerConnected(playerid))
{
new playa, money;
if(sscanf(params,"ud", playa, money))
return SendClientMessage(playerid, COLOR_GRAD2, "USAGE: /givemoney [playerid/PartOfName] [money]");
if (PlayerInfo[playerid][pAdmin] >= 1339)
{
if(IsPlayerConnected(playa))
{
if(playa != INVALID_PLAYER_ID)
{
GivePlayerMoneyEx(playa, money);
}
}
}
else
{
SendClientMessage(playerid, COLOR_GRAD1, "Nu esti autorizat sa folosesti aceasta comanda");
}
}
return 1;
}
Acum să analizăm. Noi avem parametri următori, eu vii prezint pe cei mai folosiţi:
s - String(sir de caractere, sau mesaj)
i, d - Integer(sau numar intreg) -> 1, 42, -10
c - Caracter -> a, o, *
l - Logical -> true, false
b - Binary -> 01001, 0b1100
h, x - Hex -> 1A, 0x23
o - Octal -> 045 12
n - Numar -> 42, 0b010, 0xAC, 045
f Float(numar cu virgula sau pozitie) -> 0.7, -99.5
u Username(Nume jucator sau id jucator) -> WiDuAlK(numele), 0(id-ul meu)
Bun şi acum să analizăm situaţia următoare: new playa, money; - eu am definit 2 lucruri: playa - care vreau să fie playerul şi money - care vreau să fie suma de bani pe care o atribui. if(sscanf(params,"ud", playa, money)) sscanf - funcţia (params - vine de la CMD:givemoney(playerid,params[]), dacă folosiţi strcmp, cea ce nu va recomand, în loc de params puneţi "cmdtext" din funcţia if (strcmp("/givemoney", cmdtext, true, 10) == 0) "ud", playa, money - fac 2 chestii 1 definesc valorile : "u" i se atribuie lui playa, "d" i se atribuie lui money, dacă era "ud", money, playa "u" i se atribuia lui money iar "d" lui playa. Deci revenim, această funcţie if(sscanf(params,"ud", playa, money)) este exact că funcţiile menţinute mai sus, adică : playa = ReturnUser(tmp); money = strval(tmp); deci respectivul "u" îl transformă pe playa în jucător, iar respectivul "d" îl transformă pe money în număr întreg. Tot în acelaşi timp, transformă cele acele 2 definiri în condiţi pentru comandă , adică dacă nu scrie /givemoney Widualk/0(id meu) 1000(suma de bani) să îi dea mesaj cu parametri comenzii. Totodată sscanf verifică dacă a scris parametri , nu doar îi transformă, deci if(sscanf(params,"ud", playa, money)) verifică dacă sau scris greşiţi parametri şi îi returnează un mesaj cu ei, sau cu ce vreţi voi. Că o concluzie la sscanf , ea are mai multe atribuţii , e şi simplă şi elegantă şi optimă şi ce vreţi voi. Deci e recomandabil să îl folosiţi la orice GM.
Foreach
Foreach-ul , este că un loop rapid. Loop-ul arată ceva de genu: for(new i = 0; i < MAX_PLAYERS; i++) , adică i să fie egal cu toţi jucători, adică să atribuie o funcţie tuturor jucătorilor. de genu:
for(new i = 0; i < MAX_PLAYERS; i++)
{
GivePlayerMoney(i,100);
}
sau
for(new i = 0; i < MAX_PLAYERS; i++)
{
GivePlayerWeapon(i,46(id arma),1(nr de munitii/gloante));
}
Acest "i" creşte de la 0 şi ajunge la nr playerilor conectaţi pe server, adică dacă voi aveţi 46 de playeri pe server, i = 46, dacă voi aveţi 600 playeri, i = 600 şi se atribuie la toţi 600 nu doar unuia. În timp ce creşte i la nr max de playeri, adică se verifică playeri conectaţi, apoi creşte, se face într-un timp , pe care noi nu îl vedem , dar el există şi timpul acela, bine înţeles este încărcat cu lag. Aici intervine foreach şi prin simplitate şi pentru că este şi mai rapid, deci simplu pentru că scri aşa: foreach(Player, i) în loc de acel cod mărişor şi include-ul foreach este structurat să fie mai rapid decât loop-ul normal, deci timp de lag scăzut.
Streamer
Streamer este un include, care depinde şi de plugin . Şi cam atât pot să va zic... Glumesc , cu streamer poţi introduce obiecte în joc. Cu funcţia CreateObject poţi introduce doar 1000 de obiecte, deci voi puteţi pune 2000 de obiecte, dar primele 1000 le va citi. Streamer nu are limita şi poate fi configurat că obiectele să se vadă mai de la distanţă, mai de aproape. Q: Bun , dar de ce e limita de 1000 de obiecte? A: Limita respectivă este pentru binele clientului(voi când intraţi pe server sunteţi client, hostul e serverul), deci dacă marea limita era nevoie de resurse de pc, RAM şi alte resurse, deci limita este pentru binele clientului. Streamer nu are nevoie de multe resurse, doar dacă puneţi hărţi stricate, în sens cu multe obiecte într-o zona , ele fiind şi dublicate, poate chiar de mai multe ori, în rest nu produce lag, serverele de stunt au o groază de linii numai cu obiecte, dar nu prea au lag.
Array-uri
Array-ul e ceva de genu:
new string[200];
acesta este array pt că are "[200]". Este un simplu array, el poate fi şi dublu de genu: new PlayerInfo[MAX_PLAYERS][pInfo] sau new număr[100][25]; sau mai mare. Dacă vedeţi, lungimea strîng-ului meu este de 200 de caractere(caracterele însemnând litere, cifre, simboluri sau spaţiul dintre 2 cuvinte). Deci va citi un mesaj de 200 caractere, în caz că va avea mai mult, caracterele în + nu vor fi afişate. De multe ori strîng-urile mari sunt inutile şi consumă biţi. În chat se pot vedea maxim 144 de caractere, deci strîng-ul nostru este mai mare cu 56 de caractere, care mănâncă biţi. Ce va recomand eu, este să faceţi strîng-urile mici, cam de 144 , mai mult nu aveţi nevoie, sau calculaţi în minte câte cuvinte scrieţi, şi îl puteţi face şi mai mic. Dacă e necesar, de exemplu pui comandă /stats pe dialog MSGBOX, da , ai nevoie de strîng mai mare, pentru că te foloseşti de el, dar în rest nu e necesar, şi e recomandabil să îl faci mai mic.
Stilul
Tot acum vreau să va vorbesc despre stilul în care scriptati. Eu personal folosesc tab-ul de multe ori, şi fac economie de new-uri, de genu: new strîng[100], targetid, suma = 0; în loc de new strîng[200]; new targetid; new suma = 0; şi mereu folosesc 2 tab-uri la aliniere de genu:
if(sscanf(params,"ud", playa, money))
return SendClientMessage(playerid, COLOR_GRAD2, "USAGE: /givemoney [playerid/PartOfName] [money]");
sau
if(PlayerInfo[playerid],[pAdmin] < 1)
return SendClientMessage(playerid, COLOR_GRAD2, "Nu poti folosi aceasta comanda!");
Sau alţi folosesc SPACE între caracterele din functi, dar mie personal nu prea îmi place, dar dacă vouă va place e ok. Sau dacă aveţi multe enum-uri de genu:
new engine, lights, alarm, doors, bonnet, boot, objective;
putem face aşa:
new engine,
lights,
alarm,
doors,
bonnet,
boot,
objective;
Sau dialogurile să le aduceţi într-un enum nu în define, puteţi face ceva de genu:
#define DIALOG_LOGIN 1
#define DIALOG_REGISTER 2
#define DIALOG_STATS 3
#define DIALOG_HELP 4
il faceti asa:
enum
{
DIALOG_LOGIN,
DIALOG_REGISTER,
DIALOG_STATS,
DIALOG_HELP
};
Şi iese mult mai frumos. Eu nu sunt fan acoladelor foarte lungi, de exemplu:
CMD:fixveh(playerid,params[])
{
if(IsPlayerConnected(playerid))
{
if(PlayerInfo[playerid][pAdminServer] < 1337)
{
SendClientMessage(playerid, COLOR_GRAD1, " Nu esti autorizat sa folosesti comanda asta!");
return 1;
}
if(IsPlayerInAnyVehicle(playerid))
{
RepairVehicle(GetPlayerVehicleID(playerid));
SendClientMessage(playerid, COLOR_GREY, " Masina a fost reparata !");
}
}
return 1;
}
transformam in:
CMD:fixveh(playerid,params[])
{
if(PlayerInfo[playerid][pAdminServer] < 1337)
return SendClientMessage(playerid, COLOR_GRAD1, " Nu esti autorizat sa folosesti comanda asta!");
if(!IsPlayerInAnyVehicle(playerid))
return SendClientMessage(playerid, COLOR_GRAD1, " Nu esti intr-un vehicul!");
RepairVehicle(GetPlayerVehicleID(playerid));
SendClientMessage(playerid, COLOR_GREY, " Masina a fost reparata !");
return 1;
}
Observaţi că am scăpat de acoladele în exces, când se tastează comandă îşi face verificările, după ce trece de verificări se execută, dacă rămâne la o verificare îi da mesaj.
Observaţi că am scăpat şi de verificarea if(IsPlayerConnected(playerid)) deoarece, cel care tastează comandă este mereu conectat, dar dacă folosim o comandă pe cineva, şi el nu este conectat, trebuie să facem verificarea dar în loc de if(IsPlayerConnected(playerid)) punem if(IsPlayerConnected(playa)) sau în loc de playa cum am definit noi jucătorul.
Cam atât am avut de zis, dacă cunoaşteţi şi alte metode , puteţi să le ziceţi printr-un reply aici.
Q: Mai simple? Cum mai simple?
A: Urmăreşte-mă şi vei află.
În primul rând să discutăm despre optimizare.
Optimizarea este esenţială pentru un GM, adică reduce timpul de execuţie a unei/unor functi.
Q: Bun, şi dacă îl reduce ce?
A: În timpul de executare a unei/unor funcţii lagul va creşte, şansă de crash devine mai mare şi nimeni nu e mulţumit.
Dacă optimizăm, timpul de lag va fi redus substanţial cea ce scade şansă de crash.
Q: Dar lagul acela de ce se produce?
A: Că să înţelegeţi mai bine imaginativă un calculator mai vechi, cu componente slabe de genu: 1 GB ram , placă video 64 , procesor AMD 2.0 GH.
Acum ganditiva că el lucrează. cu cât deschizi mai multe programe cu atât funcţionează din ce în ce mai greu , până se blochează.
Acum imaginativă un calculator mai bun de genu 4GB ram , placă video 1GB, procesor i3 şi punetil să ruleze aceleaşi programe. Cu siguranţă veţi observă diferenţa şi anume că se mişcă mai rapid la acele programe şi nu se mai blochează aşa de repede.
Aşa ceva este şi cu GM-ul. El trebuie să gândească în acelaşi timp ce face fiecare player în parte. Dacă GM nu este optimizat atunci clientul(adică voi) de a se bloca(crash) este mai mare.
Acum că am lămurit aceste aspecte haideţi să discutăm despre cum putem face un GM mai optim şi totodată introducem şi simplitatea.
Mai întâi voi începe cu sistemul de stocare a datelor MYSQL.
MYSQL
Observ că mulţi se plâng că nu mai sunt GM-uri pe ini(dini, yini sau alte derivări ale acestuia).Dacă tot am pomenit de derivările lui ini, pentru cei care nu ştiu sistemul de stocare a datelor ini este cel care crează un fişier .txt în scriptfiles>user(account/conturi/akk/etc). Dini, yini şi mai sunt câteva derivări sunt pentru a face puţină parformantă, adică să fie creat fişierul .txt mai rapid.
Ok , am lămurit şi acest aspect, acum hai să facem diferenţa mai întâi între ini şi mysql.Mai există şi SQLLite, dar habar nu am cu ce se mânca ăla...
Mysql este în momentul actual cel mai rapid şi mai de folos sistem de creare a datelor. Este cel mai avantajos dintre toate, iar conturile sunt într-o deplină siguranţă.
Q: Ok , şi ce treaba are cu siguranţă conturilor?
A: Hai să va zic ce mi să întâmplat mie personal după un restart. Eram pe un server de să-mp, şi numai văd că se da restart la server, eu aveam nivelul 5 , aveam 2.000.000 $ , 2 maşini, totul bine şi frumos , dar după ce să dat restart , mă văd că trb să mă înregistrez din nou, singurul de pe server, m-am înregistrat şi văd că am lvl 1 şi cele 2 maşini, iar ceilalţi nu aveau contul afectat. La mysql nu să întâmplat nici odată această.
Am zis că e şi mai rapid. Da este mult mult mai rapid decât ini , deoarece un cont pe mysql poate fi creat în baza de date într-un interval scurt de timp (0.0001-0.0010 secunde, tastaţi o comandă şi vedeţi timpul de execuţie dacă nu mă credeţi), iar la dini este undeva la 0.1 - 0.9 secunde , poate ajunge dacă este lag pe server chiar şi la 1 - 1.3 - 1.5 secunde.
Personal cred că este şi mai uşor de folosit. La mysql trebuie să fi atent la query-uri, pentru că ele trimit în baza de date informaţiile, în rest conturile se verifică cu if(Rows)- adică dacă se găsesc rânduri la acel cont, la dini de exemplu se verifică cu if(dini_Exists(file)) şi , personal mă bucur că e mai greu de făcut legătură cu baza de date, deoarece nu tot puştiul poate să-şi deschidă server.
Acum să vorbim despre procesoarele de comenzi.
ZCMD(cel mai cunoscut) şi altele
Văd că încă se foloseşte strcmp pe unele GM-uri. STRCMP este extrem de lent. STRCMP este o funcţie ce verifică mesajul din chat.
Adică, uitaţi cum arată o comandă pe strcmp: if (strcmp("/mycommand", cmdtext, true, 10) == 0) - verifică dacă a fost scris /mycomand.
Aici intervine zcmd, care e are 2 avantaje. Aici se poate spune de simplitate, adică e mai simplu să scri CMD:mycomand(playerid,params[]) decât if (strcmp("/mycommand", cmdtext, true, 10) == 0) , clar e mult mai simplu de scris.
Acum , haideţi să va vorbesc de ce strcmp e mult mai lent.
Să zicem că eu am 100 de comenzi pe strcmp. Eu folosesc ultima comandă, adică comandă cu numărul 100. STRCMP verifică 99 de comenzi şi când ajunge la a 100-a se aplică. În timp ce se verifică se produce lag, într-adevăr , lag-ul ăla se nu e vizibil , dar el există.
ZCMD e conceput să fie mai rapid. El foloseşte CallLocalFunction cea ce "se aruncă" direct în comandă şi nu stă să verifice cele 99 de comenzi , cea ce e vizibil mai rapidă comandă la executare.
Acum există nenumărate procesoare de comenzi LIFE-CMD MCMD(cel mai rapid la ora actuală), aceste procesoare au nevoie de plugin, iar în pluginul respectiv, este folosit memory hack, cea ce îl face mult mai rapid decât zcmd, dar e puţin vizibil ochiului că e mai rapid , dar că lag, e redus substanţial.
SSCANF
Când vorbim de sscanf putem spune clar simplitate în folosire. Sscanf este un strtok dar cu mai multe atribuiri şi este mult mult mai rapid în verificare. Am să va dau o comandă care foloseşte strtok să vedeţi şi cum se foloseşte.
CMD:givemoney(playerid,params[])
{
if(IsPlayerConnected(playerid))
{
tmp = strtok(cmdtext, idx);
if(!strlen(tmp))
{
SendClientMessage(playerid, COLOR_GRAD2, "USAGE: /givemoney [playerid/PartOfName] [money]");
return 1;
}
new playa;
new money;
playa = ReturnUser(tmp);
tmp = strtok(cmdtext, idx);
money = strval(tmp);
if (PlayerInfo[playerid][pAdmin] >= 1339)
{
if(IsPlayerConnected(playa))
{
if(playa != INVALID_PLAYER_ID)
{
GivePlayerMoney(playa, money);
}
}
}
else
{
SendClientMessage(playerid, COLOR_GRAD1, "Nu esti autorizat sa folosesti aceasta comanda");
}
}
return 1;
}
Vedeţi voi, în comandă există 2 strtok-uri şi acele strtok-uri se leagă şi de strlen. Strtok-ul , în comandă are atribuţia de a îi pune un parametru, în cazul nostru, la comandă de mai sus, avem 2 parametri şi anume "playerid/PartOfName" şi "money". Ele sunt definite în felul următor cu strtok: tmp = strtok(cmdtext, idx); - face legătură cu money, adică pune că parametru şi money(suma de bani pe care o atribuim) playa = ReturnUser(tmp); - transformă playa în jucător, adică oricare playa este jucător(playa este ţintă, persoană pe care aplicăm comandă) tmp = strtok(cmdtext, idx); - cu strtok îl definim că parametru în comandă money = strval(tmp); - cu strval money este definită că număr. Deci avem nevoie de 4 functi pentru o comandă simplă. Pare inutil să le scri , dar sunt esenţiale şi fără ele nu poţi face comandă corectă, mai ales că trebuie să transformăm definirile în valori playa - jucător, money - suma de bani şi să le facem că parametru. Aici intervine sscanf care e mult mult mai simplu de folosit şi mai rapid, adică noi transformăm definirile în valori şi totodată le facem şi parametri. Putem face în felul următor comandă, în loc să scriem atât o simplificăm şi o şi optimizăm.
CMD:givemoney(playerid,params[])
{
if(IsPlayerConnected(playerid))
{
new playa, money;
if(sscanf(params,"ud", playa, money))
return SendClientMessage(playerid, COLOR_GRAD2, "USAGE: /givemoney [playerid/PartOfName] [money]");
if (PlayerInfo[playerid][pAdmin] >= 1339)
{
if(IsPlayerConnected(playa))
{
if(playa != INVALID_PLAYER_ID)
{
GivePlayerMoneyEx(playa, money);
}
}
}
else
{
SendClientMessage(playerid, COLOR_GRAD1, "Nu esti autorizat sa folosesti aceasta comanda");
}
}
return 1;
}
Acum să analizăm. Noi avem parametri următori, eu vii prezint pe cei mai folosiţi:
s - String(sir de caractere, sau mesaj)
i, d - Integer(sau numar intreg) -> 1, 42, -10
c - Caracter -> a, o, *
l - Logical -> true, false
b - Binary -> 01001, 0b1100
h, x - Hex -> 1A, 0x23
o - Octal -> 045 12
n - Numar -> 42, 0b010, 0xAC, 045
f Float(numar cu virgula sau pozitie) -> 0.7, -99.5
u Username(Nume jucator sau id jucator) -> WiDuAlK(numele), 0(id-ul meu)
Bun şi acum să analizăm situaţia următoare: new playa, money; - eu am definit 2 lucruri: playa - care vreau să fie playerul şi money - care vreau să fie suma de bani pe care o atribui. if(sscanf(params,"ud", playa, money)) sscanf - funcţia (params - vine de la CMD:givemoney(playerid,params[]), dacă folosiţi strcmp, cea ce nu va recomand, în loc de params puneţi "cmdtext" din funcţia if (strcmp("/givemoney", cmdtext, true, 10) == 0) "ud", playa, money - fac 2 chestii 1 definesc valorile : "u" i se atribuie lui playa, "d" i se atribuie lui money, dacă era "ud", money, playa "u" i se atribuia lui money iar "d" lui playa. Deci revenim, această funcţie if(sscanf(params,"ud", playa, money)) este exact că funcţiile menţinute mai sus, adică : playa = ReturnUser(tmp); money = strval(tmp); deci respectivul "u" îl transformă pe playa în jucător, iar respectivul "d" îl transformă pe money în număr întreg. Tot în acelaşi timp, transformă cele acele 2 definiri în condiţi pentru comandă , adică dacă nu scrie /givemoney Widualk/0(id meu) 1000(suma de bani) să îi dea mesaj cu parametri comenzii. Totodată sscanf verifică dacă a scris parametri , nu doar îi transformă, deci if(sscanf(params,"ud", playa, money)) verifică dacă sau scris greşiţi parametri şi îi returnează un mesaj cu ei, sau cu ce vreţi voi. Că o concluzie la sscanf , ea are mai multe atribuţii , e şi simplă şi elegantă şi optimă şi ce vreţi voi. Deci e recomandabil să îl folosiţi la orice GM.
Foreach
Foreach-ul , este că un loop rapid. Loop-ul arată ceva de genu: for(new i = 0; i < MAX_PLAYERS; i++) , adică i să fie egal cu toţi jucători, adică să atribuie o funcţie tuturor jucătorilor. de genu:
for(new i = 0; i < MAX_PLAYERS; i++)
{
GivePlayerMoney(i,100);
}
sau
for(new i = 0; i < MAX_PLAYERS; i++)
{
GivePlayerWeapon(i,46(id arma),1(nr de munitii/gloante));
}
Acest "i" creşte de la 0 şi ajunge la nr playerilor conectaţi pe server, adică dacă voi aveţi 46 de playeri pe server, i = 46, dacă voi aveţi 600 playeri, i = 600 şi se atribuie la toţi 600 nu doar unuia. În timp ce creşte i la nr max de playeri, adică se verifică playeri conectaţi, apoi creşte, se face într-un timp , pe care noi nu îl vedem , dar el există şi timpul acela, bine înţeles este încărcat cu lag. Aici intervine foreach şi prin simplitate şi pentru că este şi mai rapid, deci simplu pentru că scri aşa: foreach(Player, i) în loc de acel cod mărişor şi include-ul foreach este structurat să fie mai rapid decât loop-ul normal, deci timp de lag scăzut.
Streamer
Streamer este un include, care depinde şi de plugin . Şi cam atât pot să va zic... Glumesc , cu streamer poţi introduce obiecte în joc. Cu funcţia CreateObject poţi introduce doar 1000 de obiecte, deci voi puteţi pune 2000 de obiecte, dar primele 1000 le va citi. Streamer nu are limita şi poate fi configurat că obiectele să se vadă mai de la distanţă, mai de aproape. Q: Bun , dar de ce e limita de 1000 de obiecte? A: Limita respectivă este pentru binele clientului(voi când intraţi pe server sunteţi client, hostul e serverul), deci dacă marea limita era nevoie de resurse de pc, RAM şi alte resurse, deci limita este pentru binele clientului. Streamer nu are nevoie de multe resurse, doar dacă puneţi hărţi stricate, în sens cu multe obiecte într-o zona , ele fiind şi dublicate, poate chiar de mai multe ori, în rest nu produce lag, serverele de stunt au o groază de linii numai cu obiecte, dar nu prea au lag.
Array-uri
Array-ul e ceva de genu:
new string[200];
acesta este array pt că are "[200]". Este un simplu array, el poate fi şi dublu de genu: new PlayerInfo[MAX_PLAYERS][pInfo] sau new număr[100][25]; sau mai mare. Dacă vedeţi, lungimea strîng-ului meu este de 200 de caractere(caracterele însemnând litere, cifre, simboluri sau spaţiul dintre 2 cuvinte). Deci va citi un mesaj de 200 caractere, în caz că va avea mai mult, caracterele în + nu vor fi afişate. De multe ori strîng-urile mari sunt inutile şi consumă biţi. În chat se pot vedea maxim 144 de caractere, deci strîng-ul nostru este mai mare cu 56 de caractere, care mănâncă biţi. Ce va recomand eu, este să faceţi strîng-urile mici, cam de 144 , mai mult nu aveţi nevoie, sau calculaţi în minte câte cuvinte scrieţi, şi îl puteţi face şi mai mic. Dacă e necesar, de exemplu pui comandă /stats pe dialog MSGBOX, da , ai nevoie de strîng mai mare, pentru că te foloseşti de el, dar în rest nu e necesar, şi e recomandabil să îl faci mai mic.
Stilul
Tot acum vreau să va vorbesc despre stilul în care scriptati. Eu personal folosesc tab-ul de multe ori, şi fac economie de new-uri, de genu: new strîng[100], targetid, suma = 0; în loc de new strîng[200]; new targetid; new suma = 0; şi mereu folosesc 2 tab-uri la aliniere de genu:
if(sscanf(params,"ud", playa, money))
return SendClientMessage(playerid, COLOR_GRAD2, "USAGE: /givemoney [playerid/PartOfName] [money]");
sau
if(PlayerInfo[playerid],[pAdmin] < 1)
return SendClientMessage(playerid, COLOR_GRAD2, "Nu poti folosi aceasta comanda!");
Sau alţi folosesc SPACE între caracterele din functi, dar mie personal nu prea îmi place, dar dacă vouă va place e ok. Sau dacă aveţi multe enum-uri de genu:
new engine, lights, alarm, doors, bonnet, boot, objective;
putem face aşa:
new engine,
lights,
alarm,
doors,
bonnet,
boot,
objective;
Sau dialogurile să le aduceţi într-un enum nu în define, puteţi face ceva de genu:
#define DIALOG_LOGIN 1
#define DIALOG_REGISTER 2
#define DIALOG_STATS 3
#define DIALOG_HELP 4
il faceti asa:
enum
{
DIALOG_LOGIN,
DIALOG_REGISTER,
DIALOG_STATS,
DIALOG_HELP
};
Şi iese mult mai frumos. Eu nu sunt fan acoladelor foarte lungi, de exemplu:
CMD:fixveh(playerid,params[])
{
if(IsPlayerConnected(playerid))
{
if(PlayerInfo[playerid][pAdminServer] < 1337)
{
SendClientMessage(playerid, COLOR_GRAD1, " Nu esti autorizat sa folosesti comanda asta!");
return 1;
}
if(IsPlayerInAnyVehicle(playerid))
{
RepairVehicle(GetPlayerVehicleID(playerid));
SendClientMessage(playerid, COLOR_GREY, " Masina a fost reparata !");
}
}
return 1;
}
transformam in:
CMD:fixveh(playerid,params[])
{
if(PlayerInfo[playerid][pAdminServer] < 1337)
return SendClientMessage(playerid, COLOR_GRAD1, " Nu esti autorizat sa folosesti comanda asta!");
if(!IsPlayerInAnyVehicle(playerid))
return SendClientMessage(playerid, COLOR_GRAD1, " Nu esti intr-un vehicul!");
RepairVehicle(GetPlayerVehicleID(playerid));
SendClientMessage(playerid, COLOR_GREY, " Masina a fost reparata !");
return 1;
}
Observaţi că am scăpat de acoladele în exces, când se tastează comandă îşi face verificările, după ce trece de verificări se execută, dacă rămâne la o verificare îi da mesaj.
Observaţi că am scăpat şi de verificarea if(IsPlayerConnected(playerid)) deoarece, cel care tastează comandă este mereu conectat, dar dacă folosim o comandă pe cineva, şi el nu este conectat, trebuie să facem verificarea dar în loc de if(IsPlayerConnected(playerid)) punem if(IsPlayerConnected(playa)) sau în loc de playa cum am definit noi jucătorul.
Cam atât am avut de zis, dacă cunoaşteţi şi alte metode , puteţi să le ziceţi printr-un reply aici.
Re: Optimizare, simplitate şi stil
8/8/2020, 18:48
OPTIMIZÁRE, optimizări, s. f. 1. Alegerea și aplicarea soluției (economice) optime (dintre mai multe posibile). 2. (Mat.) Raționament sau calcul care permite găsirea valorilor unuia sau mai multor parametri corespunzând maximului unei funcții. – Cf. fr. optimiser, optimisation.
In sa-mp optimizarea este procesul prin care faci un cod sa fie mai rapid la executare.
Am facut niste teste:
1) Variabila normala este mai rapida decat array.
Sa zicem ca avem nevoie de 3 variabile de pozitie pentru GetPlayerPos, sunt 2 cazuri:
fie definim un array: new Float:Pos[3]; GetPlayerPos(playerid, Pos[0], Pos[1], Pos[2]);
fie definim 3 variabile: new Float:PosX, Float:PosY, Float:PosZ; GetPlayerPos(playerid, PosX, PosY, PosZ);
La prima vedere, e mai simplu sa ne folosim de array(cel putin asa am crezut eu), un mic test pe care l-am facut foarte recent legat de viteza array si viteza variabilei normale este:
[21:32:49] Speed Test NORMAL VARIABLE 31550
[21:34:07] Speed Test ARRAY TEST 77967
[21:34:31] Speed Test NORMAL VARIABLE 24034
[21:35:11] Speed Test ARRAY TEST 39904
[21:35:35] Speed Test NORMAL VARIABLE 24056
[21:36:15] Speed Test ARRAY TEST 39867
[21:36:39] Speed Test NORMAL VARIABLE 24163
[21:37:14] Speed Test ARRAY TEST 35011
[21:37:36] Speed Test NORMAL VARIABLE 22375
[21:38:13] Speed Test ARRAY TEST 36687
Concluzie: Array este mai lent decat variabila normala.
2) SWITCH este mai rapid decat if(ceva = altceva)
O sa dau cateva exemple:
Sa presupunem ca avem nevoie sa ne folosim de OnDialogResponse:
enum
{
Dialog1,
Dialog2
};
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
return 1;
}
putem accesa cele 2 dialoguri in felul urmator:
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
if(dialogid == Dialog1)
{
}
if(dialogid == Dialog2)
{
}
return 1;
}
sau
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
switch(dialogid)
{
case Dialog1:
{
}
case Dialog2:
{
}
}
return 1;
}
putem accesa in acest fel si lista dialogurilor de la tipul: DIALOG_STYLE_LIST
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
switch(dialogid)
{
case Dialog1:
{
switch(listitem)
{
}
}
case Dialog2:
{
switch(listitem)
{
}
}
}
return 1;
}
tot in acest fel putem accesa si butonul selectat:
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
switch(dialogid)
{
case Dialog1:
{
switch(response)
{
switch(listitem)
{
}
}
}
case Dialog2:
{
switch(response)
{
switch(listitem)
{
}
}
}
}
return 1;
}
Nu doar OnDialogResponse poate fi accesat asa:
varianta 1:
forward Functie(parametru, tip)
public Functie(parametru, tip)
{
if(tip == ceva)
{
}
if(tip == ceva2)
{
}
return 1;
}
varianta 2:
forward Functie(parametru, tip)
public Functie(parametru, tip)
{
switch(tip)
{
}
return 1;
}
Am testat diferenta intre switch si if(ceva == altceva)
Rezultatele testelor mele sunt:
[21:59:24] Speed Test if(i = ceva) 7713
[21:59:27] Speed Test switch 2537
[21:59:34] Speed Test if(i = ceva) 7475
[21:59:37] Speed Test switch 2430
[21:59:44] Speed Test if(i = ceva) 7471
[21:59:47] Speed Test switch 2431
[21:59:54] Speed Test if(i = ceva) 7558
[21:59:57] Speed Test switch 2423
[22:00:05] Speed Test if(i = ceva) 8645
[22:00:09] Speed Test switch 3683
CONCLUZIE: SWITCH ESTE MAI RAPID DECAT IF(CEVA == ALTCEVA)
3)SetPVarInt vs variabila normala
Am vorbit cu stuntman candva si imi spuse ca poti optimiza scriptul cu SetPVarInt/GetPVarInt
Am testat si teoria lui, iar rezultatul testelor mi-a dat:
[22:17:11] SetPVarInt TEST : 4743
[22:17:15] normal variabile TEST : 4119
[22:17:19] SetPVarInt TEST : 4078
[22:17:22] normal variabile TEST : 3282
[22:17:26] SetPVarInt TEST : 3937
[22:17:29] normal variabile TEST : 3065
[22:17:33] SetPVarInt TEST : 3643
[22:17:36] normal variabile TEST : 2869
[22:17:40] SetPVarInt TEST : 4734
[22:17:44] normal variabile TEST : 3464
[22:17:47] SetPVarInt TEST : 3545
[22:17:50] normal variabile TEST : 2708
[22:17:55] SetPVarInt TEST : 4792
[22:17:59] normal variabile TEST : 4543
Am testat si marimea fisierului, iar SetPVarInt stocheaza mai multa memorie decat variabila definita cu new.
4)ENUM VS [Trebuie sa fiti inscris si conectat pentru a vedea acest link]
Am testat si cele 2 functii ale limbajului pawn:
[23:11:19] Timp scurs(enum): 2086
[23:11:21] Timp scurs(define): 1808
[23:11:23] Timp scurs(enum): 2050
[23:11:25] Timp scurs(define): 1937
[23:11:27] Timp scurs(enum): 1953
[23:11:29] Timp scurs(define): 1868
[23:11:31] Timp scurs(enum): 2034
[23:11:33] Timp scurs(define): 1837
[23:11:35] Timp scurs(enum): 2150
[23:11:37] Timp scurs(define): 1937
Desi define este mai rapid putin decat enum, recomandat pentru dialoguri este enum pentru a nu se incurca dialogurile intre ele.
5)Diferenta intre small si large array
Am testat si diferentele intre 2 array-uri, unul de 2000 si unul de 200:
new array[2000]; vs new array[200];
Timpul de executie pentru cele 2 array-uri:
[23:14:50] Timp scurs(array large): 3254
[23:14:51] Timp scurs(array small): 616
[23:14:54] Timp scurs(array large): 3469
[23:14:55] Timp scurs(array small): 876
[23:14:59] Timp scurs(array large): 3856
[23:15:00] Timp scurs(array small): 746
[23:15:12] Timp scurs(array large): 12562
[23:15:15] Timp scurs(array small): 3190
[23:15:38] Timp scurs(array large): 22416
[23:15:43] Timp scurs(array small): 5344
Pe langa timpul scurs, array large(cel de 2000) are marimea mai mare decat array small(array 200).
Am testat si for vs while, si dupa ce le-am comparat dar dupa ce le-am comparat, am vazut ca variaza timpul intre cele 2, si pe rand timpul pentru for devine mai mare si mai mic decat cel al lui while, deci sunt instabile, si cam egale ca viteza.
Am adus dovezi concrete legate de optimizare.
Nu am reusit sa compar iteratia facuta cu foreach si loop-ul normal facut de for, dar din cate am inteles foreach e mai rapid decat for.
Acestea fiind spuse, sper ca am mai lamurit, daca aveti intrebari sau vreti sa compar ceva dati reply iar eu voi face cu mare placere.
In sa-mp optimizarea este procesul prin care faci un cod sa fie mai rapid la executare.
Am facut niste teste:
1) Variabila normala este mai rapida decat array.
Sa zicem ca avem nevoie de 3 variabile de pozitie pentru GetPlayerPos, sunt 2 cazuri:
fie definim un array: new Float:Pos[3]; GetPlayerPos(playerid, Pos[0], Pos[1], Pos[2]);
fie definim 3 variabile: new Float:PosX, Float:PosY, Float:PosZ; GetPlayerPos(playerid, PosX, PosY, PosZ);
La prima vedere, e mai simplu sa ne folosim de array(cel putin asa am crezut eu), un mic test pe care l-am facut foarte recent legat de viteza array si viteza variabilei normale este:
[21:32:49] Speed Test NORMAL VARIABLE 31550
[21:34:07] Speed Test ARRAY TEST 77967
[21:34:31] Speed Test NORMAL VARIABLE 24034
[21:35:11] Speed Test ARRAY TEST 39904
[21:35:35] Speed Test NORMAL VARIABLE 24056
[21:36:15] Speed Test ARRAY TEST 39867
[21:36:39] Speed Test NORMAL VARIABLE 24163
[21:37:14] Speed Test ARRAY TEST 35011
[21:37:36] Speed Test NORMAL VARIABLE 22375
[21:38:13] Speed Test ARRAY TEST 36687
Concluzie: Array este mai lent decat variabila normala.
2) SWITCH este mai rapid decat if(ceva = altceva)
O sa dau cateva exemple:
Sa presupunem ca avem nevoie sa ne folosim de OnDialogResponse:
enum
{
Dialog1,
Dialog2
};
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
return 1;
}
putem accesa cele 2 dialoguri in felul urmator:
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
if(dialogid == Dialog1)
{
}
if(dialogid == Dialog2)
{
}
return 1;
}
sau
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
switch(dialogid)
{
case Dialog1:
{
}
case Dialog2:
{
}
}
return 1;
}
putem accesa in acest fel si lista dialogurilor de la tipul: DIALOG_STYLE_LIST
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
switch(dialogid)
{
case Dialog1:
{
switch(listitem)
{
}
}
case Dialog2:
{
switch(listitem)
{
}
}
}
return 1;
}
tot in acest fel putem accesa si butonul selectat:
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
switch(dialogid)
{
case Dialog1:
{
switch(response)
{
switch(listitem)
{
}
}
}
case Dialog2:
{
switch(response)
{
switch(listitem)
{
}
}
}
}
return 1;
}
Nu doar OnDialogResponse poate fi accesat asa:
varianta 1:
forward Functie(parametru, tip)
public Functie(parametru, tip)
{
if(tip == ceva)
{
}
if(tip == ceva2)
{
}
return 1;
}
varianta 2:
forward Functie(parametru, tip)
public Functie(parametru, tip)
{
switch(tip)
{
}
return 1;
}
Am testat diferenta intre switch si if(ceva == altceva)
Rezultatele testelor mele sunt:
[21:59:24] Speed Test if(i = ceva) 7713
[21:59:27] Speed Test switch 2537
[21:59:34] Speed Test if(i = ceva) 7475
[21:59:37] Speed Test switch 2430
[21:59:44] Speed Test if(i = ceva) 7471
[21:59:47] Speed Test switch 2431
[21:59:54] Speed Test if(i = ceva) 7558
[21:59:57] Speed Test switch 2423
[22:00:05] Speed Test if(i = ceva) 8645
[22:00:09] Speed Test switch 3683
CONCLUZIE: SWITCH ESTE MAI RAPID DECAT IF(CEVA == ALTCEVA)
3)SetPVarInt vs variabila normala
Am vorbit cu stuntman candva si imi spuse ca poti optimiza scriptul cu SetPVarInt/GetPVarInt
Am testat si teoria lui, iar rezultatul testelor mi-a dat:
[22:17:11] SetPVarInt TEST : 4743
[22:17:15] normal variabile TEST : 4119
[22:17:19] SetPVarInt TEST : 4078
[22:17:22] normal variabile TEST : 3282
[22:17:26] SetPVarInt TEST : 3937
[22:17:29] normal variabile TEST : 3065
[22:17:33] SetPVarInt TEST : 3643
[22:17:36] normal variabile TEST : 2869
[22:17:40] SetPVarInt TEST : 4734
[22:17:44] normal variabile TEST : 3464
[22:17:47] SetPVarInt TEST : 3545
[22:17:50] normal variabile TEST : 2708
[22:17:55] SetPVarInt TEST : 4792
[22:17:59] normal variabile TEST : 4543
Am testat si marimea fisierului, iar SetPVarInt stocheaza mai multa memorie decat variabila definita cu new.
4)ENUM VS [Trebuie sa fiti inscris si conectat pentru a vedea acest link]
Am testat si cele 2 functii ale limbajului pawn:
[23:11:19] Timp scurs(enum): 2086
[23:11:21] Timp scurs(define): 1808
[23:11:23] Timp scurs(enum): 2050
[23:11:25] Timp scurs(define): 1937
[23:11:27] Timp scurs(enum): 1953
[23:11:29] Timp scurs(define): 1868
[23:11:31] Timp scurs(enum): 2034
[23:11:33] Timp scurs(define): 1837
[23:11:35] Timp scurs(enum): 2150
[23:11:37] Timp scurs(define): 1937
Desi define este mai rapid putin decat enum, recomandat pentru dialoguri este enum pentru a nu se incurca dialogurile intre ele.
5)Diferenta intre small si large array
Am testat si diferentele intre 2 array-uri, unul de 2000 si unul de 200:
new array[2000]; vs new array[200];
Timpul de executie pentru cele 2 array-uri:
[23:14:50] Timp scurs(array large): 3254
[23:14:51] Timp scurs(array small): 616
[23:14:54] Timp scurs(array large): 3469
[23:14:55] Timp scurs(array small): 876
[23:14:59] Timp scurs(array large): 3856
[23:15:00] Timp scurs(array small): 746
[23:15:12] Timp scurs(array large): 12562
[23:15:15] Timp scurs(array small): 3190
[23:15:38] Timp scurs(array large): 22416
[23:15:43] Timp scurs(array small): 5344
Pe langa timpul scurs, array large(cel de 2000) are marimea mai mare decat array small(array 200).
Am testat si for vs while, si dupa ce le-am comparat dar dupa ce le-am comparat, am vazut ca variaza timpul intre cele 2, si pe rand timpul pentru for devine mai mare si mai mic decat cel al lui while, deci sunt instabile, si cam egale ca viteza.
Am adus dovezi concrete legate de optimizare.
Nu am reusit sa compar iteratia facuta cu foreach si loop-ul normal facut de for, dar din cate am inteles foreach e mai rapid decat for.
Acestea fiind spuse, sper ca am mai lamurit, daca aveti intrebari sau vreti sa compar ceva dati reply iar eu voi face cu mare placere.
Re: Optimizare, simplitate şi stil
8/8/2020, 18:50
Dar tot odata si alti utilizatori vor afla de la altii ce ei nu stiu.
Sa folosesti
mysql
Alt procesor de comenzi
Sscanf
Foreach-ul
Streamer
Array-urile sa fie cat mai mici
Sunt cateva din ele .
Sa folosesti
mysql
Alt procesor de comenzi
Sscanf
Foreach-ul
Streamer
Array-urile sa fie cat mai mici
Sunt cateva din ele .
Permisiunile acestui forum:
Nu puteti raspunde la subiectele acestui forum