Многострадальческий опыт написания бота на С++ и почему это того стоит
Здорова всем бессонным. Тоже не спится, поэтому напишу небольшое сообщение. Как вы знаете - я большой любитель Плюсов (В принципе это мой любимый язык программирования)
Конкретно сегодня на повестке ночи - наш бот E.C.H.O, как мы уменьшели использование ОЗУ с ~80 МБ до 8 и причем тут вообще С++
Конечно, можно было пойти в оптимизацию Питона, но будем честны? Все угодно ты можешь написать на Питоне, а Питон ты можешь написать на С++ хвхвхвхвх. Та и вообще Питон это язык интерпретируемый (выполняется в реальном времени), со своей виртуальной средой, всякими наворотами и тд. А я напомню - Оперативки категорически мало!
Выбор очевиден - Компилируемый С++, но это же тяжело... Нихера, скажу я так! Было конечно пару проблем, но в целом путь самурая пройден. Расскажу про основные моменты:
А теперь у нас есть весь цикл для создания бота: От написание кода -> Тест на рабочем пк -> Сборка под сервер (релиз)
А главное:нахера зачем это все? Ну...
- Во-первых: Мне, как кодеру на С++, сложновато писать где-то еще (Особенно Питон 💀), ибо я любитель строгой типизации данных, структуры, перечисления, шаблоны, классы с ООПшкой, а также предкомпилируемые условия и вычисления (а.к.а. Макросы).
- Во-вторых: Если грамотно писать код, то создание переменных и аллокаций идет к минимуму = Меньше использование ОЗУ.
- Та и в принципе Питон и оптимизация это две несовместимые вещи. Кто-бы что не говорил, но вся оптимизации Питона упираются в вынесение функций в С++ код, который уже хоть как-то компилируется заранее (Вы OpenCV скачайте, сами увидите в консоли как он сидит компилирует С++ файлы лол)
Интересно ваше мнение: Сделать ли статью на telegraph и/или на Хабре? Расскажу про полную установку и настройку. Ибо раз уж я пишу этот пост - то значит уже давно решил все упомянутые выше проблемы (Бонусом тестовый проект с ботом прикреплю, чего мелочиться)
Мораль истории такова: Кто ищет оптимизацию, тот всегда найдет (Даже если это стоило 14 часов в Райдере)
Высыпайтесь
Здорова всем бессонным. Тоже не спится, поэтому напишу небольшое сообщение. Как вы знаете - я большой любитель Плюсов (В принципе это мой любимый язык программирования)
Конкретно сегодня на повестке ночи - наш бот E.C.H.O, как мы уменьшели использование ОЗУ с ~80 МБ до 8 и причем тут вообще С++
Все началось с сервера за полторы шаурмы в месяц - полностью оправдал себя. Вылетает так, что я и6ал. Хотя без прикрас - держится стабильно на Debian 11, но оставляет около 100 МБ ОЗУ
По началу у меня не было опыта работы с ТГ-Ботами, поэтому пошел по самому простому пути - закачал какие-то индуские библиотеки, с ИИшкой накинул на Питоне бота и ахерел от вылетов - Система, мягко говоря, ЧАСТЕНЬКО перезагружала бота от переполнения ОЗУ, а тот в свою очередь писал сообщение админам, мол, был перезапущен (По 2 раза в день 😭)
Конечно, можно было пойти в оптимизацию Питона, но будем честны? Все угодно ты можешь написать на Питоне, а Питон ты можешь написать на С++ хвхвхвхвх. Та и вообще Питон это язык интерпретируемый (выполняется в реальном времени), со своей виртуальной средой, всякими наворотами и тд. А я напомню - Оперативки категорически мало!
Выбор очевиден - Компилируемый С++, но это же тяжело... Нихера, скажу я так! Было конечно пару проблем, но в целом путь самурая пройден. Расскажу про основные моменты:
- Установка TgBot: Дааа, эту библиотеку фиг установишь, если не знаешь как работать с CMake
- Работа с CMake: У меня еще не было опыта в CMake, но с ним я познал удовольствия жизни и теперь если я скажу что CMake плохой то знайте - меня взломали :D
- Установка зависимостей: В Линуксе - pip install... (фанаты Линукса - ваш звездный час), а в Виндовсе... - Брр, абра кадабра, бадабум! АХ БИЛЛ ГЕЙТС РАЗРЕШИ МНЕ УСТАНОВИТЬ ЭТОТ ПАКЕТ В ВИНДУ ПЖПЖПЖ 😭 (Немного тяжко, но в целом vcpkg спас ситуацию)
- Сборка проекта под Линукс: Вот НИКОГДА не спрашивайте, как я это сделал. А, вы все еще тут? Ну в целом я сначала пошел собирать проект на сервере, но когда сервер ТУПО ПЕРЕЗАГРУЗИЛСЯ ОТ НАГРУЗКИ ХВХВХВХВ (Сборка не самая простая задача), то пошел билдить на своем пк и тут опять Билл Гейтс....
- Эмуляция Debian 11: Сука, да! Если нужно собрать бота на Debian 11, то думай как Debian 11! А ирония в том, что штатный WSL (Эмулятор Линукса для Винды) содержит в себе только Debian 12, который ну ни как не подходит для сборки проекта на Debian 11. Решение?
- Docker: Я не знаю, где я так нагрешил.... Но мне пришлось скачать Docker, чтобы с него как-то выкачать образ Debian 11 (эти овощи в Debian не дают скачать старые версии системы), установить систему в WSL и уже в WSL работать с Debian 11...
Пздц, я знаю. Но что теперь?
А теперь у нас есть весь цикл для создания бота: От написание кода -> Тест на рабочем пк -> Сборка под сервер (релиз)
А главное:
- Во-первых: Мне, как кодеру на С++, сложновато писать где-то еще (Особенно Питон 💀), ибо я любитель строгой типизации данных, структуры, перечисления, шаблоны, классы с ООПшкой, а также предкомпилируемые условия и вычисления (а.к.а. Макросы).
- Во-вторых: Если грамотно писать код, то создание переменных и аллокаций идет к минимуму = Меньше использование ОЗУ.
- Та и в принципе Питон и оптимизация это две несовместимые вещи. Кто-бы что не говорил, но вся оптимизации Питона упираются в вынесение функций в С++ код, который уже хоть как-то компилируется заранее (Вы OpenCV скачайте, сами увидите в консоли как он сидит компилирует С++ файлы лол)
Интересно ваше мнение: Сделать ли статью на telegraph и/или на Хабре? Расскажу про полную установку и настройку. Ибо раз уж я пишу этот пост - то значит уже давно решил все упомянутые выше проблемы (Бонусом тестовый проект с ботом прикреплю, чего мелочиться)
Мораль истории такова: Кто ищет оптимизацию, тот всегда найдет (Даже если это стоило 14 часов в Райдере)
Высыпайтесь
❤4👍1🔥1
𝐑𝐨𝐨𝐭𝐓𝐨𝐨𝐥 𝐁𝐥𝐨𝐠
Накиньте ❤️/🔥 если вам интересно про них (И выпуск исходники в открытый доступ конечно)
Оке-оке-оке, как и обещал! Только что выложил 3 легковесные библиотеки для Ардуино, которые я сам использую в ASAI:
Вся документация грамотно расписана, примеры присутствуют. Функционала в них по минимуму, чисто MVP (Минимально Рабочий Продукт)
Будут какие-либо вопросы, баги или предложения - обращайтесь ко мне в чате или ЛС
GitHub:
RootTM1637 - https://github.com/RootTool0/RootTM1637
RootDS1302 - https://github.com/RootTool0/RootDS1302
RootEncoder - https://github.com/RootTool0/RootEncoder
Have fun!
- RootTM1637 - Управление 4-значными 7-сегментными дисплеями на базе TM1637: Вывод времени, управление точкой и яркостью
- RootDS1302 - Работа с модулем времени DS1302: Установка и чтение времени
- RootEncoder - Опрос энкодеров с неограниченным подсчётом кликов + события удержания + обратный вызов (callback) через лямбды
Вся документация грамотно расписана, примеры присутствуют. Функционала в них по минимуму, чисто MVP (Минимально Рабочий Продукт)
Будут какие-либо вопросы, баги или предложения - обращайтесь ко мне в чате или ЛС
GitHub:
RootTM1637 - https://github.com/RootTool0/RootTM1637
RootDS1302 - https://github.com/RootTool0/RootDS1302
RootEncoder - https://github.com/RootTool0/RootEncoder
Have fun!
❤3🔥1
Unreal Engine 5.5.4 не перестает удивлять
@todo в будущем мы должны создать этот UObject и иметь детальную настройку для отображения разных вещей. Последовательность действий по умолчанию для игры на этой скелетной сетке
(todo - маркер для программистов, что нужно сделать на будущее)
@todo в будущем мы должны создать этот UObject и иметь детальную настройку для отображения разных вещей. Последовательность действий по умолчанию для игры на этой скелетной сетке
(todo - маркер для программистов, что нужно сделать на будущее)
🥰2😁2
Небольшой тул для быстрой замены BP в С++ с сохранением параметров
Знаю-знаю, первый вопрос: "Replace Selected Actors with... + Copy Properties" ?
Но копирование параметров не работает, когда разговор идет о замене БП класса в С++ (Ибо в Анриле это совершенно 2 разных класса, штатное копирование не сработает)
Решение - минимально рабочий тул. Просто спавните этот класс в мире, выбираете БП и С++ класс, а затем нажимаете на кнопку "Replace Classes" ¯\_(ツ)_/¯
Единственная особенность - параметры для переноса прописываются в коде (выделено отдельной зоной, строки 38-48)
В небольшой фиче могу сказать, что есть возможность откатить изменения (Ctrl+Y, Ctrl+Z)
продолжаю переписывать бекенд ага
Знаю-знаю, первый вопрос: "Replace Selected Actors with... + Copy Properties" ?
Но копирование параметров не работает, когда разговор идет о замене БП класса в С++ (Ибо в Анриле это совершенно 2 разных класса, штатное копирование не сработает)
Решение - минимально рабочий тул. Просто спавните этот класс в мире, выбираете БП и С++ класс, а затем нажимаете на кнопку "Replace Classes" ¯\_(ツ)_/¯
Единственная особенность - параметры для переноса прописываются в коде (выделено отдельной зоной, строки 38-48)
В небольшой фиче могу сказать, что есть возможность откатить изменения (Ctrl+Y, Ctrl+Z)
продолжаю переписывать бекенд ага
❤🔥2🔥1🤩1
This media is not supported in your browser
VIEW IN TELEGRAM
⚡️Разработчики Portal: Solver портировали игру на.. ноду Texture Sample
Респект за оптимизацию 👍
Респект за оптимизацию 👍
👍5🤯1
Задачка по С++ со звездочкой
Пока болею,заставили решил пройти олимпиаду по ИИ. Есть такая простая (на первый взгляд) задачка. Условия на картинке, ограничения:
- Максимальное время выполнения: 1 секунда
- Максимальное использование памяти: 256 МБ
- Стандарт С++: С++20
- Входные значения: В диапазоне от 1 до 10^18 (включительно)
- Цель: Добиться
Скажу сразу:
- Компилируемые языки будут эффективнее, чем интерпретируемые
- Используйте тип
- Если решать задачу в лоб, у вас выйдет примерно
Оставлю тут небольшую обводку:
А дальше сами. Удачи :)
через пару часов пришлю подсказку
Пока болею,
- Максимальное время выполнения: 1 секунда
- Максимальное использование памяти: 256 МБ
- Стандарт С++: С++20
- Входные значения: В диапазоне от 1 до 10^18 (включительно)
- Цель: Добиться
O(1) (Это реально)Скажу сразу:
- Компилируемые языки будут эффективнее, чем интерпретируемые
- Используйте тип
unsigned long long (а.к.а. uint64_t)- Если решать задачу в лоб, у вас выйдет примерно
O(2^(a+b)) - что овердохераОставлю тут небольшую обводку:
#include <iostream>
#include <cstdint>
uint64_t f(const uint64_t& a, const uint64_t& b){
// Реализация функции...
}
int main() {
uint64_t a, b;
std::cin >> a >> b;
std::cout << f(a, b);
return 0;
}
А дальше сами. Удачи :)
через пару часов пришлю подсказку
❤5🔥1🤯1
Продолжая решать задачку со звездочкой
Все, кто пошли решать задачу "в лоб" - посочувствую вам. ибо... там буквально нечего делать ¯\_(ツ)_/¯
Вместо глухого расхода бумаги и времени, давайте лучше.. визуализируем задачу? В комментариях пришлю полный код (чтобы не переполнять этот пост)
Могу лишь намекнуть на то, что такое странное расположение a и b выбрано не случайно - это именно оси x и y в привычном понимании прямоугольной системы координат, сечете?
(Накинул еще немного цветов чисто для удобства)
Что могу сказать? Ну.... Диагональ всегда равна единице. То есть можно сделать неплохое умозаключение, что если a == b, то это будет единица, а это копеечка в оптимизацию как никак!
Но да ладно, сделаем важное наблюдение - Чем больше "a" и чем меньше "b", тем больше результат. Такое чувство, будто тут пахнет делением одно на другое....
Не сдавайтесь, мы совсем близко
Все, кто пошли решать задачу "в лоб" - посочувствую вам. ибо... там буквально нечего делать ¯\_(ツ)_/¯
Вместо глухого расхода бумаги и времени, давайте лучше.. визуализируем задачу? В комментариях пришлю полный код (чтобы не переполнять этот пост)
Могу лишь намекнуть на то, что такое странное расположение a и b выбрано не случайно - это именно оси x и y в привычном понимании прямоугольной системы координат, сечете?
(Накинул еще немного цветов чисто для удобства)
Что могу сказать? Ну.... Диагональ всегда равна единице. То есть можно сделать неплохое умозаключение, что если a == b, то это будет единица, а это копеечка в оптимизацию как никак!
Но да ладно, сделаем важное наблюдение - Чем больше "a" и чем меньше "b", тем больше результат. Такое чувство, будто тут пахнет делением одно на другое....
Не сдавайтесь, мы совсем близко
🔥3❤1👍1
Ответ на задачу со звездочкой
сорьки, болею, сил нет часто писать посты
Как и говорил в прошлом посте, можно заметить закономерность, что чем больше "a" и чем меньше "b", тем ответ близится к "a" (Обратите внимание на горизонтальный ряд при b = 1 - он совпадает с числами в "a")
А также если привести пару контр-примеров, то можно заметить как "a" зависит от "b", это....целочисленное деление!
Бинго, дамы и господа. Осталось только внести правки в код, и мы добились выполнение функции от
Финальный код (ответ на задачу):
Be smart. Think cold
сорьки, болею, сил нет часто писать посты
Как и говорил в прошлом посте, можно заметить закономерность, что чем больше "a" и чем меньше "b", тем ответ близится к "a" (Обратите внимание на горизонтальный ряд при b = 1 - он совпадает с числами в "a")
А также если привести пару контр-примеров, то можно заметить как "a" зависит от "b", это....
Бинго, дамы и господа. Осталось только внести правки в код, и мы добились выполнение функции от
O(2^(a+b)) до O(1)Финальный код (ответ на задачу):
#include <iostream>
#include <cstdint>
uint64_t f(const uint64_t& a, const uint64_t& b)
{
if(a == 0 && b == 0) return 1;
if(a == 0 || b == 0) return 0;
if(a < b) return 0;
return a / b;
}
int main()
{
uint64_t a, b;
std::cin >> a >> b;
std::cout << f(a, b);
return 0;
}
Be smart. Think cold
🔥4❤1😍1