stdray: (Default)
У нашей системы загрузки данных есть особенности: наличие жесткого дедлайна и единомоментное массовое появление данных на ключевых источниках. То есть в теории мы пытаемся получать информацию в реальном времени, а на практике выходит, что бОльшую часть суточного объема мы получаем в конкретные часы ночью и должны полностью отпроцессить к началу рабочего дня. Двигать делайн нельзя, потому что источники начинают выкладывать данные ночью по Москве, а во Владивостоке люди уже сидят и работают. Из-за чего можно видеть пики загрузки подсистем: сначала на получении первички, потом на трансформации, потом на раскладывании данных в детальный слой, на построении витрин и, наконец, индексации на полнотекстах.

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

По логам это выглядит так: интервал между двумя записями job'а, в который, грубо говоря, происходит лишь одна операция "создание из одного гигантского хэшсета другого с добавлением туда новых элементов", составлял чуть ли не 30 минут. Плюс в этот же период идут алерты, что на сервере кончилась память, потому что процесс всё пожрал. То есть, как я понимаю, процесс начал свопить и все замедлилось в зигалион раз.

Можно сходу набросать несколько вариантов, как эффективней работать:

  • не создавать новый хашсет, а мутировать старый

  • не работать с архивами в памяти, а распаковывать их в tmp

  • уменьшить фрагментацию памяти, используюя пул стримов

  • и так далее.



Другой вопрос, что перебирать варианты опасно и долго. И тут я понял, что плохо представляю себе как профилировать память приложения, которое жрет по 16+Гб на удаленном сервере. Варианты, которые я испробовал:

  1. JetBrains dotMemory через RemoteAgent. Не сработало, потому что долго конектится к процессу, долго делает дамп, НЕВЕРОЯТНО долго качает этот дамп, еще дольше его процессит. В итоге ни один дамп таким образом у меня открыт не был.

  2. Делаешь дамп штатными средствами ОС, качаешь Far'ом, открываешь в WinDbg и через sos смотришь !dumpheap -stat. Работает, но опять же долго делать дамп и очень долго качать.

  3. Открываешь дамп в dotMemory. Эта возможность помечена как "beta", работает 100500 лет, плюс у меня дважды упала ОС из-за ентова. На третий раз всё открылось быстро, но информация была крайне странная. профайлинг ёба
    (В ЖЖ почему-то не отображается картинка, если что она есть)
    Первая попытка профилирования, когда у меня помер пека, остановила процесс, потому что с того момента он больше не делал ничего. А что за дамп загрузился после второго падения, я хз. Хотя фантазия успела разыграться, несмотря на полное несоотвествие даже абсолютных значений реальной картине.

  4. Вспомнил, что видел у Саши Голдштейна какую-то утилиту на этот счет. Она не работает. Совсем. По крайней мере, у меня.

  5. Вспомнил, что есть clrmd и написал маленькую тулу вот такого вида. Она работает около минуты, дает более-менее похожие на правду значения. Вот ей пока и пользуюсь, только модифицировал, чтобы можно еще режим задавать (не только NonInvasive, но и Passive выбрать) и поставил в планировщик писать енти "логи" каждые 15 минут. Завтра буду разбирать.



Как вообще нормально профилировать память в серверных .Net приложениях? Поделитесь опытом. А то вот это всё дикое время на создение дампа, на перекатывание его туда-сюда просто убивает. Это как смотреть на растущее дерево. Должны же быть какие-то нормальные способы.
stdray: (Default)
Хотел в заголовок поставить слово "микросервисы", но все же не про них речь.

Дело такое. Есть у меня сервис, обеспечивающий первые 2 этапа ETL-процесса: загрузка сырых данных с источников и трансформаця их в каноничный внутренний формат. Этот формат потом жрет платная сложная тула, которая раскидывает из него данные по табличкам детального слоя, data vault и всё такое.

Сервис представляет из себя планировщик quartz, в который пихаются задачи на загрузку и трансформацию. При этом с одного источникам мы можем загружать разные документы, и, скорей всего, это будут разные процессы. В простейшем случае (всего один тип документа и один "реестр") имеем 2 джоба (загрузка и трансформация), в сложном - 2-3 десятка. Есть еще такой момент, что может существовать одна реализация YobaLoaderJob, которая в конфигах тиражируется на 12 задач с разными параметрами.

С точки зрения кода, если отбросить весь common и utility код, имеем ОДНУ библиотеку, где по папочкам разложены реализации всего этого зверинца. В целом, это было достаточно удобно:
- простая и понятная структура проектов (хост, реализация, тесты)
- элементарное добавление нового источника (запилил реализацию, накалякал тестов, занес задачи в конфиг планировщика нужного контура и погнали)
- удобный рефакторинг (с точки зрения унификации - все рядышком, посмотрел, подумал, обобщил; с точки зрения правок базовых классов - всё, что можно сломать, лежит в этом же проекте)
- легкий деплой (один раз настроил сценарий разворачивания хоста и всё)

К сожалению, минусы стали такими жирными, что теперь каждый новый источник делает меня грустить. А именно:
1. правка одного источника приводит к необходимости рестартовать все (аналогично, если надо отключить один конкретный процесс)
2. библиотека с реализациями обросла диким количеством зависимостей, а ее выхлоп весит много мегабайтов
3. когда хост запущен, он штатно жрет память в пределах 8-14 Гб, что сильно осложняет снятие и исследование дампов
4. когда какие-то процессы штатно не реагируют на сигнал завершения работы (сервис не тормозит ни за 2, ни за 5, ни за 15 минут) очень трудной найти причину (см. п3)
5. примитивные мониторинги (состояние сервиса, его потребление ресурсов) становятся абсолютно бесполезны, поскольку на фоне больших и ресурсоемких источников мелкие не видны
6. все задачи кроме своего штатного расписания имеют триггер "выполниться при запуске", что реально нагибает базу, из-за чего треть процессов получает отлуп и логи краснеют
7. долгий цикл CI/CD (для одного контура оно строится 3-4 минуты, примерно столько же идут тесты, еще 3-10 минут уходит на деплой). Итого, между запуском билда и наблюдаемой активностью проходит минут 10 минимум.

Логично, что всё это дело надо распилить, но у меня нет четкого понимания, как это сделать, чтобы не усложнять разработку. Как организовать структуру проектов и как правильно выбрать гранулярность. То есть, можно представить вот такую шкалу, на какое количество логики надо создавать отдельный сервис:
1. один для всех (текущий вариант)
2. один на источник
3. один на группу зависимостей (идея примерно такая: все джобы которые, к примеру, ходят на ftp, наследуют один класс ведут себя одинаково и им не нужен остальной хлам)
4. один на каждый джоб (другая крайность)
* п2 и п3 могут только чуть облегчить боль, но проблему они не решают


Понятно, что хотелось бы иметь п4 ОДИН ХОСТ НА КАЖДЫЙ ДЖОБ. Но как этого добиться?

По поводу сценариев сборки и развертывания я беспокоюсь мало, в худшем случае всегда можно на коленке собрать "сервер приложений", который будет мониторить папки, находить изменения, стопарить процесс и запускать с новыми сырцами. Это просто. Написать билд, который что-то соберет по определенным паттернам названий проектов еще проще.

Но я не понимаю, как это организовать в коде. Я уже выше писал, одна имплементация может иметь несколько инстансов в конфиге. И так выходит, что у меня 350+ джобов, и на каждый на выходе должен получиться типо отдельный запускаемый бинарник? Очень стремно. На каждую реализацию делать по одному проекту, прикладывать туда все необходимые конфиги, а сервер приложений из них запустит по отдельному хосту?


Я в растерянности. Не знаю, акторы-хуякторы и прочие трендовые микросервисы не помогают.
Может, у кого есть подобный опыт? Ну или соображения на этот счет?

Code review

Jun. 8th, 2017 04:27 am
stdray: (Default)
Регулярно читаю в твитттуре, что мол парни, чей код просматривают, неадекватно реагируют на критику. Ну или не только парни, может и девушки, но этот нюанс не раскрыт. И все эти росказни сводятся к тому, что люди типо реально начинают переживать. Дальше идет пояснение, что не надо воспринимать критику своего кода на свой счет. Дескать, ты не тупой мудак, просто код твой - говно. А затем разворачивается не сильно большая, не особо маленька, а такая, прямо в меру, дискуссия, как же правильно ревьюить чужой код. Набегают профессионалы самых разных высот квалификации, высказывают авторитетные мнения, которые начинают интерферировать. Ну это же понятно, что анскилед лелкам в твитторг путь заказан, потому там только ревьюверы сидят, а не ревьювируемые. И какбэ все хорошие ревьюверы хороши одинаково, а вот ревьювируемые мудаки - мудаки по своему.

ревью - это просто праздник какой-то )
stdray: (Default)
ну ты же робот ёбана

А кто-то пытался на основе лога обычного чата построить некое подобие древовидного форума?

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

Очевидные эвристики: обращения к конкретному нику, цитирования части сообщения, использования редко встречающихся слов (с точностью до N-го расстояния Левенштейна), скоростной постинг одним юзером нескольких сообщений подряд (скорей всего они должны составлять единое целое), разбивки по приветствиям, разбору содержимого линков (опять же в поиск редких слов) и тд и тп.

Понятно, что в первом приближении это не очень полезно и удобно, но должны же быть какие-то наработки. Ведь никто не вычитывает чаты дальше N-го сообщения с конца, НО увиденные обрывки обсуждений могут быть интригующими.

Интересен еще такой момент. Предположим, у нас есть такая система. А мы ее натравливаем на обычный пост в ЖЖ, где каждое предложение ОПа трактуем, как отдельно сообщение в чате. И тогда для нытико-технического поста вида "Вот мой опыт, что дураки-идиоты, так сяк робят плохо. А я туда-сюда с {technology_name} стою в белом пальто" чудо-технология сможет побить дискуссию на {technology_name} и сочувствующих "а у меня инитакоебыла" с прочими технофелософами.

Так где?
stdray: (Default)
Как писали в твитторе, в интересные времена живем:
- Microsoft без лишней скромности вкатился в Linux Foundation
- Заманил Google в .NET Foundation, который запиливает подержку дотнета для своего облака
- Показал Visual Studio для маководов. Студия уже приветствует неофитов
- Выложил для проб SQL Server, который v.Next, который можно пускать на линунксах
- Бомпанул Слек
- Сообщил, что Samsung отвлекся от производства взрывчатки, и опубликовал .NET SDK для Tizen
- Обратил внимание на проекты сообщества, такие как BenchmarkDotNet и NancyFX, приняв их в .NET Foundation
- Довел ASP.NET Core до такого состояния, что мы можем увидеть дотнет во всем известном некорректном бенчмарке


MS, правда, как я понял, прикончил WinPhone. Зато запустил совершенно непонятную мне ёбу. С другой стороны, пишут, что всё правильно MS делает




Сможешь ли ты совладать с ним?
stdray: (Default)


Хочу написать парсер поисковых запросов. Набор возможных операций мал: "и", "или", "не", группировка скобками (изменение приоритета), группировка кавычками1 (фразовый поиск), группировка кавычками2 (точное совпадение), пробел/табуляция/что-то еще - разделитель (он же implicit "и"), перевод строки - разделитель (он же implicit "или"), escape-символ (возможно, это будет '\').

Сложным мне представляется обработка ошибок. Пользователи будут вводить любую ерунду и удивляться любому поведению. Тут политика партии ещё не ясна: либо будем сыпать ошибки, либо достраивать до корректного запроса, либо и то и другое. Сыпать ошибки придётся, инфа под сотню, а значит они должны быть разумными и понятными. Это, как я понимаю, отсекает возможность применения парсер-комбинаторов и генераторов (TDOP, PEG, EBNF и прочих).

Выходит, что мне нужно ручками, кровью и потом писать лексер, выписывая автомат (регулярки не помогут) и все его состояния. Потом руками ходить по порожденной лексером коллекции токенов, с целью починить или внятно поругаться. И, наконец, руками же написать автомат парсера.

Что-то выглядит очень громоздко и скучно. Может, чего не знаю и есть короткий путь? Или, может, кто из вас видел красивые и компактные реализации чего-то подобного? В общем, я достаточно далек от разбора текста и надеюсь на любую помощь.


ЗЫ: зря я не читал дракона, да?

REPL LEL

Mar. 15th, 2016 06:04 am
stdray: (Default)



Достаточно занятная тема, которую я обычно избегаю, ибо синдром утёнка, начинал сразу с C в IDE (тогда в borland c++ 3.1). Но вот вчера внезапно выслушал монолог о том, как REPL ускоряет разработку. Знакомо, ведь я тоже радовался так когда-то. А потом всё встает на свои места.

Похоже, что радоваться REPL'у могут либо измученные тяжелой инфраструктурой программисты, которые устали создавать ConsoleApplication1488, чтобы проверить какую-нибудь ерунду, либо ребята, у которых вообще ничего нет.

Read more... )

Про api

Mar. 10th, 2016 01:17 am
stdray: (Default)



Регулярно всплывает тема запиливания хорошего годного интерфейса к ентим нашим оперденям. И все глубокомысленно отвечают, что вопрос давно решен, и REST API - наше все. А потом все столь же глубокомысленно кивают, мол всё так, всё так. Хотя по факту имеем набор нечетких рекомендаций вида:
- http в качестве транспорта
- json в качестве данных
- url в качестве идентификаторов сущностей
- http verbs в качестве действий.

Это ответ на вопрос? Я считаю, что это лел. Это как в известной песне: "Думайте сами, решайте сами". Если у вас нет обещаний, то и некому их нарушать.

Read more... )
stdray: (pic#896193)
Написал, точнее переписал (процесс продолжается) весь слой загрузки данных из внешних стрёмных источников. Переписал не из чувства прекрасного, а по следующим причинам:
1. целиком и полностью изменилось внутренне представление данных
2. невозможно поддерживать существующий код
3. невозможно анализировать работу существующих процессов загрузки

Я с некоторых пор не любитель писать с нуля, но здесь вынужденно во все тяжкие. И если с первым пунктом все понятно, то про два других подробней. Это про то, почему «написал», а не «переписал». )
stdray: (Default)
Уже сбился со счета, какой раз мне прилетает в твитторе данное видео

про макроэкономику без учета возможностей РБ )

и каждый раз смеюсь.
Вот решил схоронить в публично-личном журнале.
Хочу отметить, что данный персонаж приплывает с комментариями, аки терминальный ватник (и словца пожощще и по, хмм, выразительней), хотя, как по мне, "Джастас Уолкер" не очень "ватное" ФИО.
stdray: (Default)
ничего интересного, тип услышал на европа+ или вроде того, но она крутая
stdray: (Default)
Читал пост про книги по дизайну ООП приложений, и внезапно осознал, что прочитал большую часть приведенных книг.

И не могу сказать, что мне как-то это помогло. Скорее наоборот, после прочтения количество полезного кода резко сокращалось, а популяция пауков-розеточников росла. Ведь рефакторинги, иерархии интерфейсов, попытки работать с rich domain model, - все было контрпродуктивно. Поскольку задачи константой (известной) сложности внезапно приобретали новый порядок пиздеца человекочасов, где количество рефакторинга и доступных для задачи паттернов существенно превышало непосредственно бизнес-логику.

Конечно, это вопрос вопрос личного опыта и критического (его отсутствия) отношения, так как в определенный момент начитавшись ПФП, изучив какую-то литературу про F#, я решил, что можно невозбранно применять этот подход в повседневной работе. Как следствие - безумный, бездумный, ад пиздеца "фп стиль", который я потом рефакторил в куда более простые и идиоматичные конструкции, когда понял, что я таки буду менять работу. К сожалению, недорефакторил, и там _сложно_.

Я полагаю, что моя главная ошибка была в том, что всё это происходило хаотично, что вместо продумывания высокоуровнего дизайна приложения, я занимался дизайном уровня функции/модуля/компонента/библиотеки, при этом "слои" либо разово определялись на начальном этапе проектирования, либо формировались ( или не формировались) походу дела. Занятно, что "слои" в любой литературе носят уморительный характер, формализуемый, допустим, у Фаулера, мол уровень (level) - чисто интуитивная хуита, а вот слой (layer) - это можно разнести по разным машинам. Ну понятно, что первое и второе (до разноса) являются квазисущностями, которые держит в голове только породивший их на свет.

С этим бекграундом я с интересом прочитал статью, которая навязывает некоторый высокоуровневый дизайн в условиях убогого однопроходного компилятора F#. Занятно, что ограничения компилятора ведут к совершенно конкретному дизайну, к которому я приходил, занимаясь разработкой на эфсярпе. Но я никогда не смотрел на это в таком ключе, мол у вас просто и выбора нет. У вас есть единственно верный anemic подход, конпелятор, который иное не переварит и профит.

Понятно, что любому ограничению можно найти оправдвание (например системам типов), как можно и не делить приложение на слои. Мне просто понравилась трактовка убогости конпелятора, как некоторой статической валидации дизайна на высоком уровне.
stdray: (Default)
Вынесу из комментов, а то меня меня в противники ФП из-за отрицания киллер-фичности отступов записали недавно.


Субъективно, компактность достигается выбрасыванием лишних сущностей.

ООП - это про:
- делегирование ответственности и сертифицированные способы это сделать (патттерны)
- "безопастность уровня разработчка", ведь любой объект в терминах ООП - потенциальная точка расширения как добавлением узко-специфичной логики (костыль) и наследниками нарушающими инвариант, откуда идут закрытые классы (малая реиспользуемость) и избыточное количество деклараций (интерфейсы, полностью абстрактыне классы). Отсюда же пачка модификаторов и бойлерплейт.
- делегирование ответственности во вне: инъекция зависимостей через конфигурацию (xml spring ioc и ему подобные).
- сильную связанность (coupling), поскольку ООП-методы абстрагирования по спирали приводят к ней раз за разом, в виде того же жесткого каркаса на новом уровне абстракции. При этом растут затраты на отслеживаниее этих зависимостей.
- проблемы с тестированием (в силу предыдущего пункта), поскольку модульные тесты имитируют "архитектуру" системы. Формализм объектов - ДКА, и даже mock-объект должен имитировать его состояния.
- высокий порог вхождения. Несмотря на номинально низкий порог, разобраться в этом зверинце практически невозможно. Пока новички комплексуют от классов с пачкой статических методов, прошедшие этот этап налегают на тулинг и накапливают опыт.

ФП - это про:
- first class citizen функции
- безопастность для разработчика, через иммутабельность и чистоту функций
- решение конкретной задачи
- простое тестирование при отсутствие состояния
- высокий порог вхождения, несмотря на концептуальную простоту и доступность обучающих материалов, разбираться в этом зверинце никто не хочет. Пока неофиты пугаются ауры "научности", новички метаются между языками, книгами и прочим, прошедшие этот этап не имеют возможности применять знания технологии на практике.

ЗЫ: пишу про модульные тесты, потому что не понимаю, что такое юнит-тесты и не пишу их. А затраты на интеграционное тестировние (по моей практике) нивелируют разницу в подходах.

ЗЗЫ: ФП очень про анемичную модель (в терминах ООП). И, субъективно, такой подход проще (банально). Например, такая презентация.
stdray: (Default)
Вот мы с бро шли со стройки/бани в квартиру спать, а тут черный кот дорогу пересек. Вот сволочь. А он еще раз пересек. И еще, и еще... и так 12 раз перебежал. Братюня грит, про невезение и неудачи, но у мня опять какое-то ретро звучит в голове.

няш-мяш танцпол )

Мало ли кому не повезет, но одной политотой ни сыт, ни рад не будешь. Пляшем! пока есть такая возможность


ЗЫ: мне тут доказывают, что щаззз либо дианби, ну-метал и там прочий хип-хапп, - суть. Был бы признателен за всякие любимые ретротраки. Ведь внезапно можно выяснить, что русский рок - это Агутин, а не Макаревич.
stdray: (Default)
поскольку Высоцкий никому не по душе, а Одесса тем более, то, котаны, ловите

опять дают задержку рейса )
stdray: (pic#896193)
Внезапно, нашел видео, которое я снял, когда ходил побагетить на разгул православия в стране
Read more... )
stdray: (Default)
Вспомнил прошлое лето. Мы с отцом баню строили в деревне, я часто на даче появлялся. Потом подумал, ну что мне мешает местные убитые дороги перефоткать и на росяму выложить? Да ничего, взял и перефоткал те ямы, что мне мешали, выложил на сайте, а потом уже из Москвы заказным письмом отправил сгенерированную заяву ивановским ментам. А через 6 дней приехали работники и ямы заляпали. Хреново, конечно, абы как, но заляпали. А через пару недель пришел ответ, мол вопрос решен и будь добр удостовериться. Ну да, я удостоверился, какие-то механизмы таки работают. Пусть это почти идеальный случай, но я не о том. Я ж местным рассказываю, мол, так и так, приложение на тачфоне, потом опубликовал, потом распечатал, потом письмо заказное, но можно и обычным. Для заинтересованного человека сложность нулевая. А оказалось, что никак заляпанные ямы с моей деятельностью связаны быть не могут, что чуть ли не три года назад сельсовет этот ремонт утвердил. А факты игнорируются, что, например, заделаны исключительно сфотографированные мною ямы (а три метра влево по дороге, где мне делать нечего продолжают зиять), что через 6 дней после заявы ремонт прошел. И мне там общаться не с кем, в основом знакомые родителей, что живут здесь. Вот у них такое мнение, что никакие механизмы не работают, а если бы хоть что-то работало, то все решилось бы само собой. А потом начинаются дебаты про образование, про промышленность, про совок и так далее.

больше ерунды )
stdray: (Default)
Во-первых, стала падать какая-то ерунда, мол "хотим разместить рекламу в вашем блоге" или там "заработайте на вашем блоге". Ох уж мне эти блоггеры. У меня днявка полумертвая, но, видимо, как цель для спамера не лишняя.

Во-вторых, что гораздо хуже, кто-то таки додумался купить большую пачку смс-сообщений у оператора, купить пользовательские базы и начать торговать спамом в смс. Ну и понеслась: такси, распродажи, пиццерии, скидки и прочее. А смс не почта, никто пока фильтрацией не заморачивался, по крайней мере в России. А теперь вот спамят. Может бы и прибить этот странный старый протокол обмена сообщениями, чтобы не уходить на второй круг. Так нет, даже компания, выбрасывающая под радостные аплодисменты хипстоты на свалку истории такие бородатые штуки как RJ-45, тащит в тачфон эти самые смс. Как представлю папку "Спам" с смсками... А ничего не сделать. Большая инерция.
stdray: (Default)
Часто слышу от своих знакомых, программирующих на C# и использующих ReSharper, что едва ли не самой полезной возможностью решарпера является проверка стиля кодирования. То есть решарпер проверяет правильность именования переменных, всякие там Pascal Casing для имен типов, Camel Casing для переменных и прочее такое. В этом есть смысл, поскольку многие программисты style guide не читают, а я читал, но почти ничего не помню. И тоже полагаюсь на ReSharper, хоть и регулярно возникают с ним разногласия.

А вот для Nemerle никакого решарпера нет, более того, нет никакого style guide. Размышляя над этим по дороге, я пришел к выводу, что второе существенно, а первое - не очень. Поскольку многое можно сделать на макросах. Например, захотел я удостовериться, что названия всех типов начинаются с большой буквы. Да еще чтоб я мог выбирать, что делать с несоответствием: выдавать ошибку компиляции, предупреждение или просто проинформировать. Несложно. Для этого надо лишь объявить макрос-атрибут уровня сборки

[MacroUsage(MacroPhase.BeforeInheritance, MacroTargets.Assembly)] \

macro CapitalTypeNames(alertType : string)

NameConventionImpl.CapitalTypeNames(Macros.Manager(), alertType)


А при его вызове, собрать типы, объявленные в сборке, отфильтровать имеющие некорректные названия и вывести информацию указанным образом. Read more... )

August 2017

S M T W T F S
  12345
6789101112
13141516171819
20212223242526
27282930 31  

Syndicate

RSS Atom

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags