Миграция с 9.3 на 9.6

January 27, 2017

В прошлом году (люблю январь, "в прошлом году" звучит как давно-давно, на самом деле это было в 20-х числа декабря :smile:) мы переносили один проект на другую площадку и решили заодно обновить версию постгрес с 9.3 до 9.6.

В самой большой таблице, которая по правилу Паретто занимает 80% места, есть увесистая json-колонка data, по которой выборки реалтайм не происходят, но сохранять эту информацию нужно. И в постгрес за три минорных версии как-то так хорошо оптимизировали хранение JSON на диске, что база, которая занимала 30 гигабайт раньше, стала занимать 5 гигабайт.

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

Оптимизация одного скрипта

January 26, 2017

Руби дарит нам радость, а взамен жрет память и CPU. Руководствуясь этим тезисом, оптимизирую руби код очень редко. Однако недавно столкнулся в любопытной штукой, когда изменение в одной строчки уменьшило время выполнения c 10 секунд до долей секунды.

У нас есть набор скриптов, которые запускаем вручную для проверки целостности различных параметров инфраструктуры, и там есть примерно такая строчка, которая выполняется навскидку 60 тысяч раз за один прогон:

... if string =~ /#{name}-\d{4}-\d{2}-\d{2}__\d{2}_\d{2}_\d{2}/

Оказалось что создавать регексп на лету - весьма и весьма медленно, лучше создать его один раз и использовать столько раз, сколько надо:

RE = /#{name}-\d{4}-\d{2}-\d{2}__\d{2}_\d{2}_\d{2}/
# ...
... if string =~ RE

Простой бенчмарк показывает, что разница по времени исполнения почти в два порядка, причем в важном для комфорта диапазоне:

require 'benchmark'

c = 60_000
name = "head"
re = /#{name}-tail-\d{4}-\d{2}/
string = "head-tail-2012-12"
i = 0

Benchmark.bm do |bm|
  bm.report { c.times { i += 1 if string =~ /#{name}-tail-\d{4}-\d{2}/ } }
  bm.report { c.times { i += 1 if string =~ /#{name}-tail-\d{4}/ } }
  bm.report { c.times { i += 1 if string =~ /#{name}-tail/ } }
  bm.report { c.times { i += 1 if string =~ re } }
end
puts "i: #{i}"

#  user     system      total        real
# 1.340000   0.020000   1.360000 (  1.373314)
# 0.820000   0.010000   0.830000 (  0.843216)
# 0.390000   0.020000   0.410000 (  0.406644)
# 0.020000   0.000000   0.020000 (  0.035978)
# i: 240000

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

Сложности синхронизации

January 25, 2017

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

Среди хранилищ файлов - мой фаворит всегда был и остается дропбокс. Яндекс диск - имхо похуже, а раньше и сильно похуже. Гугл драйв - плохо даже, когда можно было бы хорошо. При таких прекрасных таблицах и документах, такой ужасный диск. Хм.

Мой любимый мессенджер - сейчас телеграмм, мне кажется он лучше работает, даже чем iMessage. А среди списков дел победитель - Тудуист. Тудуист кстати, помимо приятного вида, покорил как раз синхронизацией, она работает реально достойно. Забавно, что API у них не привычно REST-подобный, а заточенный под синхронизацию, через единый POST-запрос /sync. Прикладные программы писать не очень удобно (я пробовал ради фана, но потом прикрутил zapier-рецепт для переноса событий из календара в тудушки), однако официальные клиенты на этом API работают замечательно.

Авантюрная мечта

January 24, 2017

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

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

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

PS. Историю с таксистами мне давно хотелось написать, она мне нравится, но вот где еще больший капец, так это в статье на гигтайтм про Amazon Mechanical Turk, когда люди день за днем делают абстрактную, непонятную хрень, это матрица и есть родимая. Тук-тук, Нео.

Почты поток

January 23, 2017

Сочиняя прошлый пост про BCC, заметил одну любопытную штуку с почтой. 10 лет назад я работал самым обычным программистом и получал 100-200 и больше писем в день. Сколько получали писем руководители даже не хочу думать. Человека, который выходил из отпуска, в этот день не трогали, он проверял почту.

Вообще это была мощная страшилка, почты становилось все больше и больше, и как урбанисты 19-го века боялись, что крупные города будут полностью завалены конским навозом, так и офисные работники 20-го века считали, что скоро они будет тратить на почту весь рабочий день.

Что ж, 2017 год, и я искренне могу сказать тем, кто за нас переживал - а мы молодцы, мы не утонули в почте. Я сегодня получаю писем гораздо меньше, чем 10 лет назад и нет ощущения, что трачу на емейлы хоть сколько-то значительное время.

Много общения перешло в мессенджеры, трекеры, где можно потусоваться, а можно отключиться и реагировать только на меншены. Интерфейсы стали гораздо лучше, разработчики Google Inbox, считаю, очень хорошо постарались. Активности "я проверяю почту" в моей жизни больше практически нет.

BCC

January 20, 2017

Как говорят мудрейшие, жизнь нужно прожить не отправив письма с BCC. Все случаи использования Blind Carbon Copy, про которые я слышал - обычно вещи разной степени грусности. В переписке с другим отделом ставить своего руководителя в BCC и потом джага-джага. Или письмо со сканом уходит с BCC к безопаснику и джага джага. И разные другие кейсы непременно с половым исходом.

Один раз я был в треде с типом, который отправлял все ответы с BCC к своему, скажем так наставнику (хотя можно было его включить и в открытую, там просто рабочие моменты были). И потом наставник сдал своего протеже, ответив в интересном ему месте Reply All. Преступление и наказание в 21 веке выглядит именно так.

Я знаю всего один вариант легального использования BCC, правда не встречал в живой природе. Если вы хотите перестать утомлять кого-нибудь в большом емейл треде, то пишите "исключаю Василия Ивановича из копии, поставив его в BCC" и ставите его в BCC :smile:. Красивый ход.

Terraform + GCE = ♥

January 19, 2017

Мы потратили несколько месяцев пока приручили Селектел с Терраформом и перевели все сервера на него. И оно стоило того! По-мимо того, что инфраструктура стала на порядок контролируемее, недавно мы получили еще один подарок. Понадобилось развернуть один продакшен на Google Cloud Engine - берешь и разворачиваешь :smile:. Нашему девопсу пришлось чуть-чуть разобраться как там устроена сеть, как собирать сервера - и вжух, новый продакшен готов. Даже не пришлось разбираться с UI (а потыкать там есть где, не Амазон конечно, но все-таки).

yarn

January 18, 2017

Как вы знаете, штудирую ноду, с удивлением узнал, что npm нужно менять на yarn! Просто меняйте не думая, так как yarn создает yarn.lock, который как Gemfile.lock будет присматривать за точными версиями всех зависимостей (да-да, npm не гарантирует точных версий всех пакетов).

Вообще очень любопытно наблюдать за пакетными менеджерами. Питон я не знаю совсем, но слышал, что там два менеджера минимум, pip и easy_install, что намекает. В руби, начиная с бандлера, жизнь чудесна и безоблачна, если я правильно помню, появился он вместе с релизом рейлс 3.0, был довольно медленный, но прекрасный. Я застал времена, когда гемы и рейлс целиком еще лежали в vendor (и кстати их там еще и хачили, как-то видел проект на 2.3, в котором в вендоренном рейлс было несколько десятков изменений - :scream_cat:).

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

Первая причина это ты, а вторая все твои мечты

January 17, 2017

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

Поэтому каждый раз, когда вижу любое перечисление чего-нибудь (особенно если есть ключевое слово "причины"), стараюсь найти то единственно важное, что могло бы заменить список. Очень забавное упражнение и мощный инструмент анализа.

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

Не всякий лодаш одинаково хорош

January 16, 2017

При работе с JavaScript всегда подключал привычно Underscore.js, но всегда помнил идею, что Lodash - тоже самое только гораздо лучше по каким-то там параметрам. Именно так писали про Лодаш, когда он появился (а если я правильно помню, то Андескор появился раньше).

Недавно, балуясь с нодой, подключил const _ = require("lodash") и очень быстро нашел отличие. В андескоре есть три варианта вызова методов:

consts _ = require("underscore")

// два вида записи одного и того же:
_.groupBy([1], x => x)  // => {'1': [1]}
_([1]).groupBy(x => x)  // => {'1': [1]}

// и специальный синтаксис для колбас:
_.chain([1]).groupBy(x => x).keys().value()  // => ['1']

В лодаш же так (хотя _.chain тоже работает скорее всего для совместимости):

consts _ = require("lodash")

_.groupBy([1], x => x)  // => {'1': [1]}
_([1]).groupBy(x => x).keys().value()  // => {'1': [1]}

Хм. В Андескоре привычнее, так как пользовался много лет, но в Лодаш, пожалуй, логичнее.

PS. Документацию не читал, нашел разницу экспериментально.