Pull to refresh
19
0
Anton Bykov @TigraSan

Пользователь

Send message
Например short read/short write, которые часть POSIX-a

Было записано/считано N bytes, дальше ошибка. Приложение должно уметь это обрабатывать, но в этом месте очень часто баги. Не берусь судить, из-за того что разработчики такого не знали, или изначально работали с языком который завернул им все в «либо ошибка либо результат»

И в этом месте очень часто баги
Я так понимаю имелось в виду на D
Кому надо — делают… как мы.

Есть достаточно большая наша библиотека(в основном реактор и все вокруг), которую мы недавно передали в dlang-community
Нам для файловой системы GC ну никак не нужен. И с кернел-ом разговаривать нужно только ну в крайнем случае.
github.com/dlang-community/mecca

Но я никак не рекомендую использовать D, если только не очень серьезный системный проект, с очень серьезной командой, на много лет. Для всех остальных задач есть языки с экосистемой куда получше, а это важно

Мы правда не все туда перенесли, большАя часть того что могло быть вынесено не вынесли, но решили отдать как есть. Еще месяц назад она сидела на нашем github аккаунте, сейчас перенесли в dlang-community, так как появились желающие подхватить.
Какой-нибудь Rust с GC (абсурдно, да) был бы очень крутым языком для этих целей.

D (Dlang)

Но сравнивая с go, GC там будет блокировать на порядки дольше. И серьезные вещи на D пишутся переписывая стандартные библиотеки, что бы не использовать GC
Го действительно прост.
Просто тем что накладывает ограничения, прост как раз тем, что нет миллиона способов сделать одни и те же вещи, тем, что как правило очень мало магии. Магию делать сложно.

Сравнивая с python(откуда девопс в основном и бегут), по опыту места работу выходит так —
Ищу девопсов с python — и нет выбора, кроме как искать людей действительно с богатым опытом, ибо магии у нас вышло много, python активно к этому подталкивает. Новому человеку сложно войти, далеко не все можно отследить по использованию, далеко не всюду вообще понятно что функция получит, часто это какие то аналоги dict-ов. Конечно же это плохо, конечно хочется все переделать. Но это время, и накладывает дополнительные требования к новым работником

С другой стороны — все новые проекты на go. И когда ищу людей — меня совершенно не интересует есть ли у них опыт на го, а только более фундаментальные вещи и реальный опыт с чем нибудь. Ибо никаких сомнений нет — что с любой задачей, по коду(даже когда он не идеален) легко ориентироваться, и новый человек используя нормальный IDE ничего нигде не упустит. Так как все на ладони.

Тут конечно же можно возразить — это преимущество сильно типизированого языка.
Контраргумент тут это вся суть — после безуспешного поиска в течении долгих месяцев человека, который достаточно силен чтоб взять проект на rust-е, при этом имеющие фундаментальные знания(например, банально, понимающий что http request это не только json получаемый через request.body) я решил просто отказаться от rust-а(который достался в наследство), все за несколько месяцев переписалось на go и людей искать стало проще. Притом новый человек помогающий переписывать просто проклинал каждый день, когда ему приходилось в имплементации на rust-е пытаться понять что же оно делает.

То что на go будет написано 15 императивными строчками и понятно за 15 секунд, на rust ради красоты мира завернуто в 7 генериков, пару строчек и тройку map-ов и час для понимания, которое включает в себя чтение документации для разных библиотек. Порог вхождения растет в разы, сложность поддержки растет в разы.

В результате, и weakly typed python и strongly typed, generic, functional rust имеют один и тот же ряд недостатков в сравнении с го, по одинаковым причинам

— Отсутствие 100-процентно рабочих IDE (100% рабочее = всегда, в любой ситуации IDE покажет ошибку если используется неправильный тип и можно отследить использование любого символа, позволяя безопасный рефактор), т.е сложный вход, поддержка
— Как следствие предыдущего — любая магия(коднейм для meta programming), а она будет, обязательно становится сложной для понимания при необходимости ее трогать.
— А так как магия, это обычно связующие звенья бизнес-логики — она тоже становится сложной для поддержки
— Более высокие требования для новых работников == сложный рекрутинг
— Высокая когнитивная нагрузка, думаешь не о том
— Сложность экосистемы, deploy, crossplatform
— В процессе разработки думать приходится о том, откуда взялся NoneType, либо почему тип не подходит в длинной связке генериков, вместо того что код должен делать. И воспринимается это сложней

В общем простота и красота языка в целом, в том какого типа задачи приходится решать ежедневно, а не в том, обрабатывается ошибка одной строчкой или 4мя
Пару вопросов из списка, в паре с реальными короткими задачками — имхо намного более эффективно, чем просто пройтись по зачастую ненужной теории (хеш-меп как уже было сказано) и edge-caseам структур. Которые опять таки, зачастую можешь из-за дня в день делать правильно, при этом уже и позабыва поведение при «неправильно»
Ну как в примере с чтением из закрытого канала
Оно вроде бы как и важно, но по сути столкнувшись с этим первый раз — второй уже будешь работать через v, ok на автомате, если вообще стоит вопрос о закрытых каналах, либо что еще более вероятно — range. А что именно там происходит в v < — closed из памяти вполне и выпасть может…

Если речь обо всех из них — ну вполне может попасться «академик», теорию знает очень хорошо, на практике не может связать три строчки между собой. К слову я не считаю их бесполезными, несколько спросить стоит. Но походу дела

Что такое реальные задачки? Я себя взял за правило, если что-то пишу и вдруг обращаю внимание на то «этож классика, но 15 лет назад я бы задумался» — там кроется хороший вопрос, который никак не связан с конкретным языком.

Конкретно про go, из простых, полезных вопросов что задаю — напишите прорамку, которая принимает из stdin int, по одному на строчку, запускает некую обработку, для примера — рандомальный sleep, не больше 128 паралельных исполнений.
Чаще всего очень быстро приходится дополнить — без дополнительных библиотек, только stdlib, без гугла, без документации.

Бонус — по ctrl-c дождаться завершения бегущей обработки, не запускать новые. В целом от хорошего кандидата ожидаю и этого, грузить сразу не хочу дополнительными подробностями. Если скажет что не помнит сигналы и где они находится, но знает что они ему нужны — ок, гугли.

Тому кто могёт — дел на 5 минут, тому кто нет — все сразу ясно. В результате покрывается достаточно большое кол-во тем, включая контекст(которого к слову в вашем списке нет, а стоило бы)

ЗЫ, к слову о rust vs go
Есть проект, который мне достался в наследство, на который тоже ищу кандидатов, он написан на rust. Я его называю SSAS, Stupid simple api service. Утрирую, но ничего заоблоачного там нет и на мой взгляд rust не оправдан.
Искал месяца 2 на позицую на rust. С кандидами в целом было плохо, тех кто утверждали что знают раст вообще единицы. Задачку выше на расте никто не решил.
А даже те кто вообщем то действительно как-то раст знали, запутались в трейтах, что можно, что нельзя, почему некая стороняя библиотека(на раст разрешал делать что угодно, хоть с stackoveflow скопипастить) не работает с аргументами комманды(там я просил аргументы, а не stdin) и много чего еще. В общем это была боль.

В конечном счете я решил просто переписать на go и искать соответствующе. Стало проще. Ибо не готов я повторять эти поиски кандидатов на rust, в отличии от go, такой ряд теоретических вопросов становится намного важней, а найти и так сложно.

А разница между уровнями кандидитов я для себя определил не самой возможностью решать задачки, решить должны все. А тем как быстро и качественно, и кол-во задачек которые успел задать на интервью
Пару вопросов из списка, в паре с реальными короткими задачкой — имхо намного более эффективно, чем просто пройтись по зачастую ненужной теории (хеш-меп как уже было сказано) и edge-caseам структур. Которые опять таки, зачастую можешь из-за дня в день делать правильно, при этом уже и позабыва поведение при «неправильно»
Ну как в примере с чтением из закрытого канала
Оно вроде бы как и важно, но по сути столкнувшись с этим первый раз — второй уже будешь работать через v, ok на автомате, если вообще стоит вопрос о закрытых каналах. А что именно там происходит в v < — closed из памяти вполне и выпасть может…

Если речь обо всех из них — ну вполне может попасться «академик», теорию знает очень хорошо, на практике не может связать три строчки между собой. К слову я не считаю их бесполезными, несколько спросить стоит. Но походу дела

Что такое реальные задачки? Я себя взял за правило, если что-то пишу и вдруг обращаю внимание на то «этож классика, но 15 лет назад я бы задумался» — там кроется хороший вопрос, который никак не связан с конкретным языком.

Конкретно про go, из простых, полезных вопросов что задаю — напишите прорамку, которая принимает из stdin int, по одному на строчку, запускает некую обработку, для примера — рандомальный sleep, не больше 128 паралельных исполнений.
Чаще всего очень быстро приходится дополнить — без дополнительных библиотек, только stdlib, без гугла, без документации.

Бонус — по ctrl-c дождаться завершения бегущей обработки, не запускать новые. В целом от хорошего кандидата ожидаю и этого, грузить сразу не хочу дополнительными подробностями. Если скажет что не помнит сигналы и где они находится, но знает что они ему нужны — ок, гугли.

Тому кто могёт — дел на 5 минут, тому кто нет — все сразу ясно. В результате покрывается достаточно большое кол-во тем, включая контекст(которого к слову в вашем списке нет, а стоило бы)

ЗЫ, к слову о rust vs go
Есть проект, который мне достался в наследство, на который тоже ищу кандидатов, он написан на rust. Я его называю SSAS, Stupid simple api service. Утрирую, но ничего заоблоачного там нет и на мой взгляд rust не оправдан.
Искал месяца 2 на позицую на rust. С кандидами в целом было плохо, тех кто утверждали что знают раст вообще единицы. Задачку выше на расте никто не решил и за половину времени.
А даже те кто вообщем то действительно как-то раст знали, запутались в трейтах, что можно, что нельзя, почему некая стороняя библиотека(на раст разрешал делать что угодно, хоть с stackoveflow скопипастить) не работает с аргументами комманды(там я просил аргументы, а не stdin) и много чего еще. В общем это была боль.

В конечном счете я решил просто переписать на go и искать соответствующе. Стало проще. Ибо не готов я повторять эти поиски кандидатов на rust, в отличии от go, такой ряд теоретических вопросов становится намного важней, а найти и так сложно.
На самом деле никакой проблемы нет…
Еще лет этак 15 назад, играя в mmorpg и пользуясь каким то простым голосовым сервером(не помню уже название) именно так и было
И звучало это в разы лучше чем в зуме
Потому что:
— никаких фильтров
— все игроки с гарнитурой и никаких шумов

А с зумом большинство через динамики лэптопа, либо конференс-рум, единицы с наушниками. Приходиться обрабатывать

Обьемный звук конечно тоже имеет значение… узнал это с неожиданной стороны, когда одним ухом почти перестал слышать. В живую когда несколько человек говорят — порой сложно разделять. В зуме все получают тот же эффект

Но эта проблема, в той самой древней програмке решалась очень просто — каждого в комнате(лично для себя) можно было немного сдвинуть влево-вправо в балансе звука и это давало отличный эффект.

А шум в зуме вообще убирается локально а не удаленно, т.е убрать локально, спозиционировать каждый потом обьемно, опять таки — локально, (в пределах 25 процентов в каждую сторону), и вполне возможно что все было бы отлично, просто убрав принудительное глушение и добавив сдвиг влево-вправо…

Меня все чаще смущает поголовный отказ от


public function processSomeDto(SomeDtoClass dto)
{
     if (predicat) {
          throw new Exception(‘predicat is failed’);
     } else {
          return this.dtoProcessor.process(dto);
     }
}

И если этот пример я еще могу понять, так как в реальности это скорее всего было бы так:


public function processSomeDto(SomeDtoClass dto)
{
     if (predicat) {
          throw new Exception(‘predicat is failed’);
     } 
     if (anotherPredicat) {
          throw new Exception(‘another predicat is failed’);
     } 
     return this.dtoProcessor.process(dto);
}

И это хорошо, это точки выхода, которые легко вынести в что-либо вроде


public function processSomeDto(SomeDtoClass dto)
{
     this.validateParams()
     return this.dtoProcessor.process(dto);
}

Но основной посыл всегда — отказаться от else, если работать будет так же без него. А это имхо, зло.


Ибо следующие два варианта работают одинаково, но читаются абсолютно по разному. И активно продвигается первый вариант, с чем в корне не согласен


function abs(int num){
     if(num < 0){
          return -num
     }
     return num
}

function abs(int num){
     if(num < 0){
          return -num
     } else {
          return num
     }
}

Одно дело точки выхода, другое дело акцент на разных поведениях и при рефакторинге, когда нет этого самого else — намного проще допустить ошибку

Мне вот на самом деле интересен такой вопрос (частично высказан выше в отсылке к «Теория Темного Леса»). А может и полностью, так как книгу не читал…

Предположим, что «рядом» ничего нет, так как современные технологии позволяют обнаружить наличие цивилизации «рядом» (десяток световых лет?)

Что-либо значительно дальше предполагает возможность путешествия и коммуникации на сверхсветовой скорости. Поставим тут галочку, это доступно.
Ибо если этой галочки нет — эти цивилизации зарождаются и умирают, и вселенная о них даже не узнает.

Теперь представим, что встретились две такие цивилизации, с галочками.
В чем смысл их мирного существования? Что они могут дать друг другу? Зачем делить ресурсы, пусть даже чуть ли не неограниченные?
Очевидно, что с обоих сторон был естественный отбор. Война в «крови», или что у них там

В вопросе «что могут дать друг другу» нужно учитывать, что обе цивилизации дошли до возможности сверх светового перемещения, то есть они уже де-факто очень развиты и главное, способны развиваться дальше. Аргументы вроде «а вот та цивилизация умеет в текущую магму нырять и камни грызть» крайне нелепы (отсылка к играм)

Возможно, как часто это бывает в фантастике, люди необычайно умны и постигают за несколько тысяч лет, то что другим заняло миллионы.
Так и в таком случае — людям не нужны эти жалкие, медленные букашки, которые через сотню лет будут пещерными троллями. А этим букашкам единственное, что имеет смысл — уничтожить человечество, ибо либо так — либо стать букашками через 100 лет.

Во мне, как наверно и во многих играет любопытство, мол, а какие они, интересно же…
А так ставя вопрос, мне сложно увидеть мирное сосуществование. И тогда — нафиг нафиг…

Ну, разве что странный вариант, как в фильме «Прибытие»

Да, ошибся. Я исходил из того, что 500h/s дает порядка полутора долларов в день
Но это сильно устарело…

То есть, если предположить что на piratebay заходяд одни геймеры и процессоры способны выдать 500h/s — по сегодняшним ценам это уже всего лишь 0.38$ в день, плюс порезать на то, что web assembly все же менее эффективен да плюс не на максимум грузить — и выйдет 0.2$ * 100 = 20 долларов в день на постоянный онлайн в 100 юзеров с приличными CPU
А сколько уж их там у них на самом деле — не знаю.

Но для поддержания 100 юзеров онлайн инфраструктуры за 2000 долларов в месяц достаточно с головой и подозреваю что у них таки поболее… Имхо все равно имеет смысл на жизнь, главное подать правильно
На самом деле если грамотно использовать все ядра(web workers?), при этом ни одно из них не нагружать на сто процентов — пользователь даже не заметит. При этом, мало у кого сегодня одно ядро. Доход будет вполне приличный. Сайт с постоянным колвом около 100 пользователей онлайн(не так уж и много, особенно с учетом что многие вкладки оставляют открытыми) вполне способен приносить баксов 150 в день а то и больше.

Грамотным подходом было бы при первом заходе показать поп-ап, майнить али рекламу смотреть. Плюс оставить снизу/сбоку тумблер для переключения режима.

Беда только когда вкладок много от разных сайтов и все хотят майнить… Тут уже нужна поддержка браузеров, запрещающая браузеру выжирать больше указанного пользователем %CPU. С разумным дефолтом(80%?)
Тут конечно следует определить что такое побочные эффекты.

Построение различных объектов для быстрого доступа в работе — как по мне ничем не отличается от определения классов и функций. И там и там при импорте уже бежит много чего. И это неизбежное зло, как следствие хороших сторон языка… В том числе и monkey_patching при импорте. Абсолютно все сделать lazy нельзя… либо ценой неудобного кода

В этом контексте под побочными эффектами подразумеваю I/O, то есть — сеть и ненужные обращения к диску

В таком понимании — все чисто, импорты ~200ms на большом проекте. Но это только импорт
Запуск приложения уже подразумевает намного больше, а там уже вполне допустимо несколько уровней кеша(память-диск) с оригинальными данными из сети, различные библиотеки подгрузят свои конфигурационные файлы для автогенирации API…
И тут секунды для запуска уже реальны. Что явно расточительно, для обработки одиночного запроса :)

Более того, ему(python-у) бедному и так сложно. Импорты на большом проекте могут с легкостью занять более секунды. Импорты без побочных эффектов, просто импорты…

Я уже не говорю про инициализацию подключений и другие netI/O задержки, которые вполне могут быть при старте.

И если бы каждый запрос делал все это — лежали бы сервера со 100% оверхедом по cpu, очень тщательно занимаясь построением тяжеловесных объектов(о чем кстати эта статья), вместо того, чтоб обрабатывать предельно простые запросы юзверей, о том по какому же url-у котики лежат, занимая при этом фиксированное значение в легкодоступной памяти, без каких либо значимых овераллокаций.
Ничего не очищается.
wsgi(который, в частности реализует uwsgi, так же как и gunicorn и встроенный debug режим фласка например) просто передает построенный обьект запроса (Request) в хендлер приложения

Хендлер должен вернуть Response

Само приложение бежит, запущенное в процессе сервера реализующего wsgi

Сервер может запустить n-ое колва приложений, убивать каждое после n-ого кол-ва запросов (как костыль против утечек памяти)

Для того чтоб лично убедиться — достаточно выставить 1 процесс в uwsgi/gunicorn, убедиться что нет перезапуска после одного запроса(это никогда не дефолт) и записать какие либо данные в какой либо глобальный объект

При другом запросе — считать.
Данные будут там

Более того, подсказка, именно так держатся подключения к БД и именно так в принципе могут работать всякие функции вроде memoized, исключительно в памяти, без редисов и прочего
Добавлена поддержка флага запуска -f, чуть позже добавлю и опцию включить после запуска
Обновил, 1.1.0 (не фанат версий начинающихся с 0.0000)

— Добавлена поддержка RegEx, переключение между режимами поиска по CTRL + /
— И добавлен флаг запуска --version, для грамотных багрепортов
К слову делает он это крайне неэффективно…

У меня вышло примерно 7 секунд на 1GB лог против ~20 с less-ом. И как уже писал выше — теперь это необязательно и не нужно нажимать отмену, считает себе и считает :)
Я это уже изменил в последнем релизе, переход мгновенный, строчки считаются независимо
Случайно залил с дебаг-пакетами, релиз убрал, через минуту обновлю.
Залил новый релиз
— улучшена работа с большими файлами
— Так же с большими файлами теперь нормально должна работать и x86 и amd64 версия
— Счетчик линий теперь не блокирует, переход в конец мгновенный
Карту оффсетов больше не храню, потребление памяти должно быть минимально

Но в любом случае, если фильтры должны найти 300 строчек из 7ГБ — это не будет быстро… Но в плане того, что поиск блокируем — планирую улучшить, чтоб хоть отменить неудачный фильтр можно было и не ждать

Information

Rating
Does not participate
Location
Тель-Авив, Тель-Авив, Израиль
Date of birth
Registered
Activity