SA-MP Forums

SA-MP Forums (http://forum.sa-mp.com/index.php)
-   Русский/Russian (http://forum.sa-mp.com/forumdisplay.php?f=32)
-   -   Написание плагинов (http://forum.sa-mp.com/showthread.php?t=628672)

Diman777 13/02/2017 01:51 AM

Написание плагинов
 
Многие пишут, что через плагин всё быстрее работает (с условием если грамотно и со смыслом их писать).
Решил попробывать написать свой 1-ый плагин, в котором пока что есть 1 функция UpperToLower, она переводит строку в нижний регистр.
Результат тестирования скорости поражает.

код C++:
PHP Code:

// native UpperToLower(string[]);
static cell AMX_NATIVE_CALL UpperToLower(AMX *amxcell *params)
{
    
char *string;
    
int len 0;
    
amx_StrParam(amxparams[1], string);
    if (
string != NULL)
    {
        
len strlen(string);
        for (
int i 0leni++)
        {
            switch (
string[i])
            {
                case 
'A'string[i] = 'a'; break;
                case 
'B'string[i] = 'b'; break;
                case 
'C'string[i] = 'c'; break;
                case 
'D'string[i] = 'd'; break;
                case 
'E'string[i] = 'e'; break;
                case 
'F'string[i] = 'f'; break;
                case 
'G'string[i] = 'g'; break;
                case 
'H'string[i] = 'h'; break;
                case 
'I'string[i] = 'i'; break;
                case 
'J'string[i] = 'j'; break;
                case 
'K'string[i] = 'k'; break;
                case 
'L'string[i] = 'l'; break;
                case 
'M'string[i] = 'm'; break;
                case 
'N'string[i] = 'n'; break;
                case 
'O'string[i] = 'o'; break;
                case 
'P'string[i] = 'p'; break;
                case 
'Q'string[i] = 'q'; break;
                case 
'R'string[i] = 'r'; break;
                case 
'S'string[i] = 's'; break;
                case 
'T'string[i] = 't'; break;
                case 
'U'string[i] = 'u'; break;
                case 
'V'string[i] = 'v'; break;
                case 
'W'string[i] = 'w'; break;
                case 
'X'string[i] = 'x'; break;
                case 
'Y'string[i] = 'y'; break;
                case 
'Z'string[i] = 'z'; break;
                case 
'А'string[i] = 'а'; break;
                case 
'Б'string[i] = 'б'; break;
                case 
'В'string[i] = 'в'; break;
                case 
'Г'string[i] = 'г'; break;
                case 
'Д'string[i] = 'д'; break;
                case 
'Е'string[i] = 'е'; break;
                case 
'Ё'string[i] = 'ё'; break;
                case 
'Ж'string[i] = 'ж'; break;
                case 
'З'string[i] = 'з'; break;
                case 
'И'string[i] = 'и'; break;
                case 
'Й'string[i] = 'й'; break;
                case 
'К'string[i] = 'к'; break;
                case 
'Л'string[i] = 'л'; break;
                case 
'М'string[i] = 'м'; break;
                case 
'Н'string[i] = 'н'; break;
                case 
'О'string[i] = 'о'; break;
                case 
'П'string[i] = 'п'; break;
                case 
'Р'string[i] = 'р'; break;
                case 
'С'string[i] = 'с'; break;
                case 
'Т'string[i] = 'т'; break;
                case 
'У'string[i] = 'у'; break;
                case 
'Ф'string[i] = 'ф'; break;
                case 
'Х'string[i] = 'х'; break;
                case 
'Ц'string[i] = 'ц'; break;
                case 
'Ч'string[i] = 'ч'; break;
                case 
'Ш'string[i] = 'ш'; break;
                case 
'Щ'string[i] = 'щ'; break;
                case 
'Ъ'string[i] = 'ъ'; break;
                case 
'Ы'string[i] = 'ы'; break;
                case 
'Ь'string[i] = 'ь'; break;
                case 
'Э'string[i] = 'э'; break;
                case 
'Ю'string[i] = 'ю'; break;
                case 
'Я'string[i] = 'я'; break;
            }
        }
        
string[len] = '\0';
    }
    else
    {
        
string "";
    }
    
cell *addr NULL;
    
amx_GetAddr(amxparams[1], &addr);
    
amx_SetString(addrstring00len+1);
    return 
1;


код Pawn:
PHP Code:

UpperToLower(string[])
{
    new 
len strlen(string);
    for (new 
ileni++)
    {
        switch (
string[i])
        {
            case 
'A'string[i] = 'a';
            case 
'B'string[i] = 'b';
            case 
'C'string[i] = 'c';
            case 
'D'string[i] = 'd';
            case 
'E'string[i] = 'e';
            case 
'F'string[i] = 'f';
            case 
'G'string[i] = 'g';
            case 
'H'string[i] = 'h';
            case 
'I'string[i] = 'i';
            case 
'J'string[i] = 'j';
            case 
'K'string[i] = 'k';
            case 
'L'string[i] = 'l';
            case 
'M'string[i] = 'm';
            case 
'N'string[i] = 'n';
            case 
'O'string[i] = 'o';
            case 
'P'string[i] = 'p';
            case 
'Q'string[i] = 'q';
            case 
'R'string[i] = 'r';
            case 
'S'string[i] = 's';
            case 
'T'string[i] = 't';
            case 
'U'string[i] = 'u';
            case 
'V'string[i] = 'v';
            case 
'W'string[i] = 'w';
            case 
'X'string[i] = 'x';
            case 
'Y'string[i] = 'y';
            case 
'Z'string[i] = 'z';
            case 
'А'string[i] = 'а';
            case 
'Б'string[i] = 'б';
            case 
'В'string[i] = 'в';
            case 
'Г'string[i] = 'г';
            case 
'Д'string[i] = 'д';
            case 
'Е'string[i] = 'е';
            case 
'Ё'string[i] = 'ё';
            case 
'Ж'string[i] = 'ж';
            case 
'З'string[i] = 'з';
            case 
'И'string[i] = 'и';
            case 
'Й'string[i] = 'й';
            case 
'К'string[i] = 'к';
            case 
'Л'string[i] = 'л';
            case 
'М'string[i] = 'м';
            case 
'Н'string[i] = 'н';
            case 
'О'string[i] = 'о';
            case 
'П'string[i] = 'п';
            case 
'Р'string[i] = 'р';
            case 
'С'string[i] = 'с';
            case 
'Т'string[i] = 'т';
            case 
'У'string[i] = 'у';
            case 
'Ф'string[i] = 'ф';
            case 
'Х'string[i] = 'х';
            case 
'Ц'string[i] = 'ц';
            case 
'Ч'string[i] = 'ч';
            case 
'Ш'string[i] = 'ш';
            case 
'Щ'string[i] = 'щ';
            case 
'Ъ'string[i] = 'ъ';
            case 
'Ы'string[i] = 'ы';
            case 
'Ь'string[i] = 'ь';
            case 
'Э'string[i] = 'э';
            case 
'Ю'string[i] = 'ю';
            case 
'Я'string[i] = 'я';
        }
    }


код для теста:
PHP Code:

public OnGameModeInit()
{
    new 
time GetTickCount();
    for (new 
i1000000i++)
    {
        
UpperToLower("текст");
    }
    
printf("результат: %d ms"GetTickCount() - time);
    return 
1;


Результат тестирования UpperToLower:

без jit:
C++ | короткая строка = 172, длинная строка = 1047
Pawn | короткая строка = 1978, длинная строка = 8934

с jit:
C++ | короткая строка = 162, длинная строка = 1028
Pawn | короткая строка = 264, длинная строка = 1672

строки, которые использовались при тесте:
Code:

20 символов - иЛBё[еЬMDХ+T9wX/p1%Жs
100 символов - Юc№,Q)CxТФLrнПкХBjф[oiCЧм<bhшЗ,ыWR]ЁxчM}*Д8аCbР+bэjЭ1№D=оnнM!чepWo%GTKЧyR6VTЙSАщэЭSemюjFOЩ]ЭьтЛНЖ.ЧHLЛ


Процессор, на котором происходило тестирование: Intel Core i3 530 @ 2.93GHz

Скачать сборку для тестов v0.0.3 (мод + исходники)

Почему через плагин функции работают быстрее? Каковы преимущества?

White_116 13/02/2017 08:29 AM

Re: Написание плагинов
 
http://forum.sa-mp.com/showpost.php?...4&postcount=27 подключи jit compiler и проверь ещё разок.

DartfoL 13/02/2017 09:09 AM

Re: Написание плагинов
 
Quote:

Почему через плагин функции работают быстрее? Каковы преимущества?
потому что павн компилируется в байт код и инструкции выполняет AMX машина, а плагины компилируется в машинный код и он сразу напрямую исполняется процессором

P.S. 666-й пост

OstGot 13/02/2017 09:36 AM

Re: Написание плагинов
 
Дополню. Pawn компилятор слаб в оптимизациях, чего о C++ компиляторах сказать нельзя

DartfoL 13/02/2017 10:21 AM

Re: Написание плагинов
 
сейчас ещё раз глянул тему и нашёл ошибку в павн коде: strlen вызывается при каждой итерации, что существенно замедляет работу

И да, почему на плюсах используется switch-case, а на павне арифметика?

Mutha_X 13/02/2017 10:31 AM

Re: Написание плагинов
 
Можно в принципе было и через таблицы соответствия написать (и там и там; т.е. безусловную реализацию), тогда и наглядность по скорости работы с памятью повысилась.

Diman777 13/02/2017 01:45 PM

Re: Написание плагинов
 
Переделал, см. 1-ый пост.
С jit действительно функция от Pawn выполнилась быстрее, это забавно наблюдать)

Mutha_X 13/02/2017 03:37 PM

Re: Написание плагинов
 
Автор, предлагаю тему в формат статьи переделать (+ в репу будет :) ) и добавить вот что:
* сравнение производительности твоего кода для длинной строки (с jit и без) (можно взять ipsum lorem бла бла бла...) и для короткой (уже ты сделал);
* Всё тоже самое, но немного для другой реализации (смотри ниже код);
* Указать на каком процессоре и на какой системе получены результаты (я наблюдал ощутимую разницу в производительности аналогичных между собой решений на павне в зависимости от архитектуры проца);
Code:

// PAWN
new chars_lower_ascii[] = // en+ru
{
        0x00010203,0x04050607,0x08090A0B,0x0C0D0E0F,0x10111213,0x14151617,0x18191A1B,0x1C1D1E1F,
        0x20212223,0x24252627,0x28292A2B,0x2C2D2E2F,0x30313233,0x34353637,0x38393A3B,0x3C3D3E3F,
        0x40616263,0x64656667,0x68696A6B,0x6C6D6E6F,0x70717273,0x74757677,0x78797A5B,0x5C5D5E5F,
        0x60616263,0x64656667,0x68696A6B,0x6C6D6E6F,0x70717273,0x74757677,0x78797A7B,0x7C7D7E7F,
        0x80818283,0x84858687,0x88898A8B,0x8C8D8E8F,0x90919293,0x94959697,0x98999A9B,0x9C9D9E9F,
        0xA0A1A2A3,0xA4A5A6A7,0xB8A9AAAB,0xACADAEAF,0xB0B1B2B3,0xB4B5B6B7,0xB8B9BABB,0xBCBDBEBF,
        0xE0E1E2E3,0xE4E5E6E7,0xE8E9EAEB,0xECEDEEEF,0xF0F1F2F3,0xF4F5F6F7,0xF8F9FAFB,0xFCFDFEFF,
        0xE0E1E2E3,0xE4E5E6E7,0xE8E9EAEB,0xECEDEEEF,0xF0F1F2F3,0xF4F5F6F7,0xF8F9FAFB,0xFCFDFEFF
};
stock StringToLowerByTable_ASCII(string[]) {
        new index = -1;
        while(string[++index]) {
                        string[index] = chars_lower_ascii{string[index]};

        }
}
// C/C++
char unsigned chars_lower_ascii[] = {
        0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
        0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
        0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
        0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
        0x40,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
        0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x5B,0x5C,0x5D,0x5E,0x5F,
        0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
        0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,
        0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,
        0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,
        0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xB8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,
        0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,
        0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
        0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF,
        0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
        0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
void StringToLowerByTable_ASCII(string[]) {
        int index = -1;
        while(string[++index]) {
                string[index] = chars_lower_ascii[string[index]];
        }
}


White_116 13/02/2017 03:47 PM

Re: Написание плагинов
 
Quote:

Originally Posted by Mutha_X (Post 3843879)
Автор, предлагаю тему в формат статьи переделать (+ в репу будет :) ) и добавить вот что:
* сравнение производительности твоего кода для длинной строки (с jit и без) (можно взять ipsum lorem бла бла бла...) и для короткой (уже ты сделал);
* Всё тоже самое, но немного для другой реализации (смотри ниже код);
* Указать на каком процессоре и на какой системе получены результаты (я наблюдал ощутимую разницу в производительности аналогичных между собой решений на павне в зависимости от архитектуры проца);
Code:

// PAWN
new chars_lower_ascii[] = // en+ru
{
        0x00010203,0x04050607,0x08090A0B,0x0C0D0E0F,0x10111213,0x14151617,0x18191A1B,0x1C1D1E1F,
        0x20212223,0x24252627,0x28292A2B,0x2C2D2E2F,0x30313233,0x34353637,0x38393A3B,0x3C3D3E3F,
        0x40616263,0x64656667,0x68696A6B,0x6C6D6E6F,0x70717273,0x74757677,0x78797A5B,0x5C5D5E5F,
        0x60616263,0x64656667,0x68696A6B,0x6C6D6E6F,0x70717273,0x74757677,0x78797A7B,0x7C7D7E7F,
        0x80818283,0x84858687,0x88898A8B,0x8C8D8E8F,0x90919293,0x94959697,0x98999A9B,0x9C9D9E9F,
        0xA0A1A2A3,0xA4A5A6A7,0xB8A9AAAB,0xACADAEAF,0xB0B1B2B3,0xB4B5B6B7,0xB8B9BABB,0xBCBDBEBF,
        0xE0E1E2E3,0xE4E5E6E7,0xE8E9EAEB,0xECEDEEEF,0xF0F1F2F3,0xF4F5F6F7,0xF8F9FAFB,0xFCFDFEFF,
        0xE0E1E2E3,0xE4E5E6E7,0xE8E9EAEB,0xECEDEEEF,0xF0F1F2F3,0xF4F5F6F7,0xF8F9FAFB,0xFCFDFEFF
};
stock StringToLowerByTable_ASCII(string[]) {
        new index = -1;
        while(string[++index]) {
                        string[index] = chars_lower_ascii{string[index]};

        }
}
// C/C++
char unsigned chars_lower_ascii[] = {
        0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
        0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
        0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
        0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
        0x40,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
        0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x5B,0x5C,0x5D,0x5E,0x5F,
        0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
        0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,
        0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,
        0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,
        0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xB8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,
        0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,
        0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
        0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF,
        0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
        0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
void StringToLowerByTable_ASCII(string[]) {
        int index = -1;
        while(string[++index]) {
                string[index] = chars_lower_ascii[string[index]];
        }
}


Е*ать ты велосипедист. кинул же решение в первом сообщении.

http://forum.sa-mp.com/showpost.php?...4&postcount=27

Mutha_X 13/02/2017 04:53 PM

Re: Написание плагинов
 
Quote:

Originally Posted by White_116 (Post 3843885)
Е*ать ты велосипедист. кинул же решение в первом сообщении.

http://forum.sa-mp.com/showpost.php?...4&postcount=27

Строго говоря, пока ты условия применения не уточнил - это не велосипед вовсе... это моноцикл ;) :
отличие лишь в способе проверки условия окончания цикла и strlen только у тебя.
Из этого вытекает, что примерно до 16 (а это могут быть названия вещей и ники игроков) включительно символов с символом-терминатором будет выигрывать мой способ (тестировал без jit), а у тебя выгодный алгоритм для длинных строк (например запросы в бд (хз зачем), антикапс и другое).

На твоём бы месте я бы написал вышеизложенное и средство, которое на этапе компиляции выбирало бы оптимальный вариант (функцию) на основе размера целевого массива.

И да, автор не менял свой алгоритм на твой после предложения и указал цифры только для своего...


All times are GMT. The time now is 07:33 AM.

Powered by vBulletin® Version 3.8.6
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd.