Ну у вас это жаба… у нас nodejs. Возможных настроек минимум. На пиковых нагрузках GC заметно тормозит когда создается очень много short-lived объектов. Можно конечно расти вертикально пока не упрешься в потолок или бюджет… и все же, просто игнорировать GC и другие накладные расходы в статьях про ФП это как-то не правильно.
У вас никогда не было задержек в 15-30 секунд когда gc останавливает все что бы очистить память? Задача задаче рознь. Одно дело в воркере что то делать, с этим еще можно жить. А вот в веб сервере, когда это напрочь убивает весь перформанс, уже другое.
Самое простое например у нас, это работа с календарем. 365 дней в году.
Разная метадата на каждый день, потом накидываем всякие бизнес рулы на каждый день в отдельности, вот уже память и скачет.
Нет, конечно по возможности делаем прекалькулейшен и храним где-то, но по большому счету очень много операций синхронных, когда ответ нужно дать asap, бывает один такой вот тяжелый ендпоинт не дает спать по ночам, когда алерты приходят =))
Конечно создание всегда новых объектов избавляет от неприятных багов в многопоточном программировании. Или даже в JS где один поток, можно намудрить так что объект будет изменен кем-то другим по ссылке, это как бы здорово… если бы не GC который будет забирать у вас 80% CPU тупо на очистку памяти…
А в остальном, сколько не пытаются преподнести фп как спасение от всех бед, на практике, как я вижу, используется в очень узких кругах… и в очень специфических задачах.
Я лично использую только для простенькой фильтрации или трансформации небольших объектов когда знаю что их количество ограничено числом N, и это число меня устраивает.
Ну как не для админов. У нас были бородатые дядьки которые не подпускали нас к базе. У нас был доступ только к вызову процедур с параметрами. Все процедуры писались этими дядьками. Серьезные мужики такие. Казалось они на SQL могут операционку написать.
Когда был баг, они открывали процедуру, и начинали шаманить. Делалось это так:
Сначала с утра слышны крики — «Как это возможно? Вчера же работало?»
Потом они открывают файлик с процедурой на 1000 строк и охреневают. Это я писал?
Копируют эти 1000 строк и вставляют рядом с комментом «revision +100500, fixing bla bla bla»
На лету фиксят че-та, и пушат в базу
Это был ад в плане мейнтененса и разработки фичеров.
Поэтому мы перенесли бизнес-логику Lingualeo в базы данных на PostgreSQL
А вы знаете толк в извращениях. Разработчиков не жалко? Всегда покрывался холодным потом когда смотрел как MS SQL DBA ищут и фиксят баги в процедурах… копипастят и комментят код (ручной гит лол).
Больше чем уверен что сейчас там все красиво. Можно статейку через годик-два о том как вы это все дебажите, ревертите и т.д?
Перестаньте переводить и тащить сюда эти бесполезные и банальные статьи от Indrek Lasn которые он клепает чисто для маркетинга. Пользы от них — ноль. Его на медиуме в комментах разносят за это… а вы сюда тащите.
з.ы.
Чему вы научитесь создав клон google?
— делать поиск
Что вы такое пишете что дошли до измерения производительности основных конструкций языка? По моему это бесполезные измерения… Premature optimization во всей красе…
Не понял зачем столько телодвижений, если можно указать что бы socket.io как клиент так и сервер юзали только websocket без всяких там поллингов, просто добавлением конфига? Да и размер второй версии для клиента ~20kb, а на серваке пофиг… ниче не понимаю.
Сравнение сокета с ее же оберткой? :/
For instance, think about broadcasting a message to every connected client: with Socket.IO is just one method (.broadcast), but in vanilla WebSockets you’ll have to implement it on your own, so you’ll have to rethink about the way it works.
О боже как трудно написать проход по массиву клиентов =))
Вначале это тоже был монолит. Потом его разбили на сервисы, воркеры и т.д. А теперь еще и на майкро. Вот и получилось в конце что все в монорипо.
Один из реальных способов поддерживать общий стиль и единообразие между микросервисами — держать их в одном репо.
Это не про монорепо?
Да и знаю я про гугл и про фейсбук. Но увы, на практике у нас где то 40 девелоперов и ci реально стал проблемой. Поэтому было принято решение сверху о разделении на собственные репозитории. Конечно разрабатывать так сложнее, но должно ускорить деливери.
1. Service discovery
2. Graceful shutdown
3. Logging
4. Metrics
В нашей компании мы пишем на ноде. Но есть вещи которые работали бы намного эффективнее на GO. Но сейчас внедрить GO это проблема, потому сервисы на ноде основываются на обертке, которая и занимается теми вещами которые я перечислил. И что бы втиснуть в экосистему бинарник на GO, мне нужно будет обеспечить работу с консулом и т.д. А это уже выходит за рамки того что я как разработчик сервиса хочу делать. Обидно. А хочется просто кинуть бинарник, и что б работало =)
Ну во первых — это красиво… шучу. Мы от джеста отказались в силу того что слишком много магии. Кроме того, даже он иногда не справлялся с тем ужасом который у нас в коде.
Мое мнение такое, что жест и други кастыли в виде rewire или proxyquire появились именно потому что код писали криво, а тестировать то хоть как-то хотелось. Мы в большом проекте говна нахавались, когда тесты падали тупо после изменений имени файла, порядка выполнения или количества кейсов. Потому что люди волшебными тулзами то мокали, то где то забывали, а память то общая… потом сиди 2 дня дебаж что бы понять где забыли вернуть состояние.
Нет, ну можно конечно запускать по процессу на файл, но тогда тесты у нас вместо 10 минут будут час бежать.
А также это помогает избежать очень неприятных багов в виде cycle dependency. Да и с синглтонами тоже жизнь та еще…
Да, согласен, DI без статики то еще удовольствие. Зато в тестах никакой магии. Часто даже к sinon обращаться не надо. Дактайпинг во всей красе.
Опять же, без фанатизма. Инжектить не значит что щас мы lodash будем пробрасывать. Но вот DAO, Repository, http, queue, db и т.д. инжектим.
Ну еще из плюсов, легче собирать из этих кубиков нужный функционал. А когда все друг другу require делают, система превращается в Big ball of mud.
Так же легче перетаскивать отдельный компоненты например в отдельный сервис.
У вас может быть другой опыт и мнение. Не претендую на истину, но вот вот как-то так…
З.Ы.
Хочу заметить речь не идет о DI фреймворках… их я тоже не очень люблю. Не люблю магию и implicitly. Но на вкус и цвет…
Понятно. Нам еще не завезли =))
Вот переедем на десятую ноду, сколько новых способов будет выстрелить себе в ногу… ну или голову =)
Просмотрел бегло лекцию. В принципе, проблема в том что люди думают что промисы волшебным образом делают код асинхронным. А то что это итератор или любой другой сахар или фича — не важно. Под капотом тот же промис. И тут я думаю было бы очень полезно показать как работает современная версия евент лупа. Когда понимаешь на каком этапе работает тот или иной код, все встает на свои места.
Я в принципе согласен. Большинство тех разработчиков которых знаю и с которыми работаю и не слышали про SOLID. Большинство просто херачит код не парясь о каких-то там паттернах т.д.
Многие пишут не понимая даже что такое процесс, треды и общая память, и чем это светит например в тестах. Ну да ладно… Но у меня есть одна маленькая победа — все таки я смог донести до большинства в компании зачем нужен Dependency Injection =))
И хоть сам копаюсь в ноде довольно глубоко, даже с libuv играюсь в XCode, можно подробнее о «await блокирует event-loop»? Это же вроде просто сахар к промисам. И если операция асинхронная, то await отработает так же как и промис. Или вы о том когда разработчик делает async/await на синхронную функцию и ожидает что функция волшебным образом станет асинхронной?
При создании дампа кучи принудительно запускается сборщик мусора. В результате нам не нужно беспокоиться о тех объектах, которые могут быть удалены сборщиком мусора в будущем, но пока находятся в куче. То есть — об объектах, при работе с которыми утечек памяти не происходит.
Не очень понимаю… Как мне в дампе отличить объекты которые не будут удалены никогда от объектов «которые могут быть удалены сборщиком мусора в будущем»? Ведь если я запустил дамп когда у меня сотни или тысячи реквестов которые еще не закончили свою работу, в дампе будет много данных. Как понять где утечка среди всего этого?
Вот у нас бежит сервис в проде. Сервис писался лет 5. Там все: экспресс, раббит, любимый ивент емиттер. На нью-релике видим память бежит. Но бежит ооооочень медленно. Обычно до out of memory не доходит потому что деплоим часто.
Так вот когда открываешь дамп этого чуда, там столько всего… Сервис живой получает огромное количество запросов, отправляет месседжы и т.д. Пока что вот так в лоб скачиванием дампа найти утечку не удалось :/
Вообще в голове крутится сделать вот так:
1. Запустить сервак
2. Сделать дамп
3. Поставить сервак под лоад-балансер и дать недельку поработать
4. Вывести сервак из-под лоад-балансера. Удостовериться все реквесты и отложенные функции закончили работать.
5. Сделать дамп
6. Сравнить и надеяться на удачу
Может еще какие техники посоветуете? Ну или если я ошибаюсь, ткните носом :)
Я код пишу в темной теме и нормально… А вот логи смотреть в кибане или тот же стаковерфлоу читать — не переношу в темных цветах. Не знаю почему так, но не комфортно Ж/
У вас никогда не было задержек в 15-30 секунд когда gc останавливает все что бы очистить память? Задача задаче рознь. Одно дело в воркере что то делать, с этим еще можно жить. А вот в веб сервере, когда это напрочь убивает весь перформанс, уже другое.
Самое простое например у нас, это работа с календарем. 365 дней в году.
Разная метадата на каждый день, потом накидываем всякие бизнес рулы на каждый день в отдельности, вот уже память и скачет.
Нет, конечно по возможности делаем прекалькулейшен и храним где-то, но по большому счету очень много операций синхронных, когда ответ нужно дать asap, бывает один такой вот тяжелый ендпоинт не дает спать по ночам, когда алерты приходят =))
А в остальном, сколько не пытаются преподнести фп как спасение от всех бед, на практике, как я вижу, используется в очень узких кругах… и в очень специфических задачах.
Я лично использую только для простенькой фильтрации или трансформации небольших объектов когда знаю что их количество ограничено числом N, и это число меня устраивает.
Когда был баг, они открывали процедуру, и начинали шаманить. Делалось это так:
Это был ад в плане мейнтененса и разработки фичеров.
А вы знаете толк в извращениях. Разработчиков не жалко? Всегда покрывался холодным потом когда смотрел как MS SQL DBA ищут и фиксят баги в процедурах… копипастят и комментят код (ручной гит лол).
Больше чем уверен что сейчас там все красиво. Можно статейку через годик-два о том как вы это все дебажите, ревертите и т.д?
Черные и серые зарплаты? В хайтеке? Не это ли первый звоночек что там работать не надо?
з.ы.
Чему вы научитесь создав клон google?
— делать поиск
ну пипец…
medium.com/@alexanderravikovich/scan-10m-websites-for-x-recruiting-header-in-go-fa85816da994
Сравнение сокета с ее же оберткой? :/
О боже как трудно написать проход по массиву клиентов =))
Автор вроде синьер… статья для начинающих в вебе?
Это не про монорепо?
Да и знаю я про гугл и про фейсбук. Но увы, на практике у нас где то 40 девелоперов и ci реально стал проблемой. Поэтому было принято решение сверху о разделении на собственные репозитории. Конечно разрабатывать так сложнее, но должно ускорить деливери.
1. Service discovery
2. Graceful shutdown
3. Logging
4. Metrics
В нашей компании мы пишем на ноде. Но есть вещи которые работали бы намного эффективнее на GO. Но сейчас внедрить GO это проблема, потому сервисы на ноде основываются на обертке, которая и занимается теми вещами которые я перечислил. И что бы втиснуть в экосистему бинарник на GO, мне нужно будет обеспечить работу с консулом и т.д. А это уже выходит за рамки того что я как разработчик сервиса хочу делать. Обидно. А хочется просто кинуть бинарник, и что б работало =)
Выпиливаем сейчас в repository per domain. Пишем на ноде, но тут это не важно.
Мое мнение такое, что жест и други кастыли в виде rewire или proxyquire появились именно потому что код писали криво, а тестировать то хоть как-то хотелось. Мы в большом проекте говна нахавались, когда тесты падали тупо после изменений имени файла, порядка выполнения или количества кейсов. Потому что люди волшебными тулзами то мокали, то где то забывали, а память то общая… потом сиди 2 дня дебаж что бы понять где забыли вернуть состояние.
Нет, ну можно конечно запускать по процессу на файл, но тогда тесты у нас вместо 10 минут будут час бежать.
А также это помогает избежать очень неприятных багов в виде cycle dependency. Да и с синглтонами тоже жизнь та еще…
Да, согласен, DI без статики то еще удовольствие. Зато в тестах никакой магии. Часто даже к sinon обращаться не надо. Дактайпинг во всей красе.
Опять же, без фанатизма. Инжектить не значит что щас мы lodash будем пробрасывать. Но вот DAO, Repository, http, queue, db и т.д. инжектим.
Ну еще из плюсов, легче собирать из этих кубиков нужный функционал. А когда все друг другу require делают, система превращается в Big ball of mud.
Так же легче перетаскивать отдельный компоненты например в отдельный сервис.
У вас может быть другой опыт и мнение. Не претендую на истину, но вот вот как-то так…
З.Ы.
Хочу заметить речь не идет о DI фреймворках… их я тоже не очень люблю. Не люблю магию и implicitly. Но на вкус и цвет…
Вот переедем на десятую ноду, сколько новых способов будет выстрелить себе в ногу… ну или голову =)
Просмотрел бегло лекцию. В принципе, проблема в том что люди думают что промисы волшебным образом делают код асинхронным. А то что это итератор или любой другой сахар или фича — не важно. Под капотом тот же промис. И тут я думаю было бы очень полезно показать как работает современная версия евент лупа. Когда понимаешь на каком этапе работает тот или иной код, все встает на свои места.
Не хочу обидеть, но лекция больше похожа на объяснение методом научного тыка. Что не есть плохо, я тоже люблю как говорится «почувствовать». Но мне кажется что лекция не доносит почему так происходит. Мне вот этот чувак очень помог — blog.insiderattack.net/event-loop-and-the-big-picture-nodejs-event-loop-part-1-1cb67a182810
И тогда все очень логично получается, и понятно почему промисы а блокируют. Потому что так libuv написан. Никакой магии.
З.Ы.
По моему то что вы там реализовали можно сделать при помощи setImmediate
Многие пишут не понимая даже что такое процесс, треды и общая память, и чем это светит например в тестах. Ну да ладно… Но у меня есть одна маленькая победа — все таки я смог донести до большинства в компании зачем нужен Dependency Injection =))
И хоть сам копаюсь в ноде довольно глубоко, даже с libuv играюсь в XCode, можно подробнее о «await блокирует event-loop»? Это же вроде просто сахар к промисам. И если операция асинхронная, то await отработает так же как и промис. Или вы о том когда разработчик делает async/await на синхронную функцию и ожидает что функция волшебным образом станет асинхронной?
Не очень понимаю… Как мне в дампе отличить объекты которые не будут удалены никогда от объектов «которые могут быть удалены сборщиком мусора в будущем»? Ведь если я запустил дамп когда у меня сотни или тысячи реквестов которые еще не закончили свою работу, в дампе будет много данных. Как понять где утечка среди всего этого?
Вот у нас бежит сервис в проде. Сервис писался лет 5. Там все: экспресс, раббит, любимый ивент емиттер. На нью-релике видим память бежит. Но бежит ооооочень медленно. Обычно до out of memory не доходит потому что деплоим часто.
Так вот когда открываешь дамп этого чуда, там столько всего… Сервис живой получает огромное количество запросов, отправляет месседжы и т.д. Пока что вот так в лоб скачиванием дампа найти утечку не удалось :/
Вообще в голове крутится сделать вот так:
1. Запустить сервак
2. Сделать дамп
3. Поставить сервак под лоад-балансер и дать недельку поработать
4. Вывести сервак из-под лоад-балансера. Удостовериться все реквесты и отложенные функции закончили работать.
5. Сделать дамп
6. Сравнить и надеяться на удачу
Может еще какие техники посоветуете? Ну или если я ошибаюсь, ткните носом :)