Welcome!

By registering with us, you'll be able to discuss, share and private message with other members of our community.

SignUp Now!
Самый быстрый INI ридер/райтер ( Penis )

Самый быстрый INI ридер/райтер ( Penis ) 2025-10-08

Янв
414
76
Пользователь
pawneror добавил(а) новый ресурс:

Самый быстрый INI ридер/райтер ( Penis ) - Самый быстрый INI ридер/райтер ( Penis )

📚 PENIS — Ultra-Fast Key-Value Config Handler for SA-MP

PENIS — это высокопроизводительная библиотека для работы с конфигурационными файлами в формате key = value (аналог INI), разработанная специально для серверов San Andreas Multiplayer (SA-MP) на языке Pawn.

Важно: Название PENIS не имеет никакого отношения к анатомии. Это аббревиатура от Pawn Efficient Non-blocking In-memory...

Узнать больше об этом ресурсе...
 
Дек
367
80
Активный
OFFTOP

и ким хуем проведено сравнение что САМЫЙ БЫСТРЫЙ???

 
𝚖𝚎𝚖𝚎𝚗𝚝𝚘 𝚖𝚘𝚛𝚒.
Мар
1,220
13,443
Команда форума
Администратор
Тесты проводились с задержкой в 10 секунд от предыдущего теста. Тесты проводились в записи и в чтении файлов.

Результаты:
Код:
[13:23:38] [test_ini] Penis write: 65 ms. (1000 files)
[13:23:38] [test_ini] Penis read: 45 ms. (1000 files)
[13:23:48] [test_ini] mxINI write: 56 ms. (1000 files)
[13:23:48] [test_ini] mxINI read: 32 ms. (1000 files)

Код, с помощью которого проводились тесты:

Pawn:
forward check_penis();
public check_penis() {
    new tick_start,
        tick_result;

    tick_start = GetTickCount();
    for(new i; i < 1000; ++i) {
        new tmp_string[16];
        format(tmp_string, sizeof tmp_string, "players/%d.pen", i + 1);

        new cfg = penis_create(tmp_string);
        if (cfg < 0)
            cfg = penis_open(tmp_string);

        if (cfg >= 0)
        {
            penis_set_str(cfg, "name", "John_Doe");
            penis_set_int(cfg, "score", 9876);
            penis_set_float(cfg, "health", 99.5);

            penis_close(cfg);
        }
    }
    tick_result = (GetTickCount() - tick_start);
    printf("[test_ini] Penis write: %d ms. (1000 files)", tick_result);

    //

    tick_start = GetTickCount();
    for(new i; i < 1000; ++i) {
        new tmp_string[16];
        format(tmp_string, sizeof tmp_string, "players/%d.pen", i + 1);

        new cfg = penis_open(tmp_string);

        new name[32],
            score,
            Float:hp;

        penis_get_str(cfg, "name", name);
        penis_get_int(cfg, "score", score);
        penis_get_float(cfg, "health", hp);

        penis_close(cfg);
    }
    tick_result = (GetTickCount() - tick_start);
    printf("[test_ini] Penis read: %d ms. (1000 files)", tick_result);
    return 1;
}

forward check_mxini();
public check_mxini() {
    new tick_start,
        tick_result,
        inifile;

    // test ini readers (mxini)
    tick_start = GetTickCount();
    for(new i; i < 1000; ++i) {
        new tmp_string[16];
        format(tmp_string, sizeof tmp_string, "%d.ini", i + 1);

        inifile = ini_createFile(tmp_string);

        ini_setString(inifile, "name", "John_Doe");
        ini_setInteger(inifile, "score", 9876);
        ini_setFloat(inifile, "health", 99.5);

        ini_closeFile(inifile);
    }
    tick_result = (GetTickCount() - tick_start);
    printf("[test_ini] mxINI write: %d ms. (1000 files)", tick_result);

    //

    tick_start = GetTickCount();
    for(new i; i < 1000; ++i) {
        new tmp_string[16];
        format(tmp_string, sizeof tmp_string, "%d.ini", i + 1);

        inifile = ini_openFile(tmp_string);

        new name[32],
            score,
            Float:hp;

        ini_getString(inifile, "name", name);
        ini_getInteger(inifile, "score", score);
        ini_getFloat(inifile, "health", hp);
       
        ini_closeFile(inifile);
    }
    tick_result = (GetTickCount() - tick_start);
    printf("[test_ini] mxINI read: %d ms. (1000 files)", tick_result);
    return 1;
}

Код первого ini-ридера был взят напрямую со страницы ресурса. Код для mxini был написан одинаково.
Код запуска тестов:
Pawn:
SetTimer("check_penis", 10000, false);
SetTimer("check_mxini", 20000, false);

UPD: забыл упомянуть, что сам ini-ридер не рабочий. Проблема в макросе, который нейронка написала как функцию. Собственно, клин клином вышибает, потому и исправлял нейронкой.
 
Янв
414
76
Пользователь
Тесты проводились с задержкой в 10 секунд от предыдущего теста. Тесты проводились в записи и в чтении файлов.

Результаты:
Код:
[13:23:38] [test_ini] Penis write: 65 ms. (1000 files)
[13:23:38] [test_ini] Penis read: 45 ms. (1000 files)
[13:23:48] [test_ini] mxINI write: 56 ms. (1000 files)
[13:23:48] [test_ini] mxINI read: 32 ms. (1000 files)

Код, с помощью которого проводились тесты:

Pawn:
forward check_penis();
public check_penis() {
    new tick_start,
        tick_result;

    tick_start = GetTickCount();
    for(new i; i < 1000; ++i) {
        new tmp_string[16];
        format(tmp_string, sizeof tmp_string, "players/%d.pen", i + 1);

        new cfg = penis_create(tmp_string);
        if (cfg < 0)
            cfg = penis_open(tmp_string);

        if (cfg >= 0)
        {
            penis_set_str(cfg, "name", "John_Doe");
            penis_set_int(cfg, "score", 9876);
            penis_set_float(cfg, "health", 99.5);

            penis_close(cfg);
        }
    }
    tick_result = (GetTickCount() - tick_start);
    printf("[test_ini] Penis write: %d ms. (1000 files)", tick_result);

    //

    tick_start = GetTickCount();
    for(new i; i < 1000; ++i) {
        new tmp_string[16];
        format(tmp_string, sizeof tmp_string, "players/%d.pen", i + 1);

        new cfg = penis_open(tmp_string);

        new name[32],
            score,
            Float:hp;

        penis_get_str(cfg, "name", name);
        penis_get_int(cfg, "score", score);
        penis_get_float(cfg, "health", hp);

        penis_close(cfg);
    }
    tick_result = (GetTickCount() - tick_start);
    printf("[test_ini] Penis read: %d ms. (1000 files)", tick_result);
    return 1;
}

forward check_mxini();
public check_mxini() {
    new tick_start,
        tick_result,
        inifile;

    // test ini readers (mxini)
    tick_start = GetTickCount();
    for(new i; i < 1000; ++i) {
        new tmp_string[16];
        format(tmp_string, sizeof tmp_string, "%d.ini", i + 1);

        inifile = ini_createFile(tmp_string);

        ini_setString(inifile, "name", "John_Doe");
        ini_setInteger(inifile, "score", 9876);
        ini_setFloat(inifile, "health", 99.5);

        ini_closeFile(inifile);
    }
    tick_result = (GetTickCount() - tick_start);
    printf("[test_ini] mxINI write: %d ms. (1000 files)", tick_result);

    //

    tick_start = GetTickCount();
    for(new i; i < 1000; ++i) {
        new tmp_string[16];
        format(tmp_string, sizeof tmp_string, "%d.ini", i + 1);

        inifile = ini_openFile(tmp_string);

        new name[32],
            score,
            Float:hp;

        ini_getString(inifile, "name", name);
        ini_getInteger(inifile, "score", score);
        ini_getFloat(inifile, "health", hp);
    
        ini_closeFile(inifile);
    }
    tick_result = (GetTickCount() - tick_start);
    printf("[test_ini] mxINI read: %d ms. (1000 files)", tick_result);
    return 1;
}

Код первого ini-ридера был взят напрямую со страницы ресурса. Код для mxini был написан одинаково.
Код запуска тестов:
Pawn:
SetTimer("check_penis", 10000, false);
SetTimer("check_mxini", 20000, false);

UPD: забыл упомянуть, что сам ini-ридер не рабочий. Проблема в макросе, который нейронка написала как функцию. Собственно, клин клином вышибает, потому и исправлял нейронкой.

и зачем? Это всего лишь был рофл. Так сильно задели посты в соседней теме?)

Реальный вопрос над подумать для всех разработчиков: добиться реального прироста в скорости у mxini. Лично у меня не получилось. Если бы получилось, то тема была бы не совсем рофлом.
 
𝚖𝚎𝚖𝚎𝚗𝚝𝚘 𝚖𝚘𝚛𝚒.
Мар
1,220
13,443
Команда форума
Администратор
Это всего лишь был рофл. Так сильно задели посты в соседней теме?)
Каким образом они меня могли задеть?)
Был вопрос в данной теме - я дал ответ на данный вопрос и на название ресурса.
Сейчас же как администратор портала предупрежу - будьте добры, проверяйте ресурсы, которые хотите выкладывать на всеобщее обозрение.
 
Июл
15
0
Пользователь
Привет, внимательно посмотрел твой инклюд. Идея нормальная — держать конфиг в памяти и писать на диск только при закрытии. Но реализация… мягко говоря, сыроватая. Я бу лучше использовал mxini. А так же вот что заметил при чтении кода ( на сервере не тестировал, лишь пробежался глазами ):

Самый критичный баг — ты вставляешь нулевой байт прямо в середину файла

В макросе _PENIS_SET_VALUE после того, как записал новое значение, у тебя стоит строчка:

penesis:
penis_buffer[file_id]{start + new_len} = 0;

Проблема в том, что это происходит после сдвига хвоста буфера. Если после изменённого ключа есть ещё хоть какие-то данные (а они почти всегда есть), ты просто затираешь начало этого хвоста нулевым байтом.

Потом penis_close честно записывает весь буфер на диск через fputchar. В итоге в конфиге появляется \0 посреди файла. Любой нормальный редактор или парсер после этого ключа уже ничего не видит. Данные портятся молча.

Это даже не «можно столкнуться», это гарантированно происходит при любом изменении существующего ключа, если он не последний в файле.

2. Переполнение массива ключей

Когда ключа ещё нет и ты добавляешь новый, у тебя:

Код:
penis_key_pos[file_id][penis_key_count[file_id]++] = pos;

Никакой проверки на PENIS_MAX_KEYS. В open и create ты проверяешь, а здесь — нет. Достаточно добавить больше ключей, чем лимит, и получаешь запись за границы массива. Классика.

3. Разная логика сбора ключей в create и open

В create ты запоминаешь вообще каждый встреченный '='.В open — только первый '=' на строке (из-за флага in_new_line).

После create → close → open поведение библиотеки может измениться. Особенно если в значениях случайно окажется знак равенства.

4. remove криво вырезает строки

Ты останавливаешься на \r или \n, потом иногда пропускаешь только \r, но не всегда забираешь следующий \n. В итоге после нескольких удалений файл начинает зарастать пустыми строками и обрывками переносов. Позиции ключей при этом тоже легко разъезжаются.

5. Тихое обрезание строк до 128 символов


Во всех set_* у тебя new_val[128]. Длинное значение просто молча обрежется. Ни ошибки, ни предупреждения. Для конфигов, где могут быть длинные строки — неприятный сюрприз.

Так то код хороший, более менее читабельный, но я бы лучше использовал mxIni. Он надежнее, хоть и чуть уступает в скорости.

ред: p.s. для написания темы на форуме ты использовал нейронку. Так что не стоит обвинять меня в том что я писал через нее XML-теги. Ты сделал можно сказать тоже самое.
 
Сверху