PDA

Просмотр полной версии : [Вопрос] Использование стандартных функций



Elaid
10.11.2014, 01:31
Приветствую тебя, мой раб, у меня вопрос "Какое преимущество дает в использовании стандартный функций"
Я слышал о том, что в использование стандартный функций отражается только на скорости и нагрузке. Бывают ли такие случаи, что стандарты не всегда быстрее? Как мне понят где лучше использовать стандарты, а где нет?

DeimoS
10.11.2014, 02:54
Всё зависит от того, как написана сторонняя функция :) Если брать в пример какой-нибудь PlayerToPoint и IsPlayerInRangeOfPoint, то нативная (стандартная) функция быстрее, ибо первая реализована не очень. Но бывают случаи, когда сторонние функции работают в разы быстрее (стандартные функции ведь тоже люди писали. И писали их когда-то. За тот момент могли придумать какие-то новые реализации).
Один из примеров: функция strlen и макрос isnull.
Макрос выглядит так:

#define isnull(%1) ((!(%1[0])) || (((%1[0]) == '\1') && (!(%1[1]))))
и скорость тут достигается тем, что в макросе сразу идёт проверка первой ячейки на нуль-символ (ели в первой ячейке записан нуль-символ, значит в массиве нет текста), а функцию надо ещё вызвать и только потом она проведёт какие-то действия внутри себя и вернёт результат.
Сюда же можно приписать и командные процессоры, в которых поиск команд реализован лучше, что повышает скорость, нежели постоянный вызов strcmp.
В общем, всё зависит от конкретной ситуации и знаний того, как реализована нативная функция (иначе придётся методом тыка писать код и тестировать).

А проверить можно циклом на over1000000 итераций + записью значения GetTickCount до запуска цикла и "GetTickCount() - записанное значение" после выполнения цикла (полученное значение выводим в логи). Вот тут (http://pro-pawn.ru/showthread.php?10626-%D0%9F%D1%80%D0%BE%D0%B2%D0%B5%D1%80%D0%BA%D0%B0-%D0%BD%D0%B0-AFK%28%D0%A1%D0%B2%D1%91%D1%80%D0%BD%D1%83%D1%82%D0%BE-%D0%BB%D0%B8-%D0%BE%D0%BA%D0%BE%D1%88%D0%BA%D0%BE-SA%29&p=52013&viewfull=1#post52013) Стас давал готовый код хорошего теста. Просто в циклы "for(j=0; j<PROFILE_ITERS_MINOR; ++j)" нужно будет вставить свой код

DeimoS
10.11.2014, 03:31
Я написал вот такую функцию для своего удобства

stock TestFunction()
{
#define NUMBER_TICKS 5
#define NUMBER_TESTS 10
#define NUMBER_ITERATIONS 1000000
new ticks[NUMBER_TICKS],
tmp_ticks,
p, i, j, k;

printf("\n------------------------------------------------------------\nTesting...\nЧисло итераций в основном цикле - %d\nЧисло повторений теста - %d\n\n", NUMBER_ITERATIONS, NUMBER_TESTS);
for(p = 0; p < NUMBER_TESTS; p++)
{
for(k = 0; k < NUMBER_TICKS; k++) ticks[k] = 0;
for(i = 0; i < NUMBER_ITERATIONS; ++i)
{
//===================================
tmp_ticks = GetTickCount();
for(j = 0; j < 100; ++j)
{
//Тут код первой функции
}
ticks[0] += GetTickCount()-tmp_ticks;
//===================================
//===================================
tmp_ticks = GetTickCount();
for(j = 0; j < 100; ++j)
{
//Тут код второй функции
}
ticks[1] += GetTickCount()-tmp_ticks;
//===================================
}
printf("Тест №:%d", p+1);
printf("Первая функция: %d", ticks[0]);
printf("Вторая функция: %d", ticks[1]);
print("\n");
}
print("\n------------------------------------------------------------\n");
}


stock TestFunction()
{
#define NUMBER_TICKS 2// Тут указывается число теструемых функций. То есть, если ты собираешься тестировать 10 функций одновременно, тут указываешь число 10
#define NUMBER_TESTS 10// Тут указывается сколько раз повторять наш тест.
#define NUMBER_ITERATIONS 1000000// Ну а тут указывается число итераций для основного цикла, который будет крутить циклы с тестируемыми функциями. Если тест длится очень долго, можно указать и меньшее значение. Предыдущий макрос, в котором указывается число повторений теста, создан именно для того, чтоб сделать тест более объективным.
new ticks[NUMBER_TICKS],// Переменные, которые будем использовать в ходе теста.
tmp_ticks,// Дабы тест был максимально объективен, создание всех переменных вынесли за тело теста (циклов)
p, i, j, k;// Таким образом время, которое бы тратилось на создание этих переменных, не учитывается

printf("\n------------------------------------------------------------\nTesting...\nЧисло итераций в основном цикле - %d\nЧисло повторений теста - %d\n\n", NUMBER_ITERATIONS, NUMBER_TESTS);
for(p = 0; p < NUMBER_TESTS; p++)// Первый цикл, который отвечает за повтор всего теста
{
for(k = 0; k < NUMBER_TICKS; k++) ticks[k] = 0;// Этот цикл обнуляет таймера для каждого нового теста
for(i = 0; i < NUMBER_ITERATIONS; ++i)// Ну а этот цикл уже является тем, что отвечает за сам тест
{// Далее выделены блоки, которые являются чем-то вроде отдельного куска теста. Если тестировать надо больше двух функций, просто скопируй любой блок, замени код внутри цикла и измени значение ticks в последней строке на +1 (дабы записывалось в новую ячейку, а не перезаписывало старую)
//===================================
tmp_ticks = GetTickCount();
for(j = 0; j < 100; ++j)
{
//Тут код первой функции
}
ticks[0] += GetTickCount()-tmp_ticks;
//===================================
//===================================
tmp_ticks = GetTickCount();
for(j = 0; j < 100; ++j)
{
//Тут код второй функции
}
ticks[1] += GetTickCount()-tmp_ticks;
//===================================
}
printf("Тест №:%d", p+1);
printf("Первая функция: %d", ticks[0]);// Ну и при логировании значений не забывай прописывать правильные номера ячеек
printf("Вторая функция: %d", ticks[1]);
print("\n");
}
print("\n------------------------------------------------------------\n");
}


Вот пример теста IsPlayerInRangeOfPoint и PlayerToPoint

main()
{
TestFunction();
}

stock TestFunction()
{
#define NUMBER_TICKS 2
#define NUMBER_TESTS 10
#define NUMBER_ITERATIONS 10
new ticks[NUMBER_TICKS],
tmp_ticks,
p, i, j, t, k;

printf("\n------------------------------------------------------------\nTesting...\nЧисло итераций в основном цикле - %d\nЧисло повторений теста - %d\n\n", NUMBER_ITERATIONS, NUMBER_TESTS);
for(p = 0; p < NUMBER_TESTS; p++)
{
for(k = 0; k < NUMBER_TICKS; k++) ticks[k] = 0;
for(i = 0; i < NUMBER_ITERATIONS; ++i)
{
tmp_ticks = GetTickCount();
for(j = 0; j < 100; ++j)
{
for(t = 0; t < MAX_PLAYERS; t++) IsPlayerInRangeOfPoint(t, 20, 0, 0, 0);
}
ticks[0] += GetTickCount()-tmp_ticks;
tmp_ticks = GetTickCount();
for(j = 0; j < 100; ++j)
{
for(t = 0; t < MAX_PLAYERS; t++) PlayerToPoint(20, t, 0, 0, 0);
}
ticks[1] += GetTickCount()-tmp_ticks;
}
printf("Тест №:%d", p+1);
printf("IsPlayerInRangeOfPoint: %d", ticks[0]);
printf("PlayerToPoint: %d", ticks[1]);
print("\n");
}
print("\n------------------------------------------------------------\n");
}


stock PlayerToPoint(Float:radi, playerid, Float:x, Float:y, Float:z)
{
if(IsPlayerConnected(playerid))
{
new Float:oldposx, Float:oldposy, Float:oldposz;
new Float:tempposx, Float:tempposy, Float:tempposz;
GetPlayerPos(playerid, oldposx, oldposy, oldposz);
tempposx = (oldposx -x);
tempposy = (oldposy -y);
tempposz = (oldposz -z);
if (((tempposx < radi) && (tempposx > -radi)) && ((tempposy < radi) && (tempposy > -radi)) && ((tempposz < radi) && (tempposz > -radi)))
{
return 1;
}
}
return 0;
}

Тут я сделал 10 итераций для основного цикла потому, что внутри каждого блока запускается новый цикл на 500 итераций (MAX_PLAYERS == 500) и 500 миллионов итераций ждать придётся несколько минут :) Можно делать несколько тестов, меняя значение NUMBER_ITERATIONS, если хочешь на 100% удостовериться в том, что данные верны. В случае с данным тестом, если поставить больше 10, время будет относительно одинаковым.


[06:30:16] ------------------------------------------------------------
Testing...
Число итераций в основном цикле - 10
Число повторений теста - 10


[06:30:18] Тест №:1
[06:30:18] IsPlayerInRangeOfPoint: 987
[06:30:18] PlayerToPoint: 1000
[06:30:18]

[06:30:20] Тест №:2
[06:30:20] IsPlayerInRangeOfPoint: 905
[06:30:20] PlayerToPoint: 945
[06:30:20]

[06:30:21] Тест №:3
[06:30:21] IsPlayerInRangeOfPoint: 904
[06:30:21] PlayerToPoint: 947
[06:30:21]

[06:30:23] Тест №:4
[06:30:23] IsPlayerInRangeOfPoint: 901
[06:30:23] PlayerToPoint: 960
[06:30:23]

[06:30:25] Тест №:5
[06:30:25] IsPlayerInRangeOfPoint: 909
[06:30:25] PlayerToPoint: 952
[06:30:25]

[06:30:27] Тест №:6
[06:30:27] IsPlayerInRangeOfPoint: 905
[06:30:27] PlayerToPoint: 965
[06:30:27]

[06:30:29] Тест №:7
[06:30:29] IsPlayerInRangeOfPoint: 955
[06:30:29] PlayerToPoint: 996
[06:30:29]

[06:30:31] Тест №:8
[06:30:31] IsPlayerInRangeOfPoint: 963
[06:30:31] PlayerToPoint: 1008
[06:30:31]

[06:30:33] Тест №:9
[06:30:33] IsPlayerInRangeOfPoint: 995
[06:30:33] PlayerToPoint: 1030
[06:30:33]

[06:30:35] Тест №:10
[06:30:35] IsPlayerInRangeOfPoint: 954
[06:30:35] PlayerToPoint: 1006
[06:30:35]

[06:30:35] ------------------------------------------------------------