Производительность и масштабируемость
Голос способен поддерживать работу в системе большего количества пользователей, чем Реддит.
В 2015 году 8,7 миллионов пользователей Реддит создавали в среднем 23 комментария в секунду, что соответствовало 83 комментариям в год на одного пользователя. Количество постов верхнего уровня равнялось 73 миллионам, то есть в среднем появлялось 2 новых поста в секунду. Количество отданных за посты голосов составляло около 7 млрд, что соответствовало 220 голосам в секунду. Учитывая все сказанное, работа Реддита на блокчейн потребовала бы в среднем 250 транзакций в секунду. Голос способен обрабатывать 1000 транзакций в секунду.
Общая информация
- Голос построен на той же технологии, что и блокчейн BitShares (который способен обрабатывать 1000 транзакций в секунду).
- Нижеприведенный текст является адаптацией документации BitShares.
Для достижения указанной производительности разработчики системы опирались на систему LMAX Exchange, которая способна обрабатывать 6 миллионов транзакций в секунду. Ключевыми являются следующие пункты:
- Сохранять все в памяти.
- Держать основную бизнес-логику в одном потоке (треде).
- Держать криптографические операции (хэши и подписи) вне ключевой бизнес-логики.
- Разделять проверку на зависимую от статуса и независимую от статуса.
- Использовать объектно- ориентированную модель данных.
Следуя этим простым правилам, Голос способен обрабатывать 10000 транзакций в секунду без каких-либо значительных усилий на оптимизацию.
Теория
Блокчейн представляет собой глобальный реестр транзакций, при внесении в который в определенный момент времени каждая транзакция определенным образом изменяет состояние реестра. Порядок обработки транзакций может изменить статус других транзакций. Например, невозможно снять деньги с банковского счета до тех пор, пока поступления не этот счет не прошли клиринг. Невозможно подтвердить валидность транзакции до тех пор, пока все предшествующие ей транзакции, в которые вовлечена учётная запись, не обработаны.
Теоретически, транзакции с двух несвязанных учетных записей могут быть обработаны одновременно при условии, что они не связаны друг с другом. На практике задача на установление независимости транзакций в реестре, управляемом через умные контракты с произвольными условиями, является неразрешимой. Единственный способ удостовериться в том, что две транзакции действительно независимы - учет их в отдельных реестрах и периодический обмен данными между ними. Аналогией может быть компромисс по производительности между архитектурой неравномерного доступа к памяти (NUMA) и архитектурой равномерного доступа к памяти (UMA).
- На практике UMA намного проще и дешевле разработать.
NUMA, как правило, используется как вынужденное решение при создании суперкомпьютеров или гигантских кластеров.
В среде компьютерщиков является установленным фактом, что масштабирование производительности через параллельное выполнение операций далеко не так легко реализовать, как это было на заре компьютерной эры, когда требовалось только увеличить тактовую частоту процессора. Именно по этой причине конструкторы ЦПУ стараются максимизировать производительность в одном потоке до предела до перехода на параллельные потоки. Кластерный подход к организации вычислений используется только в том случае, когда недостаточно параллельных потоков.
Многие в криптоэкономике пытались решить проблему масштабируемости путем немедленного перехода к кластерному решению без детального изучения того, что технологически возможно создать на одном ядре одного компьютера.
LMAX
LMAX представляет собой кейс для изучения архитектуры с высокой масштабируемостью и производительностью, показывая, что может быть достигнуто в рамках одного потока. LMAX является розничной торговой площадкой, которая стремится стать самой быстрой биржей в мире. Они оказались удивительно щедрыми и публично поделились своими наработками.
Вот краткий обзор архитектуры LMAX:
Процессор бизнес-логики - место, где обрабатываются все последовательные транзакции и происходит подбор пар на покупку и продажу. Это единственный поток, в котором обрабатываются миллионы ордеров в секунду. Эта архитектура легко переносима на блокчейн-системы.
Роль системы ввода в LMAX - сбор ордеров от пользователей из разных источников и присвоение заданных порядковых номеров. После назначения порядковых номеров ордера дублируются, заносятся, транслируются на многие процессоры бизнес-логики. Задачи ввода являются параллельными и легко отдаются на откуп кластеру компьютеров.
После того как процессор бизнес-логики обрабатывает входящий поток, система вывода уведомляет всех, кому важно знать результат. Это также является параллельной задачей.
В конечном счете LMAX смог обрабатывать 6 миллионов транзакций в секунду в процессоре бизнес-логики с использованием одного ядра обычного ЦПУ с помощью виртуальной машины Ява (Java). Если LMAX смог достичь 6 миллионов транзакций в секунду, то нет необходимости использовать в блокчейн-системах кластерные решения в случаях, когда они не обрабатывают и 10 транзакций в секунду.
Высокопроизводительные блокчейны
Для достижения высокой производительности в Голосе используются наработки LMAX. При этом несколько важных моментов должны быть соблюдены:
- Сохранение всей информации в памяти.
- Минимизация операций по синхронизации примитивов (?)
- Сведение к минимуму ненужных вычислений в процессоре бизнес-логики.
Память становится дешевле с каждым днем в результате того, что является параллельной. Объем памяти необходимый для отслеживания баланса учетной записи и разрешений каждого человека в Интернете составляет меньше, чем 1 терабайт оперативной памяти, которую можно приобрести менее чем за $ 15000 и установить на обычные (высококлассные) материнские платы серверов. Задолго до того, как 3 млрд человек начнут использовать Голос, такой объем оперативной памяти будет установлен на каждом среднестатистическом компьютере.
Узким местом для блокчейн-систем является не оперативная память, а пропускная способность. При 1 млн транзакций в секунду и 256 байтах на одну транзакцию требуется пропускная способность сети в 256 мегабайт в секунду (1 Гбит / сек). Такая пропускная способность не является широко распространенной. Однако, этот уровень составляет долю от 100 Гбит / сек, по которым подключены к Интернет более чем 210 учебных заведений США, 70 американских корпораций и 45 американских некоммерческих и государственных учреждений.
Соответственно, при правильном проектировании блокчейн-система может легко держать всю информацию в оперативной памяти и масштабироваться таким образом, чтобы обрабатывать миллионы транзакций в секунду.
Использование идентификаторов вместо хэш-функций
В однопотоковых системах циклы процессора являются дефицитным ресурсом, который нужно экономно расходовать. Традиционно блокчейн-системы используют криптографические хэши для создания глобально уникальных идентификаторов, которые гарантированно никогда не будут пересекаться. Проблема использования хэшей в том, что они требуют значительно больше памяти и больше циклов ЦПУ для обработки. Для поиска учетной записи по хэшу требуется значительно больше процессорного времени, чем в случае использования прямого индекса массива данных. 64-битные целые числа проще сравнивать и использовать, чем 160-битные идентификаторы. Использование хэш-идентификаторов ведет к уменьшению места в кэше процессора и требует больше оперативной памяти при обработке. В современных операционных системах редко используемая оперативная память оптимизируется за счет сжатия, но хэш-идентификаторы являются случайными данными, которые не могут быть сжаты.
К счастью, блокчейны позволяют присваивать уникальные глобальные идентификаторы, которые не пересекаются друг с другом. Соответственно, можно полностью избавиться от хэш-идентификаторов (биткоин-адресов) для обозначения учетной записи, баланса, или разрешения.
Проведение операции проверки подписи вне процессора бизнес-логики
Все транзакции в блокчейн сети зависят от криптографических подписей, по которым проверяются права доступа. В общем случае права доступа могут быть изменены в результате других транзакций. Это означает, что права доступа должны быть определены таким образом, чтобы не требовалось криптографических вычислений внутри процессора бизнес-логики.
Для этого каждому публичному ключу должен быть присвоен уникальный и неизменяемый идентификатор. После того, как идентификатор назначен, система ввода проверяет, что подпись совпадает с присвоенным идентификатором. Соответственно, к моменту, когда транзакция попадает в процессор бизнес-логики, единственный оставшийся шаг – проверка идентификатора.
Этот же метод может быть использован для сокращения проверки предварительного условия для любого неизменного объекта со статическим идентификатором.
Создание транзакций со статической проверкой
Многие свойства транзакций могут быть проверены статически без доступа к текущему состоянию блокчейн-системы. Эти проверки включают в себя проверку диапазона параметров, де-дублирование входных значений, порядок сортировки массивов и т.д. Вообще говоря, многие проверки могут быть выполнены, если транзакция содержит данные о «предполагаемом» глобальном состоянии системы. После того как проверки выполнены, от процессора бизнес-логики требуется только убедиться, что "предположения" о состоянии системы по-прежнему верны, что может быть сведено к проверке отметки о времени создания объектов, на которые ссылается транзакция, со временем подписания транзакции.(???)
Умные контракты
Во многих блокчейн-системах для описания всех операций используется скриптовый язык общего назначения. В конечном итоге это ведет к тому, что процессор бизнес-логики представляет собой виртуальную машину, а все операции являются скриптами этой виртуальной машины. Этот подход натыкается на ограничения однопоточного исполнения кода на реальном ЦПУ, и усугубляет их путем проведения всех операций через виртуальный процессор. Виртуальный процессор, даже в случае с JIT-компиляцией всегда медленнее, чем реальный ЦПУ, но скорость расчетов – это не единственная проблема при подходе, когда все является скриптом.
При определении транзакций на таком низком уровне большая часть статических проверок и криптографических операций обрабатывают процессором бизнес-логики, и соответственно общая пропускная способность системы падает. Криптографическую проверку подписи нужно не на скриптовом движке проводить, нечего его нагружать
Исходя из данных по LMAX, мы знаем, что виртуальная машина для блокчейн должна быть разработана как однопоточная система. Это означает, что она изначально должна быть оптимизирована для JIT компиляции, и что наиболее часто используемые умные контракты должны изначально поддерживаться блокчейном. Только редко используемые пользовательские контракты должны обрабатываться через запуск на виртуальной машине. Эти пользовательские контракты должны быть оптимизированы под максимизацию производительности, что означает ограничение на использование адресуемой памяти при возможности обработки в кэше процессора.
Объектно-ориентированная модель данных
Одним из преимуществ сохранения всей информации в оперативной памяти является то, что программное обеспечение может имитировать реальные взаимоотношения между данными. Это означает, что процессор бизнес-логики может легко использовать указатели на данные, размещенные в памяти, а не посылать запросы к базе данных. Это также означает, что данные могут быть доступны без копирования и оперативно изменены. Эта оптимизация предполагает увеличение на порядок производительности системы по сравнению с подходом, при котором идет работа с базой данных.
Размер транзакций
Блокчейн, который обрабатывает 100000 транзакций каждую секунду, создаёт большое количество данных. Средний размер транзакции на Риппл и Биткоин составляет около 250 байт. Подобная транзакция в Голосе занимает в среднем 100 байт. Другими словами, конкурирующие системы требуют в 2,5 раза больше полосы пропускания для прохождения одинакового количество транзакций. При пропускной способности 1 гигабит/секунду, передача блока с 100000 транзакций займет около 0,1 секунды. В указанных выше системах на это потребуется 0,25 секунды. Принимая во внимание другие задержки, свойственные пиринговым сетям - становится ясно, что размер транзакции прямо влияет на интервал блока и задержку подтверждения.
Размер транзакций часто является показателем количества данных, которые процессор должен обработать. Таким образом, он служит указанием на то, как скоро однопотоковый ЦПУ будет полностью загружен.
Некоторые оптимизации возможны во всех протоколах, если они предполагают, что все узлы получают информацию обо всех транзакциях, и требуется только передать упорядоченный список идентификаторов транзакций.
Вывод
Проектирование высокопроизводительного блокчейна не является чем-то сверхъестественным и не требует ни детального знания протоколов, ни распараллеливания процесса обработки транзакций. Вместо этого, для высокопроизводительного блокчейна требуется перенести все расчеты, которые не являются критическими, из ядра бизнес-логики, и разработать протокол, который облегчает такую оптимизацию. Это то, что реализовано в Голосе.