Простір для вивчення нової професії, зростання в кар’єрі або розвитку бізнесу👇🏻
Наша команда пише для вас найкращі та найцікавіші матеріали, які обов’язково допоможуть у вашому навчанні: https://genius.space/lab/
Last updated 3 weeks, 5 days ago
Performance by design
В попередньому дописі я зробив маленький сервіс який скриншотить твітер.
Зазвичай все що я пишу на Java то роблю на Spring Boot, через багату та зрозумілу екосистему та відносну швидкість розробки.
Цього разу для загального розвитку взяв vert.x, який заявлений найшвидшим Java-фреймворком згідно з результатами Ultimate Web Frameworks Benchmark.
Мій проєкт складається лише з двох ендпоїнтів — /health
для перевірки чи все ок та /api/screenshots
власне для скриншотів, тому бойлерплейту було мінімум.
Але що мене відразу вразило, так це те що фреймворк за замовчуванням виставляє таймаути на обробку HTTP-запитів. Якщо час виконання перевищує софт-ліміт, то в лог пишеться повідомлення:
Thread Thread[vert.x\-eventloop\-thread\-0,5,main] has been blocked for 2031 ms, time limit is 2000 ms
Якщо ж час обробки перевищує хард-ліміт, то ліба викидає експешн:
io.vertx.core.VertxException: Thread blocked
at java.base/java.lang.Thread.sleepNanos0(Native Method)
at java.base/java.lang.Thread.sleepNanos(Thread.java:491)
at java.base/java.lang.Thread.sleep(Thread.java:559)
at java.base/java.util.concurrent.TimeUnit.sleep(TimeUnit.java:446)
at me.rozhkov.snapshottr.App.handleScreenshotRequest(App.java:79)
При цьому код продовжує працювати, але експешн буде в логах.
Це чудовий приклад коли швидкодія закладається самим фреймворком та спонукає розробника думати як організувати обробку, щоб вкладатися в ліміти.
Я завжди виступаю за sane defaults, бо в сучасному світі занадто багато опцій, варіантів, прапорців, та перемикачів, щоб конфігурувати то все кожного разу.
Можливо у Spring Boot теж є таке налаштування, але його треба додатково увімкнути. Розробники роблять все на своїх машинах та не задумуються про швидкодію, поки не прийде час стрес-тесту, але тоді вже може бути запізно.
Раніше я вже згадував про автоматичне логування реквестів, SQL-запитів та часу їх виконання у Rails. Вважаю що це має стати стандартом усіх таких бібліотек. Чим прозоріше для нас, розробників, те, що виконується на сервері та скільки часу воно займає, тим більше можливостей писати відразу нормально, а не як-небудь.
Уявіть проходити мільйон співбесід по алгоритмах та системному дизайну, щоб потім влаштуватися у твітер та писати неймовірно тормозний сервіс, який віддає вам твіт цілу вічність, не може відразу завантажити тред, а глибина дом-дерева може позмагатися з глибиною node_modules того недолугого фронтенду який змогли написати олімпіадники. Це абсолютна ганьба та дискредитація інженерного ремесла від тих, хто заявляє найвищі вимоги до наших вмінь. Пруф що твітер можна зробити швидким та нормальним я вже давав — це Nitter.
Пишуть що Premature Optimization is the Root of all Evil, але я з цим не погоджуюсь. Нормально роби — нормально буде, і для цього не треба витрачати надмірно багато часу та зусиль. Просто з початку задайте собі адекватні обмеження та дотримуйтесь їх.
☝️Практична порада
?Подивіться чи підтримує ваш фреймворк схожу функціональність та увімкніть її.
#інструменти
permalink | @full_of_hatred
?Щоденні донати?на ЗСУ?
?@Donate1024Bot
Телеграм-бот для скриншотів твітера
У нас в телеграм-чаті каналу часто приносять посилання на твітер. Дивитися їх незручно, бо ти тикаєш посилання, щоб почитати коротенький текст. Логічно було б цей текст вставляти в прев'ю лінка, але твітер так робити не буде, бо їм потрібен енгейжмент.
Якось прочитав у блозі Swizec Teller пост про те як він зробив скріншотилку інстаграма на лямбді. Згадав про це і подумав — давай і собі зроблю! Впевнений що таких проєктів є ціла купа, але я хотів отримати задоволення від розробки, бо люблю робити продукти та програмувати?.
Колись давно я хотів зробити бота який буде автоматично банити за матюки, проєкт провалився і зараз цей бот просто рахує статистику повідомлень (хто більше написав) та робить ще деяку дрібну роботу. Вирішив його розширити.
ШІ швидко підказав потрібний код:
def screenshot(link)
browser = Ferrum::Browser.new({browser\_options: {'no\-sandbox': nil}})
begin
browser.go\_to(link)
browser.network.wait\_for\_idle(duration: 2, timeout: 30)
path = "tmp/tweet\_\#{Time.now.to\_i}.jpeg"
browser.screenshot(path: path, selector: 'article[data\-testid="tweet"]', quality: 95, format: "jpeg")
path
rescue StandardError => e
Rails.logger.error("Error capturing screenshot: \#{e.message}")
nil
ensure
browser.reset
browser.quit
end
end
За 5 хв протестив локально — все працює як треба! Заливаю, не працює. WTF?
Починаю розбиратися. Спочатку думав що проблема в alpine на якому зібраний базовий образ. Потім думав що проблема у твітері який блокує запити. Потім в, тому що недостатньо пам'яті. Потім в, тому що браузер закривається. Перевів з альпіну на дебіан, переконався що курли на твітер з хоста проходять, додав пам'яті, зробив браузер перзистентним.
Але все одно скриншоти робились через раз. Я витратив ще купу часу на різних форумах у спробах розібратися що ж не так, адже все було максимально просто — бібліотека то тонкий врапер над процесом хроміума, там нічому було ламатися.
Врешті я здався і вирішив переписати все на Java. ШІ швидко підказав потрібний код на Selenium:
driver.get(url);
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
WebElement element = driver.findElement(By.cssSelector(cssSelector));
File screenshotFile = element.getScreenshotAs(OutputType.FILE);
Я нашкрябав вебсервіс який би виставив ендпоїнт до інтернету. З минулого разу я згадав про Ulitimate Web Frameworks Benchmark, і такий думаю, давай не буду брати Spring Boot, а візьму vert.x. Сказано—зроблено—задеплоєно. Запускаю — не працює?
Хром видає якісь крипто помилки, нічого не гуглиться. Заходжу на хост, запускаю хроміум вручну, той пише OOM. Фух, ясно, даю машині більше пам'яті, вуаля — все працює.
❓Наступна проблема—браузер не встигає завантажити прев'ю картинки або відео, які є у твіті. На жаль, я не знайшов як це нормально вирішити, тому просто додав 5 секунд очікування після відкриття сторінки. Можливо читачки та читачі підкажуть як більш елегантно це розв'язати?
Ну все, чатботи крутяться, скриншоти мутяться. Додав туди ще код який буде відповідати в телеграм, бо не хотілося робити муторну інтеграцію з основним сервісом.
Потім подивився що скриншоти треба в рамку, бо телеграм їх обрізає по висоті. Додав паддінгу 50px та й вспокоївся.
Три доби — жодної помилки, пам'ять не протікає, в середньому скриншот робиться за 7 секунд. Як на мене, це дуже багато, але вище написав що не знаю як виправити таймаут.
Бот — @chat_keeper_bot. Ви можете додати собі його в будь-який чат, і він теж буде працювати.
#проєкти
permalink | @full_of_hatred
?Щоденні донати?на ЗСУ?
?@Donate1024Bot
Ruby on Snails: 1 req/sec
Нещодавно один відомий консультант по перформенсу рельс написав твіт, де стверджував що більшість Rails апок тримають 1.5 req/sec на одному ядрі й тому треба мільйони vCPU, пам'яті та серверів, щоб воно хоч якось працювало.
Надзвичайно контроверсійна заява яка породила відповідну реакцію спільноти, де різні люди заявляли що в них все працює як мінімум в 10 разів швидше.
Згодом по треду виявилося, що 1.5 req/sec це те що автор бачить на своїх консалтингових проєктах. Тобто не всі проєкти, а ті, куди його запрошують (очевидно, з перформенс проблемами). І не нормально написані проєкти, а нездало написані. І основна проблема не в повільному Ruby, а в I/O до бази. Короче як в тому анекдоті, «— Чули Рабінович виграв мільйон у лотерею? — Все так, тільки не Рабінович, а Петренко, не мільйон, а тисячу, не в лотерею, а в карти, і не виграв, а програв».
Я звичайно крінжанув з поста, потім крінжанув що люди ганьблять Ruby, потім пішов дивитися скільки ж тримає сайт https://donate1024.org/
Поставив модну зараз програму oha, запустив у 20 потоків на 30 секунд: oha \-c 20 \-z 30s \-m GET \-\-latency\-correction \-\-disable\-keepalive \-\-redirect 0
https://donate1024.org/
і отримав наступний результат:
```
Summary:
Success rate: 100.00%
Total: 30.0017 secs
Slowest: 18.8368 secs
Fastest: 0.2681 secs
Average: 1.1295 secs
Requests/sec: 9.7328
Total data: 2.68 MiB
Size/request: 10.11 KiB
Size/sec: 91.64 KiB
Response time distribution:
10.00% in 0.4612 secs
25.00% in 0.5410 secs
50.00% in 0.6348 secs
75.00% in 1.0161 secs
90.00% in 1.9351 secs
95.00% in 2.4722 secs
99.00% in 16.0569 secs
99.90% in 18.8368 secs
99.99% in 18.8368 secs
```
~10 req/sec на одному ядрі з ±нормальним p95, бо сервер в мене найдешевший: shared\-cpu\-1x@512MB
Ця сторінка звісно не рендерить нічого такого, але десяток запитів в базу і яка-не яка логіка присутня. Звісно всі запити оптимізовані по максимуму, але все ж.
Маю гіпотезу, що більшість часу що витрачається, це не Ruby, а I/O в базу. Тобто якби сюди запулити джаву, то результат був би не набагато кращим, бо код аплікейшена це десятки мілісекунд, стислися б вони у два рази, в загальній частці це не дало б суттєвого прискорення. Щоб перевірити, може знайду час написати два ідентичних сервери на Ruby та Java і порівняти.
І це я просто написав нормальний код. Простору для оптимізацій ще багато: додати кешування, оптимізувати рендерінг HTML (замінити стандартний шаблонізатор ERB на Phlex). Якщо запаритися, то гадаю, що вдалося б покращити результат вдвічі.
Я ж зупинився на тому, що в мене сторінка віддається за 300 мс.
Тому сміливо пишемо на тому, що подобається, оптимізуємо дані та SQL запити, а всім хейтерам які заявляють про тормознутість вашого рантайму у порівнянні з джавою/растом/го сміливо ~~плюємо в обличчя~~ ставимо реакцію клоуна.
P.S.: я звичайно не метр перформенсу, але ще 4 роки тому писав про те що корені всіх проблем веб апок — це запити в базу даних.
P.P.S.: особливо прискіпливі можуть сходити на TechEmpower Web Framework Benchmarks та подивитися, що Spring не набагато швидший ніж Rails, Laravel та Django повільніші, а виграють не фреймворки, а голі бібліотеки вебсерверів.
#робота
permalink | @full_of_hatred
?Щоденні донати?на ЗСУ?
?@Donate1024Bot
Олімпіадники strikes back
Щодня @Donate1024Bot надсилає своїм підписникам звіти по завершених зборах. Це посилання на соцмедіа, відео з фото та супровідний текст.
Деколи ті звіти не відправляються через костурбатість Telegram Bot API:
- Текст до картинок не може бути довшим ніж 1024 символи. Щоб запобігти цьому обмеженню я додав у себе в адмінці валідацію на розмір тексту
- Файлів з медіа не може бути більше ніж 10. Щоб уникнути цієї помилки я просто брав перших 10 файлів, якщо випадково в адмінці додавав більше при створенні звіту
І найнапряжніше це document can't be mixed with other media types
. Олімпіадники Дурова не змогли зробити одночасну відправку різних типів файлів. Найчастіше у мене ця помилка падає коли випадково разом з JPEG файлами додав PNG. Також неможливо відправити PDF або щось інше разом з картинками.
В чому проблема це зробити для мене загадка. Хоче користувач додати одним повідомленням кілька картинок різних форматів, відео, та бінарний файл — ну покажи замість прев'юшки іконку файлу і все.
?А найцікавіше що джипег та відео можна відправити одним повідомленням! Чому не можна одночасно відправити PNG та JPEG?
Signal до речі, теж цим страждає. Тупе обмеження яке програмісти придумали напевне щоб спростити собі життя.
Рік я ігнорував цю проблему і коли телеграм не хотів відправляти мій звіт користувачам, то це попадало в Sentry, а далі я вже вручну дивився що не так і переробляв звіт.
Але врешті мені воно надоїло і я додав «тестування» звіту: при його створенні відразу відправляти у приватний чат. Таким чином я точно знатиму що звіт валідний та буде належним чином доставлений користувачам.
Інтеграційне тестування на продакшені?
#проєкти
permalink | @full_of_hatred
?Щоденні донати?на ЗСУ?
?@Donate1024Bot
Збір на абонплату старлінків
upd: збір завершено, всім дякую!
Вітаю шановне товариство!
?Шо ви там, оновили дані? Вже думаєте куди податися чи обираєте гідрокостюм?
?Працюю над тим щоб запропонувати вам дещо цікаве?
??Ну а поки що прошу допомогти моїм друзям з проплатою старлінків.
Зараз на балансі маю 4 старлінки: 3×95$ та 1×59€
На перших трьох вже борг 190$? Не хотілося б щоб кенти випадково залишилися на позиціях без зв'язку.
Щоб два рази не вставати пропоную зібрати 30000₴ — на кілька місяців вперед.
Банка: https://send.monobank.ua/jar/A9WetxuXih
Приват: 4627055113374002
PayPal: [email protected]
Чеки — в коментах до цього посту.
Дякую всім за допомогу!
P.S.: генератор, старлінк та щогла з попереднього збору успішно пережили дуже близьку роботу 120, 122, 152 та ще бозна чого і продовжують допомагати ✊
Привіт усім!
Хто не встиг задонатити на старлінки, може надолужати донатом на пікапа L200 (саме він на фото) для моїх файних друзів з особливих військ?
Хлопці наводили суєти на різних цікавих напрямках, а щоб наводити ще більше суєти завжди потрібен транспорт.
Частину суми вже зібрали силами приватних донорів, залишилось прибизно 1600$.
Банка на мого товариша: https://send.monobank.ua/jar/9MDYEDfZBg
Якщо маєте можливість позолотити ручку на paypal, ось: [email protected]
Принципові фани державних банків можуть закинути гроші на мій приват: 4627055113374002
Дякую всім за донати!??
?Дякую всім!
Зібрано 24,117.99₴
Витрачено 21,706.93₴
Залишок 2,411.06₴ піде в оплату наступних періодів.
Ще раз дякую всім хто підтримав збір?
Прочитав «Убік»/«Ubik» та «Чи мріють андроїди про електричних овець?»/«Do Androids Dream of Electric Sheep?»
Втомився від селф-хелпу та бізнес літератури, та вирішив надолужати лауреатів премій хуго, неб'юла.
«Убік»
Дуже дивно читати книги, ідеї з яких ти вже бачив у багатьох фільмах. Виявляється що матрицю та inception придумали ще у 60-і роки, а ми, замість першоджерела, дізнаємося це з химерних та блідих адаптацій.
Книжка починається як бадьорий кіберпанк, але досить швидко трансформується в абсолютно психоделічне оповідання з примарною межею між реальністю та галюцинаціями. Спойлерити не буду, якщо вам сподобався Inception, то прочитайте й це, тим більше що вона досить коротка.
«Чи мріють андроїди про електричних овець?»
Як поцінювач кіберпанку та блейд ранерів маю з соромом зізнатися що до книги добрався тільки зараз. Традиційно, фільми мають лише поверхневий стосунок до книг.
Надзвичайно депресивне оповідання, після якого хочеться ~~кинути петлю на шию~~ лежати й нічого не робити як райан гослінг в кінці другого фільму. Маю чутливість до смертей тварин, а тут їх достатньо щоб зіпсути настрій на цілий день.
У фільмах абсолютно не згадується релігійний аспект та програмування емоцій, яким тут надано багато значення. Я тему не викупив. У мене взагалі трохи туго з розумінням глибинних сенсів, тому порожня пригодницька бойова фантастика мені заходить добре, а складні психологічні трилери та драми у фантастичних сетінгах — недуже.
Втім, до прочитання рекомендовано.
#прочитав
permalink | @full_of_hatred
?Щоденні донати?на ЗСУ?
?@Donate1024Bot
Простір для вивчення нової професії, зростання в кар’єрі або розвитку бізнесу👇🏻
Наша команда пише для вас найкращі та найцікавіші матеріали, які обов’язково допоможуть у вашому навчанні: https://genius.space/lab/
Last updated 3 weeks, 5 days ago