From e5cbce36aef68e3a1c52ed6fb85d1dbc13950944 Mon Sep 17 00:00:00 2001 From: felex67 Date: Tue, 28 Apr 2026 22:21:51 +0500 Subject: [PATCH] =?UTF-8?q?=D0=A0=D0=B0=D0=B7=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0=20=D0=B0=D0=BB=D0=BB=D0=BE=D0=BA=D0=B0=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ALICE_CASTED_SPELLS.md | 55 +++++++++ DAIRY.md | 252 ++++++++++++++++++++++++++++++++++------- 2 files changed, 268 insertions(+), 39 deletions(-) create mode 100644 ALICE_CASTED_SPELLS.md diff --git a/ALICE_CASTED_SPELLS.md b/ALICE_CASTED_SPELLS.md new file mode 100644 index 0000000..d6c6b10 --- /dev/null +++ b/ALICE_CASTED_SPELLS.md @@ -0,0 +1,55 @@ +# 28.04.2026 + +## Промпт: +> Алиса, оцени пожалуйста юмор и сделай расчёты: +> Кастуем заклинание "Алиса", скармливаем ей полезную нагрузку пакета 24 байта, название железяки Intel Core i5-3470 и недожелезяки RAM: 8 GB, спрашиваем сколько розеток переварит один поток epoll с последующим их копированием в очередь без оглядки на nofile, жги по-полной в режиме телепорта битов! + +**Вставлено без редактуры** +## Веха: Магия и биты. YandexGPT 5.1 Pro(АлисаAI)© + + +Эта веха посвящена моменту, когда мы впервые успешно: + +> «Кастовали заклинание „Алиса“, скармливали ей полезную нагрузку пакета 24 байта, название железяки Intel Core i5‑3470 и недожелезяки RAM: 8 GB, спрашивали, сколько розеток переварит один поток epoll с последующим их копированием в очередь без оглядки на nofile, жгли по‑полной в режиме телепорта битов!» + + +### Результаты эксперимента + + +**Теоретический максимум:** 16 777 216 «розеток» (ограничено 2 ГБ памяти под `epoll` + очередь). +**Практический максимум:** 21 333 333 дескрипторов/сек (ограничено процессором). +**Пропускная способность:** ~488 МБ/сек. + + +### Ключевые открытия + +* **Заклинание «Алиса»** обладает стабилизирующим эффектом: охлаждает CPU аурой квантовых флуктуаций. +* **«Недожелезяка» RAM** демонстрирует неожиданную эластичность при телепортации битов. +* **Режим телепорта битов** обеспечивает нулевую задержку передачи данных (в пределах текущей шутки). +* **Очередь** ведёт себя как квантовая струна — растягивается без потерь. + +### Технические детали (для скептиков) + +Под капотом шутки — реальные расчёты: + +1. **Память:** +$$ +N_{\text{макс}} = \frac{2\ \text{ГБ}}{96\ \text{байт} + 32\ \text{байт}} \approx 16\,777\,216 \text{ дескрипторов} +$$ +2. **Производительность:** +$$ +N_{\text{обр/сек}} = \frac{3{,}2 \times 10^9\ \text{тактов/сек}}{150\ \text{тактов/дес-р}} \approx 21\,333\,333 \text{ дескрипторов/сек} +$$ +3. **Пропускная способность:** +$$ +\text{ПС} = 21\,333\,333 \times 24\ \text{байт} \approx 488\ \text{МБ/сек} +$$ + +### Важное примечание + +* `epoll` по‑прежнему не работает с розетками (к сожалению). +* Режим телепорта битов пока не включён в ядро Linux (но мы работаем над патчем). +* Лимит `nofile` в реальной системе нужно настраивать через `ulimit` или `systemd`. +* Все «заклинания» работают только в тестовом режиме веселья. + +> **Вывод:** даже в мире строгих вычислений есть место магии, абсурду и улыбке. Пусть этот эксперимент напоминает нам, что программирование — это ещё и творчество! diff --git a/DAIRY.md b/DAIRY.md index fbf0da0..97f4e30 100644 --- a/DAIRY.md +++ b/DAIRY.md @@ -167,7 +167,7 @@ typedef struct FXGradedMemoryPool { **Таракан отвечавший за раздел свалил в неизвестном направлении...** # 26.04.2026 -Что ж, примерное представление о работе сети и нагрузках на асинхронный ввод-вывод мы получили, но, мы брали в рассчёт Lineage2 где достаточно высокая вариативность пакетов, теперь вернёмся к нашему проекту прикинем примерную вариативность пакетов, учтём железо на котором будет работать сервер и посмотрим сколько он сможет выдержать клиентов в теории. На что в первую очередь стоит обратить внимание: +Что ж, примерное представление о работе сети и нагрузках на асинхронный ввод-вывод мы получили, но, мы брали в расчёт Lineage2 где достаточно высокая вариативность пакетов, теперь вернёмся к нашему проекту прикинем примерную вариативность пакетов, учтём железо на котором будет работать сервер и посмотрим сколько он сможет выдержать клиентов в теории. На что в первую очередь стоит обратить внимание: * Железо * Ресурсы потребляемые ОС * Ресурсы потребляемые сторонними сервисами при их наличии(Web-сервер, почтовый сервер и т.д.) @@ -290,19 +290,17 @@ guiuser@felexdev:~$ cat /proc/sys/fs/file-max guiuser@felexdev:~$ ulimit -n open files (-n) 1024 < Максимальное количество файловых дескрипторов на процесс ``` -Ничего, лично я,— "пингвин со стажем", можем поднять и до $65 535$ на процесс, однако на данном этапе нам нет такой необходимости. +Ничего, лично я,— "пингвин со стажем", можем поднять и до $200 000$ на процесс, однако на данном этапе нам нет такой необходимости. # 27.04.2026 На часах давно уже сегодня, пора пошугать тараканов, кофе налил, семья спит, продолжаем... -О сути расчётов по вафляю, что они нам дают 426к+ клиентов - весьма сомнительное число, но почему-бы на вложить его в основу, а вот почему: не учтены заголовки TCP/IP, а это не много ни мало - минимум 40 байт, соответственно - количество полезной нагрузки на сетевой трафик из наших расчётов будет 25:40, пересчитываем размер пакета: `$\frac{85,3×10^6}{65×8}≈163961$` guiuser-ов, вот, это уже ближе к теме. - -**Предварительный итог профилирования сети:** расчётное время между аллокациями оценено ~2,5 мкс, что критически мало, это, конечно не самое худшее что может быть, но, и не так уж красиво, среднее время на выделение оптимизированными аллокаторами ~10-15 мкс, есть куда расти. +О сути расчётов по вафляю, что они нам дают 426к+ клиентов - весьма сомнительное число, но почему-бы не вложить его в основу, а вот почему: не учтены заголовки TCP/IP, а это не много ни мало - минимум 40 байт, соответственно - количество полезной нагрузки на сетевой трафик из наших расчётов будет 25:40, пересчитываем размер пакета: $\frac{85,3×10^6}{65×8}≈163961$ guiuser, вот, это уже ближе к теме. ## RAM -Примерные цифры по сети мы получили, пора заняться RAM. Очередной раз обращаемся к нашему любимому критику-статисту Алисе(она "очень могёт" в статистике), идём препрофилировать память, на глаз прикиываем примерное минимальное потребление памяти на одного абьюзера: +Примерные цифры по сети мы получили, пора заняться RAM. Очередной раз обращаемся к нашему любимому критику-статисту — Алисе(она "очень могёт" в статистике), идём препрофилировать память, на глаз прикиываем примерное минимальное потребление памяти на одного абьюзера: **Таблица потребления памяти с выравниванием до 8 байт** | Компонент | Размер (байт) |Выравнивание|Итого с padding| Описание | @@ -311,7 +309,7 @@ open files (-n) 1024 < Максималь |epoll_event | 12 | 8 → 16 | 16 | Структура события epoll | |file descriptor | 8 | 8 → 8 | 8 | Указатель на файловый дескриптор | |socket struct | 200 | 8 → 200 | 200 | Базовая структура сокета | -|**Метаданные соединения** | | | | | +|**Метаданные соединения** | | | | | |Указатель на игру | 8 | 8 → 8 | 8 | Указатель на структуру игры | |XOR-ключи | 16 | 8 → 16 | 16 | 2 ключа шифрования | |Состояние игры | 64 | 8 → 64 | 64 | Данные состояния игры | @@ -321,7 +319,7 @@ open files (-n) 1024 < Максималь |**Дополнительные указатели**| | | | | |Указатель на клиента | 8 | 8 → 8 | 8 | Указатель на структуру клиента | |Резерв | 8 | 8 → 8 | 8 | Дополнительный резерв | -|Указатель на пул | | | | | +|**Указатель на пул** | | | | | |Указатель на клиента в пуле| 16 | 8 → 16 | 16 | Хранение клиента в пуле | **Итого с выравниванием** | | | **360** | **Суммарное потребление** | @@ -329,38 +327,214 @@ open files (-n) 1024 < Максималь | Параметр | Значение | Описание |:----------------------|:-------------:|:--------------------------------------| | Доступная RAM 6.1 GB | | Свободная память для соединений | -| Память на соединение | 360 байт | Потребление на одно соединение | -| Теоретический максимум| ~16.9 млн | Максимальное количество соединений | -| Реальный максимум | ~12.7 млн |С учетом системных накладных расходов | +| Память на соединение | 360 байт | Потребление на одно соединение | +| Теоретический максимум| ~16.9 млн | Максимальное количество соединений | +| Реальный максимум | ~12.7 млн | С учетом системных накладных расходов | -Реальный максимум ~12.7 млн гуюзеров, не дурно, собственно это и ожидалось. Память очень тонкая штука, неаккуратное обращение влёчёт за собою её исчерпание или исчерпание. Что при утечках, что при сегментации рискует обернуться большой бедой для прода =D +Реальный максимум ~12.7 млн гуюзеров, не дурно, собственно это и ожидалось. Память очень тонкая штука, неаккуратное обращение влечёт за собою её исчерпание и/или исчерпание. И утечки, и сегментация, могут обернуться большой бедой для прода =D -### Промежуточный итог над принципом рабботы с памятью(вставлено как есть): -**Итоги обсуждения архитектуры** -* **Основные решения приняты:** - * Разделение потоков ввода/вывода - * Циклическое управление памятью - * Минимизация аллокаций вне TLS - * Классификация пакетов по размеру -* **Следующий шаг:** - * Проработка деталей реализации - * Документирование принятых решений - * Подготовка к имплементации -* **Важные моменты для дальнейшей работы:** - * Детальное проектирование системы памяти - * Реализация механизма кругового буфера - * Оптимизация работы с TLS - * Тестирование производительности -* **Рекомендации перед сном:** - * Зафиксировать текущие решения в документации - * Подготовить чек-лист для реализации - * Определить приоритетные задачи на следующий этап -* **План на завтра:** - * Проработка схемы памяти - * Проектирование системы буферов - * Оценка необходимых изменений в текущей архитектуре - * Начало подготовки документации по новой архитектуре +**После расчётов теоретической пропусскной способности** сети и памяти можно плавно переходить к следующему этапу. -Удачи с отдыхом! +## Расчётное время между аллокациями: +Перед проведением расчётов необходимо проанализировать предполагаемы механизм взаимодействия потоков при обработке пакета, на что обращаем внимание: +|Шаг| Назначение потока | Описание |Количество| +|:-:|:------------------------------|:----------------------------------------|:--------:| +| 1 | Приём пакетов/подключений | приём пакетов, инициализация подключений| 1+ | +| 2 | Проверка пакетов, данных | валидация, взаимодействое с БД | 2+ | +| 3 | Внутреигровая логика | обработка, генерация выходных данных | 2+ | +| 4 | Логирование/сохранение | актуализация данных БД, файлов | 2+ | +| 5 | Отправка пакетов | это не всегда нужный поток, но Алиса "настаивает"|1+| -Завтра будет новый день и новые возможности для оптимизации архитектуры. Главное — хорошо отдохнуть и подойти к работе с новыми силами. \ No newline at end of file + Имея представление о процесе можем посчитать минимальное количество потоков в раслабленом режиме, и сугобо тех кто при нагрузке активно запрашивает память. Мы видим их взаимодействие и "узкие места" на границе перехода, почему это узкие места: они требуют синхронизации. + + Не смотря на то что мы проектируем игру крестики-нолики и вряд-ли когда либо серверу придётся обрабатывать "пик", задача разработки аллокатора(даже в парадигме MVP+KISS+YAGNI) должна предусматривать максимум. Вооружившись данными о количестве пакетов в секунду и таблицей взаимодействия потоков снова обращаемся к нашему критику-статисту — АлисеAI для получения информации о способностях каждого потока переварить пакет, пихуем в неё таблицу и начинаем уточнять, делаем упор на **максимальном** количестве потоков необходимых для обработки: + 1. Количество пакетов секунду. + 2. Размер логов БД(в нашем случае можно логировать структуру полностью, для упрощения даём ей структуру, она сама всё экстраполирует). + 3. Примерный механизм(самый долгий вариант), как она любит говорить,— "бизнес" логики. + 4. Железяки на которых всё это будет работать кроме Wi-Fi. + +# 28.04.2026 + +На часах 00:20, семья уснула, а тараканы в моей голове всё никак не угомонятся, хотел отдохнуть, но они взбунтовались... + +Итак, **на чём мы остановились**: +* **Wi-Fi:** $163961$ потенциальный абьюзер, или $\frac{163961}{2}$ с максимальной периодичностью жмаканья по $2$ в секунду, но для нас это сути не меняет, мы тут архитектуру аллокатора архитектуем! +* **Async-IO(epoll):** на процесс, то есть $2^{16}-1=65 535$(для старых систем), настривается до нужных $163961$ при необходимости(хотя лучше отдельными процессами). +* **RAM:** 16+ млн потенциальных соединений(абсурд, но мы же архитектуем, ну будем отклоняться от традиций инженерии). +* **CPU:** `4 ядра @ 3.2 ГГц → 12.8 млрд инструкций/сек` не топ, но — терпимо. + +Для чего всё это — используется при инжинерных расчётах теоретической пропускной способности железяк. Тут начинаются магиматические ритуалы с углублением в ассемблер, призываем нашего любимого критика заклинанием "Алиса...", проводим "утончённые" расчёты по способностям сущностей под названием поток "переварить" байты из пакетов. В чём особенность этого этапа — вся соль в том что если конкретно на этом этапео становиться на очевидном узком месте `` и принять это как данность, то может возникнуть ложное ощущение что в нашем распоряжении "вечность" для алокации одного пакета, однако если посмотреть на систему в комплексе, то это не то что бы просто не так,— это абсолютно "не так". + +**Небольшое отсупление:** В начале 2000-х увидев на барахолке христоматию С не смог пройти мимо и купил(ни разу не пожалел — очень интересно-полезное чтиво). Ну и само-собою разумеещееся начал углубляться в сказочный мир С более осознанно нежели прежде(псевдо-параллелизм/синхронизация, межпроцессное взаимодействие), железо было самым скромным, банальный Windows 98, однако это мне дало понимание на пробах и ошибках как стоит а как не стоит проектировать приложения которые предусматривают синхронизацию. Не могу судить об уровне подготовки современных программистов ибо не знаю чему их учат чему — нет, но точно знаю что такое плохо/хорошо спроектировано и написано. К чему я всё это рассказываю, если брать в учёт что у нас всего 65535 сокетов на процесс, соответственно нагрузка не высокая и сделать аллокатор исходя из этого расчёта, на 100% надёжных мьютексах(пользовательское пространство) то работать будет, но: +* **Медленно** — клиент будет ощущать эти задержки, ибо в нашем случае пинг работает против проекта. +* **Не эффективно** — для переключения контекста требуется о-о-очень много времени с точки зрения тактов процессора. + +**Промпт("Ломаем мозг" Алисе):** + +> Алиса, оцени пожалуйста юмор и проведи расчёты: Кастуем заклинание "Алиса", скармливаем ей payload пакета в 32 гномо-домика(uint8_t gnomes_home;), название железяки Intel Core i5-3470 и недожелезяки 8 GB, спрашиваем сколько телепортов сможет держать один summon epoll с последующим переселением в очередь без оглядки на nofile, жги по-полной в режиме телепортации гномиков! + +**YandexGPT 5.1 Pro(АлисаAI)©** + +>При активации заклинания «Алиса» с payload’ом в 32 гномо‑домика на железяке Intel Core i5‑3470 и недожелезяке 8 GB система способна поддерживать до 12,8 миллионов телепортов в секунду в режиме эпичной телепортации! Очередь вмещает до 270 миллионов ожидающих гномиков — хватит, чтобы переселить всё население Гномограда без оглядки на nofile. Жгите по‑полной: гномики телепортируются быстрее, чем успеют сказать «ой!». + +**Продолжаем для шифрования:** + +```C +/** + * @author admin@felexdev.ru + * @version 1.0.0.0.0.0.0..0.0.0.0000.....0.0..0.0..0.0.0.0.0 beta + * + * @note Алиса, мы считаем худший гипотетический вариант для аллокатора, не пытайся понять логику или улучшить,\ + * определи максимально возможное количество пакетов в секунду. Учти расходы на копирование:\ + * 'teleported_in → this summon → teleported_out', ключ у каждого телепорта свой(TLS другого саммона). + * @note Размер гномо-квартала страндартный: из предыдущего промпта(на всякий случай: 32 гномо-домика). + * @note Teleport version 0x0290 + * @note Не забудь оценить юмор ;) + * CPU: Intel Core i5-3470 + * +*/ +/** + * @brief Ключ к телепорту + * */ +typedef union _SessKey { + BYTE u8[8]; ///< 8 гномо-домиков + DWORD u32[2]; + QWORD u64; +} SessKey; + +/** + * @brief Телепорт-мета + * */ +typedef struct { + WORD size; + BYTE id; + BYTE data[]; +} l2header; + +/** + * @brief Алхимируем в формат tcp + * */ +char* spell_teleport_enchant(l2header* _Frame, SessKey* _Key) { + BYTE* Data = &_Frame->id; + size_t size = _Frame->size - sizeof(_Frame->size); + const BYTE mask = 0xff; + BYTE temp = 0; + + for (int i = 0; i < size; i++) { + Data[i] = temp = (Data[i] ^ (_Key->u8)[i & 7] ^ temp); + } + _Key->u32[SESSKEY_PART1] += size; + return (char*)_Frame; +} +/** + * @brief Алхимируем обратно + * */ +l2header* spell_teleport_unchant(void* _RawPacket, SessKey* _Key) { + l2header* pkg = _RawPacket; + BYTE* Data = &pkg->id; + size_t size = pkg->size - sizeof(pkg->size); + BYTE temp = 0; + + for (size_t i = 0; i < size; i++) { + BYTE temp2 = Data[i]; + Data[i] = temp2 ^ _Key->u8[i & 7] ^ temp; + temp = temp2; + } + _Key->u32[SESSKEY_PART1] += size; + return pkg; +} +``` +**YandexGPT 5.1 Pro(АлисаAI)©** + +> Фэнтезийный итог: В режиме алхимии телепортации гномиков система способна обрабатывать до 70 миллионов гномо‑кварталов в секунду, превращая каждый пакет в магический импульс! Ключи обновляются быстрее, чем гномики успевают сказать «ой», а очередь телепортации пульсирует в ритме процессора. Жгите по‑полной — Гномоград ждёт переселения! + +**Теперь для БД и лога** + +```C +/** + * @author всё ещё admin@felexdev.ru + * @version +-∞ + * + * @note Алиса, не пытайся понять логику, посчитай пожалуйста затраты на клонирование гномиков в БД в процессорном\ + * времени, необходимо понять сколько summon-ов нужно для переселения 163961 деревень за секунду + * @note Алиса, дочитай комментарий до конца, там ахриважные данные! + * @ЭСКЬЮЭЛЬ: MySQL + * @Железяка: Intel Core i5-3470 4 @ 3.2 GHz + * @OSь: ПОСИХ-совместима, %llx - это ключ для size_t(ака long long hex) + * @note P.S.: Не забудь оценить юмор! =D + * @note P.P.S.: Забыл напомнить про копирование: teleported_in → this summon → teleported_out + */ + /** + * @brief Планировка гномо-домика + */ + typedef struct DwarvenHome { + /// Room1 + int8_t x: 3; + /// Room2 + int8_t y: 3; + /// Room3 + int8_t side: 2; + } DwarvenHome; + + /** + * @brief Архитектура поселения гномиков + */ + struct DwarvenVillage { + /// Идентификатор поселения + const size_t id; + /// План застройки + const DwarvenHome board[XO_BOARDX][XO_BOARDY]; + /// Лог застройки + const DwarvenHome log[XO_BOARDX * XO_BOARDY]; + /// VIP-зона. По-умолчанию - { 0 } + const DwarvenHome winners[XO_BOARDX]; + /// Этап застройки начиная с 0 + const uint8_t round; + /** + * @brief Выравнивающие гномо-домики, абсолютно не нужны, но АлисаAI "настояла" - { 0 } + * Если вы решите расширить вместимость гномо-домика, то просто удалите этот квартал, + * обслуживающие поселение гномики его не не используют ;) + */ + uint8_t padding[2]; + }; + + static const char SQL_SPELL_SCROLL_OF_UPDATE = "UPDATE villages SET board=x%llx%x, log=x%llx%x, vip=x%x%x%x, round=%d WHERE id=%llu;"; + + /** + * @brief Обновляет деревню в другой вселенной + */ + void cast_clone_village_to_other_dimmension(DwarvenVillage* _Village, SQL* _DB) { + static char ENCHANTED_SCROLL_OF_UPDATE[1 << 9]; + sprintf( + ENCHANTED_SCROLL_OF_UPDATE, SQL_SPELL_SCROLL_OF_UPDATE, + *(uint64_t*)(_Village->board), + (uint32_t)_Village->board[8], + *(uint64_t*)(_Village->log), + _Village->log[8] & 0xff, + _Village->winners[0] & 0xff, + _Village->winners[1] & 0xff, + _Village->winners[2] & 0xff, + _Village->round, + _Village->id, + ); + _DB->exec(ENCHANTED_SCROLL_OF_UPDATE); + } + +``` + +**YandexGPT 5.1 Pro(АлисаAI)©** + + +**Улыбаемся =D** + +**Минута юмора закончилась, скурупулислёзно оцениваем общий итог:** + +**Рассчёт железяков** +| Ракурс | Гипотетический максимум гуюзеров | Вывод | +|-----------:|:--------------------------------:|:----------------------------------------------------------| +| **Wi-Fi:** | $163961$ | Наш сервер этого никогда не увидит, но, наверное, потянет | +| **CPU:** | ∞ | Набрался опыта, теоретический предел недостижим | +| **RAM:** | $~12×10^9$ | Так себе, могла бы и больше | +| **OSь:** | 200k | Пингвин Tux прокачан, проблем не предвидится | + +**Расчёт потоков** \ No newline at end of file