Оптимизация кода Pawn: советы и рекомендации

Активный
Статус
Сообщения
516
Лайки
32

8

месяц на сайте

Оптимизация улучшает производительность сервера. Разберем основные техники.

Оптимизация циклов
Код:
// ПЛОХО - проверка на каждой итерации
for(new i = 0; i < MAX_PLAYERS; i++)
{
    if(IsPlayerConnected(i))
    {
        // код
    }
}

// ХОРОШО - кеширование размера
new maxPlayers = GetMaxPlayers();
for(new i = 0; i < maxPlayers; i++)
{
    if(IsPlayerConnected(i))
    {
        // код
    }
}

// ЕЩЕ ЛУЧШЕ - использование foreach
foreach(new i : Player)
{
    // код
}

Оптимизация строк
Код:
// ПЛОХО - создание новой строки каждый раз
for(new i = 0; i < 100; i++)
{
    new string[128];
    format(string, sizeof(string), "Игрок %d", i);
}

// ХОРОШО - переиспользование строки
new string[128];
for(new i = 0; i < 100; i++)
{
    format(string, sizeof(string), "Игрок %d", i);
    // использование строки
}

Оптимизация проверок
Код:
// ПЛОХО - множественные проверки
if(IsPlayerConnected(playerid))
{
    if(GetPlayerMoney(playerid) > 0)
    {
        if(GetPlayerHealth(playerid) > 0)
        {
            // код
        }
    }
}

// ХОРОШО - ранний выход
if(!IsPlayerConnected(playerid)) return 0;
if(GetPlayerMoney(playerid) <= 0) return 0;
if(GetPlayerHealth(playerid) <= 0) return 0;
// код

Оптимизация таймеров
Код:
// ПЛОХО - слишком частые таймеры
SetTimer("UpdatePlayer", 100, true);

// ХОРОШО - оптимальная частота
SetTimer("UpdatePlayer", 1000, true);

// Использование одного таймера для нескольких задач
forward MainTimer();
public MainTimer()
{
    UpdatePlayers();
    UpdateVehicles();
    UpdateBusinesses();
}

Оптимизация массивов
Код:
// Используйте правильные размеры массивов
new PlayerData[MAX_PLAYERS][PlayerInfo]; // правильно
new PlayerData[1000][PlayerInfo]; // избыточно

// Используйте индексацию вместо поиска
new playerIndex[MAX_PLAYERS] = {-1, ...};
// Быстрый доступ по индексу вместо поиска

Оптимизация функций
Код:
// Используйте stock для неиспользуемых функций
stock UnusedFunction()
{
    // код
}

// Используйте inline для простых функций
#define GetDistance(%1,%2,%3,%4,%5,%6) \
    floatsqroot((%1-%4)*(%1-%4) + (%2-%5)*(%2-%5) + (%3-%6)*(%3-%6))

Оптимизация OnPlayerUpdate
Код:
// ПЛОХО - тяжелые операции в OnPlayerUpdate
public OnPlayerUpdate(playerid)
{
    SavePlayerData(playerid); // слишком часто
    return 1;
}

// ХОРОШО - использование таймеров
new lastUpdate[MAX_PLAYERS];

public OnPlayerUpdate(playerid)
{
    if(GetTickCount() - lastUpdate[playerid] > 5000)
    {
        // легкие операции
        lastUpdate[playerid] = GetTickCount();
    }
    return 1;
}

// Тяжелые операции в отдельном таймере
SetTimerEx("SavePlayerData", 60000, true, "i", playerid);

Оптимизация диалогов
Код:
// Кешируйте списки диалогов
new weaponList[512];

ShowWeaponDialog(playerid)
{
    if(strlen(weaponList) == 0)
    {
        // Генерация списка один раз
        for(new i = 0; i < sizeof(WeaponList); i++)
        {
            format(weaponList, sizeof(weaponList), "%s%s\n", weaponList, WeaponList[i][wName]);
        }
    }
    
    ShowPlayerDialog(playerid, DIALOG_WEAPONS, DIALOG_STYLE_LIST, "Оружие", weaponList, "Выбрать", "Отмена");
}

Оптимизация TextDraw
Код:
// Обновляйте только при изменении
new lastMoney[MAX_PLAYERS];

UpdateMoneyTextDraw(playerid)
{
    new money = GetPlayerMoney(playerid);
    if(money != lastMoney[playerid])
    {
        new string[32];
        format(string, sizeof(string), "$%d", money);
        TextDrawSetString(moneyTextDraw, string);
        lastMoney[playerid] = money;
    }
}

Оптимизация проверок расстояния
Код:
// Используйте квадрат расстояния для сравнения
stock IsPlayerInRange(playerid, Float:x, Float:y, Float:z, Float:range)
{
    new Float:px, Float:py, Float:pz;
    GetPlayerPos(playerid, px, py, pz);
    
    new Float:distance = floatsqroot(
        floatpower(px - x, 2) + 
        floatpower(py - y, 2) + 
        floatpower(pz - z, 2)
    );
    
    return distance <= range;
}

// Оптимизированная версия без квадратного корня
stock IsPlayerInRangeFast(playerid, Float:x, Float:y, Float:z, Float:range)
{
    new Float:px, Float:py, Float:pz;
    GetPlayerPos(playerid, px, py, pz);
    
    new Float:distanceSq = 
        floatpower(px - x, 2) + 
        floatpower(py - y, 2) + 
        floatpower(pz - z, 2);
    
    return distanceSq <= floatpower(range, 2);
}

Важные моменты:
- Профилируйте код для поиска узких мест
- Избегайте преждевременной оптимизации
- Измеряйте производительность до и после
- Документируйте оптимизации

Оптимизация улучшает работу сервера!
 

1 человек читают эту тему (Всего: 1, Пользователей: 0, Гостей: 1)

Сверху