Заметки: Работа

Мои мысли о жизни, работе и разных интересных штуках вокруг меня.

Показано: 0 · Страница

В пятьдесят раз быстрее
5 декабря 2019 ·

Получил вводную: документ закрытия месяца у заказчика проводится без малого час. База не особенно большая, но такая продолжительность в любом случае не вариант. Даже если учесть, что закрытие месяца — это ни разу не частотная операция и её можно делать, например, ночью.

Лезу в код, делаю замер производительности и вижу, что и почти всё это время платформа тратит на одну-единственную процедуру, выполняя пакет запросов. Смотрю первый из них; ну, думаю, классика — запрос данных через точку от составного типа. Наверняка СУБД пристегивает целый вагон соединений с тяжеленными таблицами документов, вот оптимизатор и не успевает набросать адекватный план.

Проверяю теорию — так, а тип SalesDocument включает всего восемь документов. Это, условно, в пределах допустимого (считается, что оптимизатор в состоянии подобрать адекватный план выполнения запроса, если количество соединений — в пределах восьми).

Смотрю размеры таблиц документов — не особенно-то и большие. Выполняю запрос отдельно от пакета — да, работает не мгновенно (читает около 350 000 записей и отбирает примерно 200 000), но никак не час.

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

Проверил — именно тут платформа и проводит большую часть времени, ожидая ответа от СУБД.

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

Это тот случай, когда общая рекомендация 1С сработала идеально — вместо 50 минут документ стал проводиться за три, а после дополнительной оптимизации кода — за минуту. То есть, в пятьдесят раз быстрее того, что я имел вначале.

Такой результат я счел достаточным (минута для закрытия месяца — это в общем случае нормально) и остановился.

На, мужик, изоленту
2 августа 2019 ·

Начитанные друзья иногда спрашивают — мол, какая у тебя любимая книга? Мне, блин, всегда чутка стыдно отвечать на этот вопрос, потому что при всём том огромном выборе, который есть, это «Марсианин» Энди Вейера.

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

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

― Энди Вейер, «Марсианин»

И приятнее пахнуть
10 июня 2019 ·

На днях выпустили очередный релиз FirstBIT ERP (наш программный продукт для автоматизации бизнеса в ОАЭ). Вложен вагон труда, всё работает как надо, есть чем гордиться и всё такое. Я, например, кучу сил потратил на то, чтобы сделать полноценный обмен данными с Битрикс24 и порядком рад, что успел этот механизм зафиналить.

Но в душе всё равно немного завидно коллегам из геймдева: наши патчноуты, конечно, тоже интересные, но такого там всё-таки не встретить.

Растолстевшие роли
18 апреля 2019 ·

Очень любопытная заметка про неприятности, которые можно нажить командой роли «Снять все права». Нет, никакого криминала, права-то она честно снимает — только вот её вызов может привести к тому, что объект роли на пустом месте сожрёт в несколько раз больше памяти, чем ему реально нужно.

Прочитал, задумался и пошел проверять, как обстоят дела с этим у нас в конфигурации. И что бы вы думали? Накопал десятка два ролей, доверху набитых «снятыми галочками». Выгрузка прав весила около трёхста мегабайт, а после оптимизации — усохла почти втрое.

Любопытно, как это до сих пор оставалось незамеченным. Скорее всего, из-за количества объектов — у нас сравнительно небольшая конфигурация. То есть проблемные роли потребляли не так много ресурсов, чтобы мы что-то заподозрили.

Простая галочка
30 марта 2019 ·

Пару недель назад мы добавили в справочник номенклатуры FirstBIT ERP параметр «Inactive». Задача была простой: если товар больше не нужен пользователю — он ставит галочку и тот исчезает отовсюду (из форм выбора, форм подбора остатков на складах и так далее).

Звучит несложно, правда? Техническая реализация тоже была простой — мы прошлись по всем объектам, в которых предполагается выбор номенклатуры, и добавили дополнительный параметр этого выбора.

Параметры выбора

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

Мы принялись искать выход. Проблема в том, что история ввода хранится в системном хранилище и повлиять на неё программно нельзя. Можно разве что полностью удалить — но фактическая очистка истории происходит только при перезапуске клиента (и то через раз). Отключить историю вообще? Напоминает лечение простуды отсечением головы.

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

В общем, мы создали такой параметр. Хранится в общем хранилище и транслируется в формы при их открытии через общий модуль, который программно добавляет параметр выбора. Если пользователь снимает или устанавливает флаг Inactive для любой номенклатуры — значение параметра меняется, а уже открытые формы получают его через механизм оповещений.

Минуточку!

А ведь как все невинно начиналось, а?

Однако механизм неплохо работает, хотя его недостатки налицо: во-первых, системное хранилище будет постепенно пухнуть по мере появления всё новых и новых сочетаний реальных параметров выбора и нашего, фиктивного. Во-вторых, запись номенклатуры теперь потенциально узкое место: два пользователя не смогут одновременно записать номенклатуры, у которых изменены флаги Inactive (будет блокировка при записи нового значения нашего скрытого параметра выбора в общее хранилище).

Первую проблему можно решить очисткой хранилища по какому-то триггеру, вторую — записью нашего параметра выбора в разрезе пользователей (например, через регистр сведений). Впрочем, мы искренне надеемся, что 1С даст какой-то доступ к истории ввода до того, как нам придется городить дополнительные костыли к тем, что мы уже наворотили :-)

Повторяющийся ключ
1 марта 2019 ·

На Инфостарте вышла любопытная статья про ошибку СУБД «cannot insert duplicate key». Одна из возможных причин сбоя — использование уникального идентификатора объекта для сопоставления при обмене с другими информационными базами (то есть, без служебного регистра, сопоставляющего объекты базы данных с идентификаторами объектов внешней базы).

Такой жести, чтобы уникальные идентификаторы совпали в разных базах для одной и той же таблицы, у меня в практике пока не было. Однако от подхода «единого идентификатора» я отрекся окончательно после того, как делал обмен между FirstBIT ERP и GROTEM / Agent.

Архитектура пилотного решения была такая: данные из FirstBIT ERP выгружались сперва в служебную ИБ 1С, написанную разработчиками GROTEM'а, а уже оттуда — в основную базу данных сервера мобильных приложений.

Сопоставление было сделано очень просто — через идентификаторы объектов. Например, один и тот же документ в обеих базах имел один и тот же идентфикатор. Но были и более сложные схемы: например, контрагент FirstBIT ERP на стороне GROTEM'а превращался в три объекта: собственно контрагента, торговую точку и документ взаиморасчетов.

WAIT WHAT

Да, в документ взаиморасчетов. И все три объекта имели один и тот же идентфикатор — идентификатор контрагента FirstBIT ERP. В общем, не то чтобы это было очень изящным решением, но для платформы такой расклад вполне адекватен и мы решили, что проблем быть не должно.

Однако обмен работать отказался.

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

В итоге выяснилось, что:

  1. В этой самой базе есть таблица, где хранятся все интересующие нас объекты. Документы, элементы справочников, вот это всё.
  2. Эта таблица имеет уникальный индекс по GUID объекта.

В этом месте интрига закончилась. Ну да, первый же выгруженный контрагент создавал целых три сущности с одним и тем же GUID, которые прекрасно лежали в своих таблицах на стороне 1С, но не могли быть записаны в одну общую таблицу базы данных приложения.

I will not use GUIDs to map objects!

Неудачная охота
21 февраля 2019 ·

При обновлении платформы до 8.13.12.1790 наткнулись на плавающий баг при переключении текущей страницы элемента на сервере. Конкретно на сервере оно срабатывает, но как только управление возвращается на клиент — текущей страницей становится та, что была до изменения. При этом ещё и происходит событие изменения текущей страницы (как будто пользователь сменил её вручную).

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

И вот, наконец, ты смотришь на проблему под правильным углом, а она — обычный жук. Возможно, полосатый или в крапинку, но жук как жук — сидит себе, шевелит усами. И ты такой: блин, это что — и есть моя добыча? :-)

Эволюция
16 февраля 2019 ·

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

В итоге мы задерживаем дыхание, когда глотаем, путаемся между dissatisfied и unsatisfactory, а ещё программируем на чудесном языке JavaScript — который, при всём своем удобстве и распостраненности, вобрал в себя все мыслимые и немыслимые недостатки скриптовых языков.

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

Зная всё это, мне чуть-чуть проще смотреть на то, во что иногда превращается мой код на очередном цикле разработки. Ну и что, что у этого хомячка отрос драконий хвост? Эволюционно, например, такой хвост очень полезен. Кто я такой, чтобы спорить с Дарвином?

Твит

Конкатенация строк
27 января 2019 ·

Как и многие другие компании, мы даем соискателям тестовое задание. Оно намеренно несложное и нужно больше для того, чтобы посмотреть — насколько кандидат понимает платформу? Как аккуратно работает с объектами конфигурации и её кодом?

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

Однако тут есть другой аспект. В первой половине прошлого года «Рарус» опубликовал отчет о работах, проделанных для «Билайна». Там много любопытного, но среди прочего есть совершенно оглушительный пункт: за счет отказа от соединения строк разработчики добились 40% снижения нагрузки на процессоры! От двух дополнительных серверов после этих изменений вообще отказались, так как они стали не нужны.

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

Распределенный дизайн
20 октября 2018 ·

Дизайнер из «Stack Overflow» написал о том, как они организуют удаленную работу. Понравилась структура текста — не просто «как мы это делаем», а прямо парами: проблема + решение.

У нас в компании почти вся разработка — удаленная и сам я — тоже удаленщик. Мне очень нравится так работать; главное тут — помнить, как легко нахватать самых неожиданных проблем, когда твое рабочее место и твой дом — одно и то же место. Советы из статьи пить воду и вылезать под солнце вполне себе актуальны, например — в ходе какого-нибудь кранча про это и правда легко забыть.

Разные стороны медали
5 марта 2018 ·

Привет!

Фидбек — одна из самых клевых штук в моей профессии. Да, не первый год программирую, да, кучу всего написал, переписал и переделал, и всё равно каждый сложный механизм, наконец заработавший так, как надо — это… Ну, не знаю. Как снова и снова слышать «да» на выпускном бале :-)

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

Выгрузка автобусных рейсов
17 ноября 2017 ·

С тех пор, как мы с коллегами заново автоматизировали КПАТ, она работает на «Управлении автовокзалами». Это конфигурация для 1С:Предприятия, то есть её можно сравнительно быстро интегрировать почти с чем угодно.

Первым делом мы решили наладить выгрузку маршрутного расписания автобусов на E-Traffic и Яндекс.Расписания.

Что это за ресурсы?

Первый ресурс, E-Traffic — это крупнейший в России агрегатор данных автовокзалов. Собирает информацию о запланированных рейсах и выступает как агент по продаже электронных билетов. То есть пассажирам не нужно продираться через сайты автовокзалов — на E-Traffic можно купить билет откуда угодно куда угодно.

Что касается Яндекс.Расписаний — это один из дочерних проектов российского поисковика. Как и E-Traffic, предназначен в первую очередь для пассажиров и умеет быстро строить относительно сложные маршруты с пересадками. Билетами они, правда, не торгуют.

Как была сделана выгрузка?

Поначалу мы нагородили довольно сложную архитектуру, позволяющую транслировать расписание в обе системы. Потели как черти — пока в ходе переговоров не выяснилось, что у E-Traffic уже есть рабочий транспорт для передачи расписания в Яндекс, и задача естественным образом не усохла вдвое.

Технически всё было сделано в виде веб-сервиса для «Управления автовокзалами». Получив SOAP-запрос от E-Traffic, он собирал внутри информационной базы 1С:Предприятия все необходимые данные о запланированных автобусных рейсах и возвращал их в виде XML-ки.

Нам даже не пришлось писать код получения расписания с каждого вокзала, входящего в сеть КПАТ'а: все они создаются и хранятся в одном месте — главном узле РИБ, а веб-сервис мы развернули именно там. В итоге больше времени ушло на разные согласования, чем на программирование.

А где посмотреть?

Внутренняя кухня снаружи не видна, да и там ничего необычного — роботы общаются с роботами, эка невидаль :-) Результат их болтовни — куда интереснее! Например, вот расписание рейсов из Кемерово в Новокузнецк на сегодня.

Стоп-слова для интерфейсов
14 января 2017 ·

Любопытная заметка про термины и формулировки, которые лучше не применять при разработке интерфейсов. Позабавила ремарка про аутентификацию и авторизацию.

И, конечно, список выглядит неполным без знаменитых контактов (и полупроводников) :-)

Авибус
16 февраля 2015 ·

Конфигурация для 1С:Предприятия, которую мы пару лет назад внедряли на кузбасских автовокзалах, обзавелась симпатичной обложкой.

По-моему, очень круто! В том числе и тем, что это один из проектов, постепенно разрушающих заплесневелый, но невероятно устойчивый даже среди айтишников миф про 1С — типа, это скучный тормозной софт для бухгалтеров, а настоящие пацаны пишут только на C++ (Java, Javascript, подчеркните, впишите) и тому подобные бредни.

Польза от блога
1 февраля 2015 ·

Всеволод Устинов написал любопытную заметку по поводу ведения рабочего блога.

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

Ещё полезные ссылки на ту же тему:

Движение вперёд
20 января 2015 ·

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

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

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

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

Столп света
7 апреля 2014 ·

Чтение собственного прошлогоднего кода отчетливо отдает мазохизмом: ага, вот тут я неявный запрос в цикле организовал, а вот тут — получил таблицу остатков и зачем-то сгруппировал её. Молодец, дружище!

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

Частная станция
3 февраля 2013 ·

Кассы Беловского автовокзала изнутри остро напомнили старый-престарый симулятор больницы для DOS — «Theme Hospital».

Во всяком случае я, когда играл, кабинеты терапевтов делал по тому же принципу: одинаковые квадратные комнатки, урна строго в одном углу, цветок строго в другом углу, батарея строго под окном и так далее :-)