Search
Write a publication
Pull to refresh
36
0

User

Send message

Использование квадродеревьев при расчёте пробок 2ГИС

Reading time6 min
Views23K
Даже не являясь навигатором, 2ГИС собирает и показывает информацию о пробках. Во-первых, это необходимо для построения оптимальных маршрутов, а во-вторых — такие данные очень нужны пользователям в больших городах.

В 2ГИС сервис пробок появился в сентябре 2011 года и сегодня работает в пяти городах (Новосибирск, Санкт-Петербург, Красноярск, Уфа, Казань). В планах на ближайшее будущее — запустить пробки во всех городах-миллионниках.

Под катом история про то, с какими проблемами мы столкнулись и как их решили.

Читать дальше →

Диаграмма Вороного и её применения

Reading time25 min
Views131K
Доброго всем времени суток, уважаемые посетители сайта Хабрахабр. В данной статье я бы хотел рассказать вам о том, что такое диаграмма Вороного (изображена на картинке ниже), о различных алгоритмах её построения (за , — пересечение полуплоскостей, — алгоритм Форчуна) и некоторых тонкостях реализации (на языке C++).



Также будет рассмотрено много интересных применений диаграммы и несколько любопытных фактов о ней. Будет интересно!
Читать дальше →

Опыт построения и эксплуатации большого файлового хранилища

Reading time17 min
Views42K
Даниил Подольский

Даниил Подольский (Git in Sky)


Рассказ о том, что каждый инженер должен сделать в своей жизни после того, как он родил ребенка, посадил дерево и построил дом – это сделать свое файловое хранилище.

Доклад мой называется «Опыт построения и эксплуатации большого файлового хранилища». Большое файловое хранилище мы строим и эксплуатируем последние три года. В тот момент, когда я подавал тезисы, доклад назывался «Ночью через лес. Опыт построения эксплуатации бла-бла-бла». Но программный комитет попросил меня быть серьезнее, тем не менее, на самом деле это доклад «Ночью через лес».

AA-Tree или простое бинарное дерево

Reading time6 min
Views19K
Тема бинарных деревьев уже обсуждалась на хабре (здесь и здесь).

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

Мне, однако, кажется, что AA-дерево заслуживает отдельной статьи.

Читать дальше →

Моноиды и их приложения: моноидальные вычисления в деревьях

Reading time20 min
Views24K
Приветствую, Хабрахабр. Сегодня я хочу, в своём обычном стиле, устроить сообществу небольшой ликбез по структурам данных. Только на этот раз он будет гораздо более всеобъемлющ, а его применения и практичность — простираться далеко в самые разнообразные области программирования. Самые красивые применения, я, конечно же, покажу и опишу непосредственно в статье.

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

Итак, на повестке сегодняшнего дня — моноиды и их основное применение для кеширования вычислений в деревьях.

Моноид как концепция


Представьте себе множество чего угодно, множество, состоящее из объектов, которыми мы собираемся манипулировать. Назовём его M. На этом множестве мы вводим бинарную операцию, то есть функцию, которая паре элементов множества ставит в соответствие новый элемент. Здесь и далее эту абстрактную операцию мы будем обозначать "⊗", и записывать выражения в инфиксной форме: если a и b — элементы множества, то c = ab — тоже какой-то элемент этого множества.

Например, рассмотрим все строки, существующие на свете. И рассмотрим операцию конкатенации строк, традиционно обозначаемую в математике "◦", а в большинстве языков программирования "+": "John""Doe" = "JohnDoe". Здесь множество M — строки, а "◦" выступает в качестве операции "⊗".
Или другой пример — функция fst, известная в функциональных языках при манипуляции с кортежами. Из двух своих аргументов она возвращает в качестве результата первый по порядку. Так, fst(5, 2) = 5; fst("foo", "bar") = "foo". Безразлично, на каком множестве рассматривать эту бинарную операцию, так что в вашей воле выбрать любое.

Далее мы на нашу операцию "⊗" накладываем ограничение ассоциативности. Это значит, что от неё требуется следующее: если с помощью "⊗" комбинируют последовательность объектов, то результат должен оставаться одинаковым вне зависимости от порядка применения "⊗". Более строго, для любых трёх объектов a, b и c должно иметь место:
(ab) ⊗ c = a ⊗ (bc)
Легко увидеть, что конкатенация строк ассоциативна: не важно, какое склеивание в последовательности строк выполнять раньше, а какое позже, в итоге все равно получится общая склейка всех строк в последовательности. То же касается и функции fst, ибо:
fst(fst(a, b), c) = a
fst(a, fst(b, c)) = a
Цепочка применений fst к последовательности в любом порядке всё равно выдаст её головной элемент.

И последнее, что мы потребуем: в множестве M по отношению к операции должен существовать нейтральный элемент, или единица операции. Это такой объект, который можно комбинировать с любым элементом множества, и это не изменит последний. Формально выражаясь, если e — нейтральный элемент, то для любого a из множества имеет место:
ae = ea = a
В примере со строками нейтральным элементом выступает пустая строка "": с какой стороны к какой строке её ни приклеивай, строка не поменяется. А вот fst в этом отношении нам устроит подлянку: нейтральный элемент для неё придумать невозможно. Ведь fst(e, a) = e всегда, и если ae, то свойство нейтральности мы теряем. Можно, конечно, рассмотреть fst на множестве из одного элемента, но кому такая скука нужна? :)

Каждую такую тройку <M, ⊗, e> мы и будем торжественно называть моноидом. Зафиксируем это знание в коде:
public interface IMonoid<T> {
    T Zero { get; }
    T Append(T a, T b);
}

Больше примеров моноидов, а также где мы их, собственно, применять будем, лежит под катом.
Читать дальше →

Малоизвестный MST. Multi-region implementation considerations

Reading time8 min
Views22K
image
Отказ от ответственности.

В данной статье пойдёт речь о логике выбора Root порта на коммутаторах выполняющих роль CIST Regional Root в мультирегионной имплементации протокола MST. В случае использования дельных советов и преступных выводов из этой статьи в производственных сетях предприятий, автор не несёт ответственности за ваши последующие действия, возможные сбои в функционировании вычислительной сети, частичную потерю данных и порчу оборудования.

Читать дальше →

Пальчиковые деревья (Часть 1. Представление)

Reading time6 min
Views19K
Вышла недавно статья на Хабре о том, как можно самому создать на функциональном языке такие структуры как Очередь (первый зашёл, первый вышел) и Дек (напоминает двусторонний стек — первый зашёл, первый вышел с обоих концов). Посмотрел я на этот код и понял, что он жутко неэффективен — сложность порядка O(n). Быстро сообразить, как создать структуры с O(1) у меня не вышло, поэтому я открыл код библиотечной реализации. Но там была не лёгкая и понятная реализация, а <много кода>. Это было описание пальчиковых деревьев, необходимость и элегантность которых для этой структуры данных хорошо раскрывается текущей статьёй.

Пальчиковые деревья


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

Статья будет состоять из 3-х частей:

Пальчиковые деревья (Часть 1. Представление)
Пальчиковые деревья (часть 2. Операции)
Пальчиковые деревья (Часть 3. Применение)

Разрабатывая структуру данных


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



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

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


Читать дальше →

Сжатые префиксные деревья

Reading time8 min
Views61K
Тема префиксных деревьев поиска уже неколько раз поднималась на хабре. Здесь, например, кратко описывается, что такое префиксное дерево и зачем оно нужно, и рассматриваются основные операции над такими деревьями (поиск, вставка, удаление). К сожалению, ничего при этом не говорится про реализацию. В этом недавнем посте рассматривается «питонья библиотека datrie», являющаяся Cython-оберткой библиотеки libdatrie. По последней ссылке имеется хорошее описание реализации частично сжатых префиксных деревьев в виде детерминированных конечных автоматов (с использованием массивов). Я решил внести свои пять копеек в эту тему, рассмотрев реализацию на языке С++ префиксных деревьев с помощью указателей. Кроме того, была и еще одна цель — сравнить между собой поиск строк с помощью сбалансированного двоичного дерева поиска (АВЛ-дерево) и сжатого префиксного дерева.

Читать дальше →

Cassandra глазами Operations

Reading time9 min
Views12K
Основной проект компании, в которой я работаю, посвящен оптимизации показов рекламы в приложениях на фейсбуке и на мобильных устройствах. На сегодняшний день проект обслуживает до 400 миллионов уникальных посетителей в месяц, работает на тысяче с лишним виртуальных серверов. Количество серверов и обьемы данных, которые должны обрабатываться двадцать четыре часа в сутки, ставит перед разработчиками ряд интересных проблем, связанных с масштабируемостью и устойчивостью системы.

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

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


  • события могут происходить на разных серверах и в разных датацентрах (восточный и западный берег США, Европа)
  • интервал между событиями — от долей секунды до нескольких дней
  • к моменту получения завершающего события (например конверсия) информация обо всей цепочке должна быть на руках
  • время жизни информации — примерно десять дней, после чего она должна быть удалена, желательно автоматически, через TTL
  • темп чтения/записи событий — сотни или тысячи в секунду
  • Время ответа: желательное — до 10мс, допустимое — в пределах 50мс, максимальное — до 100мс
  • информация должна быть доступна «всегда» — независимо от аварий железа, сети, апгрейдов
  • система должна легко масштабироваться: добавление новых серверов, датацентров должно происходить прозрачно для остальных сервисов (допустима деградация времени ответа в заданных пределах).

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

Лекции Техносферы. Подготовительный курс «Алгоритмы и структуры данных» (весна 2016)

Reading time3 min
Views39K


Цель этого курса — познакомить слушателей с основными алгоритмами, применяемыми для разработки программного обеспечения. Вы научитесь выбирать подходящие структуры данных и алгоритмы для реализации возникающих задач, и узнаете, как использовать языки С/С++ для реализации алгоритмов.

Курс ведет Сергей Бабичев, доцент кафедр информатики и вычислительной математики, а также теоретической и прикладной информатики в МФТИ. Под катом вас ждет восемь лекций:

  • Лекция 1. «Введение. Исполнители. Абстракции интерфейсов. Рекурсия»
  • Лекция 2. «Жадные алгоритмы»
  • Лекция 3. «Сортировки»
  • Лекция 4. «Поиск. Списки»
  • Лекция 5. «Деревья»
  • Лекция 6. «Хеш-таблицы»
  • Лекция 7. «Динамическое программирование»
  • Лекция 8. «Алгоритмы на графах»

Игровая индустрия: полезные материалы для геймдевелопера от A до Z

Reading time10 min
Views162K
В последнее время мы часто сталкиваемся с вопросами о том, как попасть в игровую индустрию, какие полезные материалы на эту тему можно почитать и посмотреть, с чего начать изучение геймдева. Когда начальные знания появляются, то возникают уже более конкретные вопросы, например «где найти единомышленников для создания игры», «как продвигать свой проект с минимальным бюджетом», «на каких издателей стоит выходить, как это делать и стоит ли вообще», «как улучшить ретеншн в нашей игре» и так далее.

Друг наших образовательных программ Михаил Пименов,  CEO компании Wonder Games и Team Lead инди-проекта "Guard of Wonderland" сам не раз задававший себе эти вопросы, создал для себя выборку всевозможных материалов по индустрии геймдева. От полезных ресурсов, до сообществ, подкастов, книг и фильмов, которые призваны помочь понять, с чего начинается и чем заканчивается разработка игрового проекта. Объединив наши силы, мы с Мишей сделали эту статью с подборкой полезных материалов по игровой индустрии. Вы найдете подборку под катом.


Читать дальше →

Квантовое хеширование. Лекция в Яндексе

Reading time20 min
Views20K
Фарид Мансурович Аблаев — заведующий кафедрой теоретической кибернетики Казанского федерального университета. Приехав в московский офис Яндекса, Фарид Мансурович рассказал об алгоритмах, потенциально пригодных для запуска на квантовых компьютерах. Таких устройств пока очень мало, и они толком не освоены даже самыми передовыми компаниями. Но когда они начнут дешеветь, у специалистов уже будут наработки, позволяющие приступить к их использованию.


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

Как мы сделали ровную балансировку нагрузки на фронтенд-кластере

Reading time10 min
Views20K

Юрий Насретдинов (youROCK, Badoo)


Юрий Насретдинов

Расшифровка доклада Юрия Насретдинова на конференции HighLoad++ 2015. Юрий расскажет про то, как Badoo (крупнейшая социальная сеть для знакомств с новыми людьми) сделали практически идеально ровную балансировку нагрузки на нашем кластере. Передаём ему слово...

Чтобы обслуживать то количество пользователей, то количество реквестов в секунду, которые мы получаем, у нас около трех тысяч серверов, и на PHP-FPM конкретно приходится 70 тысяч в пике.

О том, как мы эти запросы распределяем по нашему кластеру, я расскажу.



Кратко — о чем я буду рассказывать. Во-первых, я расскажу, как «с высоты птичьего полета» устроен роутинг запросов на нашем сайте. Потом расскажу, какие, вообще, существуют алгоритмы балансировки; про то, как мы делали балансировку до того, как мы сделали автоматическую систему. Расскажу про эту автоматическую систему, ну и будут кое-какие выводы. Также хотел сказать, что эта система будет выложена в open-source после этого доклада.

Разбор задач финального раунда RCC 2016

Reading time12 min
Views7.7K


18-го сентября был проведен последний, финальный этап чемпионата по спортивному программированию Russian Code Cup 2016 года. Первое место в упорной борьбе занял Геннадий Короткевич, второе и третье места — Владислав Епифанов и Николай Калинин соответственно.

Турнирную таблицу финала можно найти здесь, призовой фонд в этом году впервые распределен на первые 25 мест рейтинга. Это не единственное нововведение — впервые в RCC имели возможность поучаствовать англоговорящие программисты, коих набралось более тысячи из 4.5 тысяч участников. Помимо традиционных для соревнования стран СНГ, в финальном раунде боролись представители Германии, Финляндии, Японии, Швейцарии, Китая и Южной Кореи. Кроме того, в этот раз был проведен зеркальный раунд на Codeforces — сразу после финала основного состязания, у всех желающих была возможность решить задачи финала в специально организованном соревновании для первого дивизиона, поучаствовало чуть больше 200 программистов.

Традиционно предлагаем вам разбор задач финала (тесты можно скачать здесь):

A. Церемония закрытия
B. Кактусофобия
C. Домашнее задание
D. Слалом
E. Шифр
F. Покрытие массива
Читать дальше →

Обзор курсов по Deep Learning

Reading time11 min
Views71K
Привет, Хабр! Последнее время все больше и больше достижений в области искусственного интеллекта связано с инструментами глубокого обучения или deep learning. Мы решили разобраться, где же можно научиться необходимым навыкам, чтобы стать специалистом в этой области.

image
Читать дальше →

Как устроена apache cassandra

Reading time13 min
Views243K
Кассандра
В этом топике я хотел бы рассказать о том, как устроена кассандра (cassandra) — децентрализованная, отказоустойчивая и надёжная база данных “ключ-значение”. Хранилище само позаботится о проблемах наличия единой точки отказа (single point of failure), отказа серверов и о распределении данных между узлами кластера (cluster node). При чем, как в случае размещения серверов в одном центре обработки данных (data center), так и в конфигурации со многими центрами обработки данных, разделенных расстояниями и, соответственно, сетевыми задержками. Под надёжностью понимается итоговая согласованность (eventual consistency) данных с возможностью установки уровня согласования данных (tune consistency) каждого запроса.

NoSQL базы данных требуют в целом большего понимания их внутреннего устройства чем SQL. Эта статья будет описывать базовое строение, а в следующих статьях можно будет рассмотреть: CQL и интерфейс программирования; техники проектирования и оптимизации; особенности кластеров размещённых в многих центрах обработки данных.
Дорогу осилит идущий...

Использование потенциальных полей в сценарии стратегии реального времени

Reading time8 min
Views42K
Реализация поведения юнитов в RTS играх может стать серьезной проблемой. Компьютер, зачастую, контролирует огромное количество юнитов, в том числе и принадлежащих игроку, которые должны передвигаться в большом динамическом мире, попутно избегая столкновения друг с другом, выискивая врагов, защищая собственные базы и координируя атаки для истребления противника. Стратегии реального времени работают в реальном времени, что делает довольно сложным слежение за планированием действий и навигацией.

Этот урок описывает метод планирования течения игры и навигации юнитов, который использует многоагентные потенциальные поля. Он основан на работах под номерами [1, 2, 3]. (Смотри в конце статьи ссылки на используемые материалы)



Читать дальше →

Рандомизированные деревья поиска

Reading time8 min
Views58K

Не знаю, как вы, уважаемый читатель, а я всегда поражался контрасту между изяществом базовой идеи, заложенной в концепцию двоичных деревьев поиска, и сложностью реализации сбалансированных двоичных деревьев поиска (красно-черные деревья, АВЛ-деревья, декартовы деревья). Недавно, перелистывая в очередной раз Седжвика [1], нашел описание рандомизированных деревьев поиска (нашлась и оригинальная работа [2]) — настолько простое, что занимает оно всего треть страницы (вставка узлов, еще страница — удаление узлов). Кроме того, при ближайшем рассмотрении обнаружился дополнительный бонус в виде очень красивой реализации операции удаления узлов из дерева поиска. Далее вы найдете описание (с цветными картинками) рандомизированных деревьев поиска, реализация на С++, а также результаты небольшого авторского исследования сбалансированности описываемых деревьев.
Читать дальше →

2-3-дерево. Наивная реализация

Reading time15 min
Views65K
Недавно мне понадобилось написать 2-3-дерево и я начал искать информацию в русскоязычном интернете. К сожалению, ни на хабре, ни на других ресурсах я не смог найти достаточно полную информацию на русском языке. На всех ресурсах было одно и то же: свойства дерева, как вставляются ключи в дерево, поиск в дереве и иногда простой пример, как удаляется ключ из дерева; не было реализации.

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

Топ 6 оптимизаций для netty

Reading time5 min
Views27K
Всем привет. Эта статья продолжение 10к на ядро с конкретными примерами оптимизаций, которые были проделаны для повышения производительности сервера. С написания первой части прошло уже 5 мес и за это время нагрузка на наш продакшн сервер выросла с 500 рек-сек до 2000 с пиками до 5000 рек-сек. Благодаря netty, мы даже не заметили это повышение (разве что место на диске уходит быстрее).

Blynk load
(Не обращайте внимание на пики, это баги при деплое)

Эта статья будет полезна всем тем кто работает с netty или только начинает. Итак, поехали.

Нативный Epoll транспорт для Linux


Одна из ключевых оптимизаций, которую стоит использовать всем — это подключение нативного Epoll транспорта вместо реализации на java. Тем более, что с netty это означает добавить лишь 1 зависимость:

<dependency>
   <groupId>io.netty</groupId>
   <artifactId>netty-transport-native-epoll</artifactId>
   <version>${netty.version}</version>
   <classifier>linux-x86_64</classifier>
</dependency>

и автозаменой по коду осуществить замену следующих классов:

  • NioEventLoopGroup → EpollEventLoopGroup
  • NioEventLoop → EpollEventLoop
  • NioServerSocketChannel → EpollServerSocketChannel
  • NioSocketChannel → EpollSocketChannel

Дело в том, что java реализация для работы с не блокирующими сокетами реализуется через класс Selector, который позволяет вам эффективно работать с множеством соединений, но его реализация на java не самая оптимальная. Сразу по трем причинам:

  • Метод selectedKeys() на каждый вызов создает новый HashSet
  • Итерация по этому множеству создает iterator
  • И ко всему прочему внутри метода selectedKeys() огромное количество блоков синхронизации

В моем конкретном случае я получил прирост производительности около 30%. Конечно же, эта оптимизация возможна только для Linux серверов.
Читать дальше →

Information

Rating
Does not participate
Location
Россия
Date of birth
Registered
Activity