вторник, 26 декабря 2017 г.

Про производительность PWA и single page приложений

         Меня давно посещала мысль что все эти PWA/single page application и переиспользование JS кода это утопия. И эта утопия достижима только если вы работаете над государственным проектом и вам насрать на performance budget. А как только у вас появляются реальные требования по производительности то выяснится что стратегии оптимизации client side JS и server side JS - совсем разные, можно сказать противоположные. 
         К примеру в этой статье  https://habrahabr.ru/post/345212/.com[perevod]-vy-mozhete-sebe-eto-pozvolit - наглядно доказано что написать хорошее PWA/single page application это очень сложно. Я давно подозревал что это именно так, что обеспечение быстрой первой загрузки - это пиздец какая проблема, но у меня не было данных чтобы это доказать. Теперь есть. 
         https://hpbn.co/ - High Performance Browser Networking by  Ilya Grigorik - надо будет обязательно прочитать.

понедельник, 25 декабря 2017 г.

Exceptions в Java

     Многие критикуют Golang за отсутсвие Exceptions. Якобы из-за этого пишется очень много кода по обработке ошибок. С одной стороны это правда, этот код писать нужно. Ошибка сама не всплывет вверх по стеку, поэтому как минимум if + return написать придется. Но с другой стороны этот подход оказывается оправданным для performance critical code. В этой статье - http://java-performance.info/throwing-an-exception-in-java-is-very-slow/  анализируется производительность Java Exceptions. Оказывается бросить исключение это пиздец как медленно  - 1-5 микросекунд. И для performance critical кода предлагается кэшировать исключения. По-моему это костыль хуже некуда. Либо возвращать кастомные объекты со строкой сообщение об ошибке внутри. Это тот же самый error в Golang. В общем когда смотришь на Java с опытом использования Golang - то все выглядит совсем не так радужно как это выглядело раньше. 

Коллекции в Java

      В своем недавнем посте я разнес в щепки стандартную реализацию HashMap в  Java. Оказывается не все так плохо. Не я один считаю что стандартный HashMap отстой, и Java коммьюнити написало альтернативные варианты реализации HashMap.  В http://java-performance.info/hashmap-overview-jdk-fastutil-goldman-sachs-hppc-koloboke-trove-january-2015/ проведено неплохое сравнение этих реализаций. Чемпионами оказались fast utils и  Колобок! В общем пошел читать исходники fast utils, буду учиться писать на Java у настоящих мужиков.

среда, 20 декабря 2017 г.

Golang sync.Map

      sync.Map в появившийся в Golang 1.9 оказался довольно занятной штуковиной. Я посмотрел видео с конференции:
 Перечитал еще раз слайды - https://github.com/gophercon/2017-talks/blob/master/lightningtalks/BryanCMills-AnOverviewOfSyncMap/An%20Overview%20of%20sync.Map.pdf но все равно не мог четко понять - в каких случаях стоит использовать sync.Map а в каких обычный map[] + mutex. Может недостаточно понятно написано, может просто я такой одаренный. В общем мне чтобы разобраться нужно залезть в исходники, что я собственно и сделал - https://golang.org/src/sync/map.go?s=822:2269#L16
          Итак под капотом sync.Map находятся две map[] - readonly map и dirty map. Readonly map используется для быстрого чтения/записи уже существующих значений. В readonly map храниться не само значение а указатель на него. Для чтений значения используется  atomic.LoadPointer(), для записи - atomic.CompareAndSwapPointer(). Это так называемый fastpath, то есть собственно для чего все и затевалось. И используем мы этот fastpath если пишем или читаем значения по уже существующим ключам. Все остальное - происходит уже не так быстро. В случае если мы вставляем новое значение - оно попадает в dirty map. Все операции с dity map происходят с заблокированным мютексом. После какого-то количества cache miss - попыток чтения новых значений из readonly map происходит промоушен dirty map до readonly map.  После этого все недавно добавленные ключи можно будет читать писать без блокировки. 
        Итого: читаем/пишем по существующим ключам очень быстро (сильно быстрее map + mutex),  потребляем в 2 раза больше памяти на указатели/хэш таблицы(dirty map также хранит все ключи из readonly map). Но размер значений тут никакой роли не играет, так как мы не храним значения а только указатели на них.  Добавление новых ключей и look up по вновь добавленным ключам происходит сильно медленнее обычной map + mutex потому что появляется дополнительный indirection level(указатели), и сами операции с ними - atomic, а это значит много memory barrier-ов.    

вторник, 19 декабря 2017 г.

Проникновение ИТ в быт

     В очередной раз убеждаюсь что по некоторым параметрам Китай уже далеко впереди планеты всей. Один из эти параметров - это проникновение ИТ в быт, в традиционные отрасли бизнеса не связанные с ИТ. Почему-то в Европе да и у нас - ИТ (за небольшим исключением) сосредоточено вокруг интернета и "около интернетных" областей деятельности. Такие области деятельности как ресторанный бизнес вообще  ИТ вообще не сильно затронуло - за исключением разве что кассового аппарата. Здесь в Ханчжоу во многих ресторанах на уголок стола приклеен QR код, отсканировав который в AliPay приложении  ты можешь сразу увидеть меню, сделать заказ, а когда покушаешь - и сразу оплатить его. Причем люди сидящие за одним столом могут видеть что заказывают другие, и один человек может оплатить за всех. В некоторых местах бумажного меню вообще нет, в принципе. А нахера оно если у каждого есть смартфон и AliPay ??
         Тоже самое с такси - все без исключения таксисты принимают AliPay. Многие даже не хотят с наличкой связываться вообще, требуют AliPay. У нас только ленивый не потешается над платежной системой МИР. А китайцы сделали себе UnionPay и в ус не дуют. Международные кредитные карточки мало где принимают. В основном только в гостиницах и аэропортах. Ну еще из банкомата можно наличку снять. А так - либо UnionPay, либо AliPay. 

Нанкин (Nanjing)

     На выходных довелось побывать в южной столице Китая - Нанкине. Этот город был столицей поднебесной до того как ее перенесли в северную столицу - Пекин. Сейчас Нанкин это средний по китайским меркам город, что-то около 8 миллионов житилей. В нем расположены довольно много достопримечательностей: гробницы времен династии Мин, мавзолей Сунь Ятсена, древние крепостные стены. Много парков и озер. Несмотря на размер оставляет впечатление довольно провинциального города. Не китайскую еду или кофейню найти очень проблематично. Зато женщины там заметно красивее тех что я наблюдаю в Ханчжоу или Шанхае.  


Разучились работать

      В последнее время я довольно тесно вовлечен в один из проектов над которым работают наши китайские коллеги из сами знаете какой компании. Невольно замечаю некоторые  "национальные особенности" работы. Работают ребята как проклятые. Никаких тебе разговоров про мотивацию, work-life баланс - такое впечатление что они вообще не знают что это такое. Такое впечатление что их команды вообще работают вопреки законам people management-а. Начальник прилюдно распекает подчиненного на чем свет стоит,   тот утирает сопли(образно) и еще шибче начинает работать. У нас стоит какому-нибуть менеджеру себе такое позволить - да его самого за такое уволят. И тот человек на которого накричали полгода после этого будет "демотивированным".  В общем разница в менталитетах - просто колоссальная. 
       Да,  очень много из того что они делают - они делают не оптимально, да сам результат зачастую выглядит как говно (костыль на костыле) - но они делают чтобы это гавно работало, и делают это в срок. И это просто невероятно. Потому что дедлайны изначально ставятся нереальные. И они умудряются в них укладываться. За счет нереальной самоотдачи. Когда в 9 вечера находят с десяток багов и к утру разработчик обещает все пофиксить.  Да я честно уже не вспомню когда я такое встречал в лазаде. У нас дедлайн по задачам в днях измеряются, и один день - это вообще минимальная единица измерения. А тут чувак обещает что все к утру исправит. Я уверен что он домой сегодня не попадет и что за овертайм ему никто не заплатит. 
       Плюс к этому строгая дисциплина, где дедлайн - это действительно  dead line и переступить его - смерти подобно. И дедлайны эти контролируются дважды в день, так что не забалуешь. В общем это производит впечатление такого бездушного комбайна который выжимает из людей все соки, но достигает цели. Не берусь судить - хорошо это или нет, но мне кажется мы уже разучились так работать.  И именно поэтому конкурировать с ними мы уже врятли сможем. 

понедельник, 18 декабря 2017 г.

Java HashMap vs Golang map[]

      Волею судьбы сейчас я плотно занимаюсь Java, вместо горячо любимого мною Golang. Ну и попутно сравниваю как решены те ил иные задачи в Golang и Java. Сегодня речь пойдет про хэш таблицы. С точки зрения алгоритмов HashMap и map[] практически идентичны - hash table + разрешение коллизий через цепочки. Но это теоретически, а с практической точки зрения реализация значит ничуть не меньше чем выбранные алгоритмы. Итак начнем: исходники HashMap я взял отсюда, а исходники map[] отсюда

Golang map[]

    1. Общее устройство. Данные хранятся в блоках по 8 элементов. Младшие 3 бита хэша используются для идентификации key-value пары внутри блока. Хэш таблица представляет собой массив из таких восьми-элементных блоков.  Первый блок из восьми элементов всегда располагается непосредственно в хэш таблице.  У этого есть важное следствие - Go map[] чувствует себя очень комфортно при количестве коллизий меньше 8 на элемент хэш таблицы. С учетом того что удлинение цепочки коллизий также происходит блоками по 8 элементов, то go map[] вообще весьма устойчива к росту числа коллизий.  Сам блок представляет из себя структуру из 8 однобайтовых значений для хранения младших битов хэшей, затем 8 ключей и 8 значений. В зависимости от типа ключей и значений они могут хранится непосредственно в этой структуре данных либо там могут хранится только указатели на них.
    2. Хэш функция - Go использует в качестве хэш функции встроенную в большинство процессоров функцию AES шифрование(инструкция AESENC). 
    3. Начальный размер хэш таблицы:   
           3.1 Для пустого map[] хэш таблица вообще не создается, 
           3.2 Если при инициализации map capacity указана меньше 8  - то хэш таблица также не создается.
          3.3 Если capacity указанная при создании map[] больше или равно 8, то размер таблицы рассчитывается как ближайшая степень двойки для которой выполняется условие (1 << B) * loadFactor > count, где B - степень двойки, loadFactor - магическое число равное 6.5, count - map[] capacity указанная при инициализации.  
    4. Расширение хэш таблицы. При расширении хэш таблицы учитывается два фактора:
        a. Количество элементов в map[], при этом логика аналогична описанной выше (как при инициализации map[])
        b. Количество цепочек длинной больше 8 элементов. Как я написал выше  Golang map[] оптимизирован для работы с цепочками длинной менее 8 элементов, поэтому реализация заточена на то чтобы сохранить длинну цепочки от одного до двух элементов. Так как счетчик "переполнений"(цепочек длинной более одного элемента) это uint16, то сама логика различается для map размером хэш таблицы меньше (1 << 16) и больше этого значения.
        если размер таблицы меньше чем (1 << 16) то хэш таблица расширяется в случае если количество цепочек с переполнением становится больше чем (1 << B) (где B - степень двойки, размер хэш таблицы). 
       если размер таблицы больше чем (1 << 16) то логика остается той же, но расчет количества "переполнений" становится приблизительным.
      Если принять во внимание то что в одном звене цепочки может находится до 8 элементов - то расширение хэш таблицы случается всегда по первому условию ( количество значений больше чем 6.5 * (1 << B)).  

Java HashMap 

1. Общее устройство HashMap предельно простое. Это классический hash map как он описан в учебниках по программированию. Хэш таблица представляет собой массив Entry, в каждом Entry ключ, значение и указатель на следующий Entry. Никаких хитростей и попыток оптимизировать что-то. Прям скуку смертная да и только.
2. Хэш функция - как я понял вызывается встроенный в объект метод hash() к которому сверху применяется простейшая XOR функция:
3. С начальным размером таблицы все тоже очень грустно - оно всегда равно 16 элементам. Либо ближайшей степени двойки большей чем требуемая capacity.
4. Расширение хэш таблицы реализовано также крайне просто - есть loadFactor, равный 0.75. Как только количество элементов в HashMap превышает текущее capacity на 75% ее размер увеличивается в двое. Расширение HashMap также происходит предельно просто - выделяется новая хэш таблица, в цикле проходимся по старой таблице и перекладываем ее элементы в новую таблицу. 

Вывод

  
В общем признаться честно - java меня разочаровала. Единственное достоинство реализации HashMap - это простота реализации. Все просто и понятно. Негде там ошибиться. 
По сравнению с этим реализация map[] - это вершина инженерной мысли. Как Porshe 911 по сравнению со старым фордом. В map[] экономится каждый бит. Многих оптимизаций без хорошего понимания ассеблера просто не понять. Количество аллоцируемых объектов,  ссылок в Golang map[] на порядок меньше чем в HashMap, а это значит что и  гораздо меньше работы для сборщика мусора. Также гораздо выше memory locality. В Golang даже floating point арифметику лишний раз стараются не использовать, заменяя сдвигами и другими целочисленными операциями.  В общем мне стало немного понятнее почему софт на Java так тормозит.

вторник, 21 ноября 2017 г.

Golang internals

        За что я люблю Golang - так это за то что ему сравнительно легко заглянуть под капот. Golang это единственный известный мне язык программирования runtime которого написан на нем самом а не на C(на 99%,  там есть немного ассемблера). То есть барьер между написанием программ на языке Go и заглядыванием внутрь - сильно ниже чем у того же PHP или Python. 
    Заглянув в runtime/стандартную библиотеку ты получаешь гораздо более глубокое понимание того как на самом деле работают приложения написанные на Golang. Там очень много красивых решений, которым можно поучится. Вообще когда ты читаешь как реализованы production class решения, ты на многие вещи начинаешь смотреть по другому.
         К примеру сортировка. Существует многие десятки алгоритмов сортировки, какой из них выбрать? Казалось бы - смотри на Big O и выбирай. Но это теория. А на практике оказывается что за счет малой константы многие алгоритмы с O(n2) оказываются быстрее чем алгоритмы гарантирующие O(n log n) даже в худшем случае. В общем кому интересно как работает встроенная в Golang сортировка можно почитать здесь: - https://golang.org/src/sort/sort.go  
          Другой пример - реализация map. Как на самом деле реализован тип map ? Какая хэш функция там используется ? Какой первоначальный размер хэш таблицы ? Как он увеличивается с ростом количества данных в map ? Если вам также интересно как и мне - то ответы на все вопросы можно найти здесь - https://golang.org/src/runtime/hashmap.go 

среда, 15 ноября 2017 г.

Load balancing

         В очередной раз убедился что механизм балансировки основанный на RTT(round trip time) это не самая удачная идея. Когда мы его внедряли мы получили довольно не плохой выигрыш в производительности - порядка 20%. Но потом выяснилось что это была не самая удачная идея. Почему:
          - Сетевые флуктуации случайным образом влияют на распределение нагрузки. То есть распределение запросов между экземплярами приложения определяется (или как минимум сильно зависит от сетевых флуктуаций). Фактически мы приходим к ситуации когда небольшие сетевые проблемы могут привезти к тому что отдельные экземпляры отхватывают порцию траффика не совместимую с жизнью и уходят в себя/убиваются OOM.
      - В контексте перехода на Kubernetes выяснилась еще одна интересная особенность. Экземпляры приложения запущенные в Kubernetes стабильно получали больше запросов чем аналогичные инстансы  запущенные вне Kubernetes. Объясняется это просто. Все Kubernetes сервера приехали в последней партии железа и соответсвенно были смонтированы в несколько рядом стоящих стоек. Соответсвенно RTT внутри Kubernetes облака были в среднем в 2 раза меньше пингов между старыми серверами, что приводило к соответсвующему распределению нагрузки в пользу K8s экземпляров. 
     -  При RTT-based балансировке ты не можешь пропорционально балансировать нагрузку между экземплярами приложения имеющими разное количество аппаратных ресурсов. То есть если один экземпляр запущен на сервере с 24 ядрами а другой на сервере с 40 ядрами - то они все равно будут получать примерно равное количество запросов. Все потому что RTT до сервера с 24 ядрами ничем не отличается от RTT до сервера с 40 ядрами. Вроде бы очевидный факт, но почему-то в тот момент когда мы это реализовывали мне это в голову не пришло. За что собственно и поплатился.
            Собственно вывод который я сделал для себя: балансировка должна основываться именно на ресурсах доступных экземпляру приложения (количеству/качеству CPU, RAM). То есть должен высчитываться некий индекс производительности экземпляра приложения и на его основе уже будет происходить балансировка нагрузки.           
      Еще один извечный вопрос load balancing-а: как собственно балансировать трафик ? Централизовано, через какой-нибудь прокси или через алгоритм "зашитый в клиента". Под алгоритмом зашитым в клиента я подразумеваю некий "smart connector" который сам решает к какому серверу нужно обратится на основе неких доступных ему данных (service discovery + какие-то метрики/данные).
        В первом случае мы получаем проблему в виде SPOF (single point of failure) со всей вытекающей головной болью(как обеспечить ее доступность, мониторинг и тд), нужно дополнительное железо именно под балансировщик/прокси. Именно поэтому я всегда был поклонником второго варианта. Но выяснилось что не все так просто в реальной жизни. У второго варианта также есть  весьма серьезные недостатки: невозможность быстро и единообразно поменять алгоритм балансировки, необходимость поддерживать "smart connector" для всех используемых языков/платформ.  Если у тебя 5 компонентов которые написаны на одном языке - то все более менее терпимо. Но у нас то микросервисы, блять! Это прдразумевает что: 1.  их много, 2. Они поддерживаются разными командами и за всеми хер уследишь, 3. Каждый суслик - агроном и может писать на чем ему вздумается.  В общем менять алгоритм балансировки в таких условиях - это боль и печаль.    

понедельник, 13 ноября 2017 г.

Не заметили как стали большими

     В последнюю распродажу мы поставили небольшой рекорд - 100k RPS на всех 6 странах одновременно, до 30k на страну. Что сказать - 100k RPS это уже не шутки. Мы сами не заметили как стали большими.  

четверг, 2 ноября 2017 г.

Golang runtime

       Не так давно в ходе выкладки в прод memory/cpu лимитов для компонентов наткнулся на интересную особенность поведения Golang runtime. При нехватки CPU ресурсов у приложения написанного на Golang может резко возрастать потребление памяти. Связано это с тем что при увеличении  нагрузки доля CPU выделяемая на сборку мусора уменьшается и в какой-то момент времени мусор начинает генерироваться быстрее чем идет его сборка. 
         В таком режиме go приложение начинает довольно быстро расходовать память и быстро  пристреливается OOM killer-ом. Потом оно перезапускается, но уже с пустыми кэшами. Так как кэши пустые, приложение начинает расходовать еще больше CPU и вероятность того что оно сново уйдет в крутое пике - крайне велика. 
          Первоначальное предположение было - что Go runtime не видит memory limit-ов установленных cgroup. По после чтения исходников я выяснил что go runtime и не пытается увидеть эти лимиты. Действительно, у приложения запущенного без root привилегий не так много возможностей увидеть с какими ограничениями по памяти оно запущено. И даже если у тебя есть root права - эти ограничения будут зависеть от очень многих факторов, и эти факторы будут различаться на каждой поддерживаемой платформе. В общем go runtime просто аллоцирует новые куски памяти до тех пор пока его не прикончит OOM killer или до тех пор пока  операционная система не вернет ему ошибку при очередном вызове mmap(2). В этом случае go runtime падает с паникой.

вторник, 17 октября 2017 г.

Новый MacBook - отстой

     Я давно хотел написать этот пост, дабы предостеречь всех от покупки этого чуда техники. Причины:

  • Эти идиоты за каким-то хером убрали mac safe. Mac safe - это  лучшее изобретение за всю историю усовершенствования ноутбуков. Он не раз спасал жизнь моего ноута. Теперь вместо него я получил дибильный USB-C
  • Ни одного USB порта нет. Хочешь подключить что-то через USB - плати за переходник.
  • Эти переходники с USB-C на USB - огромные, торчат на 20 сантиметров (я говорю про официальный яблочный)
  • Touch bar панель - абсолютно бесполезная штука. Те кто ее придумывал забыли что как правило с клавиатурой работают в слепую. А теперь функциональные клавиши в слепую не так то просто нажать.  
В общем если бы была возможность в старом корпусе но с новой начинкой купить - я бы этим воспользовался. 

четверг, 21 сентября 2017 г.

Мысли в слух

         Сегодняшний день в каком то смысле подвел черту под результатами моих трудов за последние 4 года. И заставил о многом задуматься. Попробую поделиться своими выводами без указания деталей, дабы не нарушить NDA. 
       Первое что я осознал: done better than perfect. Быстро сделать работающее решение(пусть на костылях, пусть из говна и палок) - это гораздо лучше чем потратить в 10 раз больше времени на решение которое экономит один round-trip или пересылает на 10 мегабайт меньше данных. Почему - потому что это экономит тебе время. Обычно когда сравнивают различные решения то учитывают миллисекунды и мегабайты, но не учитывают время потраченное на реализацию этого решения. Оглядываясь назад могу сказать что я в какие-то моменты был идеалистом и пытался все сделать сразу идеально. И закапывал в это кучу времени.  Теперь вот каюсь в этом. 
                Второе - keep it fucking simple. Воистину блять. Вот только это и хочется здесь добавить. Это выражение - как buzz word, его повторяют к месту и не к месту. Но осознание этого приходит только с опытом. Когда мы сравниваем различные решения - мы зачастую забываем об еще одном очень важном критерии - сложности. И выбираем решения которые гораздо более сложные. Просто потому что они красивее. Делай просто - и будет заебись. Все, именно так. К тому же наверняка и быстрее еще получится. Да, об этом решение скорее всего не расскажешь на конференции, да и друзьям в курилке не расскажешь. Зато работает, зато быстро.  Чем больше в системе движущихся частей - тем больше вероятность что одно из них сломается.
              Отдельно хочется сказать про микросервисную архитектуру. Будь проклят тот день когда этот buzz word пришел в Лазаду. Про нее толко на конференциях хорошо рассказывать, но в практическом плане - это просто ад. Все те мечтатели которые  ее нахваливают - как правило просто получают удовольствие от ее реализации,  они кайфуют от возрастающей сложности системы. Им важен процесс а  не  результат. Хотя они думают что приносят пользу - это не так. А если кто-то вам начнет расхваливать -  FaaS(function as a service) - увольте его немедленно.  После 2-х лет эксплуатации микросервисной архитектуры в продакшене  могу твердо сказать - в 99% она вам не нужна. Я уверен что те проблемы который вы с помощью нее собираетесь решить - можно решить гораздо проще. И я еще более уверен что когда вы принимаете решение о переходе на микросервисную архитектуру - вы не осознаете всех тем проблем которые вы сами себе этим создаете.  Особенно проблем вне продакшена - в организации разработки, в организации dev environment, QA и релизного процесса.
               Мой опыт подсказывает мне что организационная структура отдела разработки очень сильно связана с архитектурой разрабатываемого приложения. Многие будут говорить - что за чушь, такого не может быть. Но на самом деле связь между организационной  структурой и структурой приложения очень важна. Если нет четкого соответствия между компонентами архитектуры и командами - начинается бардак. Я не говорю что это должна быть связь 1:1, но эта связь определенно должна быть. Итак если вернуться к вопросу о том нужна ли микроархитектура и насколько она должна быть микро - я бы сказал так:
      - если у вас меньше чем 10-15 программистов в отделе разработки - забудьте про микросервисы. Они вам просто не нужны. Монилит - ваш выбор.
            - если команда выростает до 100 человек, то с монолитом работать будет уже не удобно. Можно попробовать разобрать монолит на несколько приложений, каждое из которых разрабатывается отдельной командой.
     - только если ваша команда выросла до 200-300 человек - можно подумать о микросервисной архитектуре. Но опять же - степень ее микросервисности должен быть пропорционален численности отдела разработки.
          Отсюда вывод - микросервисы отлично работают в компаниях масштаба Netflix, Ebay, Paypal и тд.  Для более мелких компаний это как правило принесет только проблемы. 

Aerospike


        В последнее время мне пришлось довольно близко познакомится с внутренностями Aerospike. Большим открытием для меня стал тот факт что  специализированный SSD storage аероспайка не имеет собственного кэша. Так как этот сторадж работает напрямую с блочным устройством, то они также обходят кэш файловой системы.  Это означает что каждый GET запрос к персистентному namespace означает поход на SSD. Это конечно быстрее чем HDD, но все равно во много раз медленнее чем работа с памятью.  Исходя из этого я могу сделать вывод что Aerospike проектировался в первую очередь под write нагрузку либо под смешанную 50% write/50% read нагрузку. В таких случаях кэш как правило бесполезен, поэтому в AS его и нет.
             Но если вам нужен persistent сторадж с преимущественно read нагрузкой очень хорошо себя показал файловый сторадж аероспайка. В этом случае чтение идет с кэша файловой системы, что весьма позитивно сказывается на общей производительности Aerospike.
              Для тех кто хочет понять как работает Aerospike, я рекомендую к прочтению whitepaper Aerospike: Architecture of a Real-Time Operational DBMS

четверг, 8 июня 2017 г.

Hangzhou

      Так случилось что ровно через год после своего первого визита в Китай я снова оказался в Hangzhou. Если в первую поездку я по большому счету кроме офиса и отеля ничего не видел, в этот раз все было гораздо интереснее. Так как летели через Шанхай, то нам удалось обзавестись симками. Ими торговали какие-то странные чуваки на выходе из зоны прилета, рядом с банкоматами. 250 юаней отдал за 5GB интернет траффика. Не могу сказать что дешево, но и не дорого. Как минимум оно того точно стоило. Так как в Hangzhou абсолютное большинство людей обладает достаточно редким в наше время скилом - АБСОЛЮТНЫМ не знанием английского. Даже такие простейшие звуки как yes, no, ok у них не вызывают никаких ассоциаций.
        В день приезда нам удалось добраться до озера West Lake которое находится практически в центре города.
Как вы сами можете наблюдать место очень красивое, романтичное. Единственная проблема - там людей вокруг него до дури. Но это довольно частая история когда вас миллиард. Еще мы поужинали в ресторанчике с незатейливым названием бабушкина кухня. Ресторан оказался отменным. Мы заказали 3 блюда на двоих. После того  как мы съели первое блюдо на двоих и практически наелись - мы поняли насколько мы ошиблись. Но фатальной ошибкой стал заказ десерта - нам принесли две огромные порции мангового мороженого. Ну прям вот в тарелку из под супа с горкой его наложили. В общем - труба. От туда мы просто выкатились. 
        На следующий день у нас было очень много работы, после которой наши коллеги повели нас в местный ресторан подчивать китайской водкой - Майтай. Обычный самогон по вкусу, но стоит он как потом оказалось каких-то космических денег - 2500юаней за бутылку(370 долларов). Очень позабавила их манера выпивать. Как только мы сели они  начали нас по очереди поздравлять, не по порядку а именно по старшинству. Сразу видно кто из них самый главный, а кто так просто поорать любит.  Поздравляют они без перерыва. Только один тост скажет - выпьем и  сразу следующий берется за рюмку. А мы то лопухи, при каждом тосте выпиваем - нас же поздравляют. В общем накидались мы изрядно. 
       Следующий вечер оказался еще более богатым на события. После ужина мы отправились в местный ночной клуб. Он похоже был довольно "развратным" по местным меркам. Там танцевала go-go танцовщица, местные усиленно на нее пялились. По нашим меркам она не тянула на go-go ну никак: была страшна и практически полностью одета. Сразу после того как мы сели за столик к нам пришла девушка-хостес и предложила сыграть в кости. Такая довольно тупая игра, но помогает быстро набухать гостей. Ибо по условиям игры тот кто проигрывает обязан выпить.  Потом мы поехали в район стадиона и там было просто куча заведений самого разного формата. Начиная от караоке баров для состоятельных мужчин в возрасте. Фишка этих баров в том что ты должен подарить поющей девушке букет (который стоит конских денег) и за это она посидит за твоим столиком до тех пор пока вдохновение снова не озарит ее. После этого она снова уйдет на сцену петь, до тех пор пока не охрипнет или ей снова не подарят букет.  Такой в общем не хитрый бизнес. Букеты многоразовые, потом их тоже возвращают к сцене.
Другие заведения были очень приличного уровня:

В них тусила местная золотая молодеж. Пили Вдову Клико. Ведрами. Буквально. Я думаю тысяч по 5 баксов на столик они там точно оставляли. Ну и валялись потом вокруг пьяные в говно, но очень крутые. 
      В общем год спустя поездка в Китай выдалась гораздо веселее чем в прошлый раз. 

пятница, 28 апреля 2017 г.

KubeCon Europe + Саксонская швейцария

       В конце марта этого года мне удалось вырваться на KubeCon Europe + на выходных посетить регион называемый Саксонская Швейцария(в окрестностях Дрездена). Из минусов - прямо перед началом поездки я подхватил какой-то адский вирус и всю неделю у меня была температура под 40. Это прямо скажем помешало мне насладится этой поездкой.
            KubeCon Europe с одной стороны порадовала обилием интересных докладов, с другой стороны места явно было маловато. Несколько докладов мне пришлось смотреть стоя, несколько я вообще не смог посмотреть потому что даже в помещение войти нельзя было. Но к счастью они все доклады выложили на YouTube:

  Теперь расскажу немного про свой маршрут: мы стартанули из Берлина в пятницу утром и уже через 2 часа были в Саксонской Швейцарии:

Подобные виды являются визитной карточкой этого места. Природа там просто изумительная. Пиво тоже. А вот еда - так себе. Хваленые немецкие сосиски по моему скромному мнению в Москве готовят лучше. Но самое лучшее что там есть - это Эльба:
Согласитесь, Эльба просто великолепна! Что еще бесило - особенно в сельской местности люди не особо умели/хотели говорить по английски.  Но в целом место замечательное.
         Следующий день мы провели в самом Дрездене, осмотрели местный картинные галереи. Не могу назвать себя поклонником изобразительного искусства, но мне было интересно. Вечером мы поехали в Потсдам, ближе к Берлину где и заночевали. Утро мы посвятили осмотру местного дворца. Состояние его прямо скажем плачевное. Не понимаю людей которые сравнивают его с Петергофом. Это все равно что х#й с пальцем сравнивать.

Стачка 2017

          В этом году я впервые выступил на большой русско-говорящей конференции. Случилось это прямо скажу спонтанно. Каким-то образом на меня вышли организаторы конференции и предложили выступить. До этого я уже имел небольшой опыт выступлений: один раз на Golang Meetup  в Москве, второй раз на Rocket конференции в Берлине.  Несмотря на скромный опыт, получилось вроде не плохо. Для тех кому интересно я выложил свои слайды в открытый доступ:

           Если говорить о самой стачке - впечатления смешанные. С одной стороны - я рад что такое мероприятие проходит в моем родном городе. Это очень круто. С другой стороны очевидно что количество докладчиков из московских компаний - стало сильно меньше. Не говоря уже про зарубежные. Видел только пару тренеров которые приехали продавать свои курсы.  И что еще больше угнетает - очевиден сильный перекос в сторону маркетинговых докладов. Медленно но верно конференция перестает быть технической. Под технические секции были отданы самые "скромные" площадки, и например на секции про машинное обучение стабильно не хватало места. Ну и самое провальное место - это кейтеринг. Ребята собрали 5 тысяч человек в одном месте и забыли что всем этим людям нужно поесть и попить. На этом же элементарно столько денег можно заработать. Но внизу я нашел буквально 3 кофе поинта у которых всегда толпились люди. Если учесть что промежутки между докладами не такие уж и большие(в районе 15-20 минут), то кофе попить было просто нереально.