В моей прошлой статье я предположил, что блокчейн должен обрабатывать транзакции со скоростью порядка 10 млн в секунду (оффлайн), чтобы достичь скорости в 1000 транзакций в секунду в реальном времени и при этом надбавить не больше одного часа за год на время повторного воспроизведения. Сегодня я хотел бы представить решение, позволяющее достичь этого уровня производительности конкретно в случае с переводами.
Предположим, что в одном блоке 3000 переводов (интервал между блоками - 3 секунды). Чтобы обработать эти 3000 переводов со скоростью 10 млн в секунду у нас есть 300us (.3 миллисекунды) на каждый перевод. Используя текущую архитектуру ChainBase мы сможем обработать эти переводы за 0.15 секунд (из расчета 5us на перевод). Чтобы достичь нашей цели мы должны ускорить эту операцию в 500 раз.
##Одиночный поток не жизнеспособен
Само действие перевода с одного аккаунта на другой предполагает вычитание из одного баланса и прибавление к другому. В вычислительных терминах это не станет проще, чем уже есть, так что остается очень мало пространства для улучшения однопоточной обработки.
Порядок операций имеет значение
Для примера возьмем начальное состояние, где у Алисы есть 100 SBD, а у Вовы - 0 SBD. Один блок способен поддерживать перевод 100 SBD от Алисы к Вове и перевод 100 SBD от Вовы к Еве, но только если перевод Алисы применяется первым.
При нынешнем положении вещей параллельное проведение двух переводов невозможно, так как перевод Вовы недействителен до тех пор, пока не завершится перевод Алисы. Более того, если бы они производились параллельно, то получилась бы гонка за чтение и запись баланса.
Переосмысляя семантику перевода
Что, если мы определим новые требования для действительного блока так, чтобы каждый аккаунт мог получить не более одного депозита или одного снятия. При таких более жестких требованиях мы сможем производить все 3000 транзакций параллельно. А так как каждый перевод занимает 5us и мы имеем 15us, то можно позволить каждому аккаунту производить до трех депозитов или снятий на блок. С тремя секундами между блоками это означает, что каждый аккаунт имеет максимальную скорость транзакций в 1 TPS (транзакций в секунду), но блокчейн в целом может обрабатывать 200,000 * THREAD COUNT транзакций в секунду. Мы можем построить рабочую установку, поддерживающую 44 ядра, а значит такой блокчейн будет способен обрабатывать 8.8 млн переводов в секунду.
Как достичь 100 млн переводов в секунду
Внеся некоторые небольшие изменения в распределение памяти и порядок операций, мы сможем легко покрыть разницу, необходимую для достижения 10 млн переводов в секунду. Если сюда добавить еще и оптимизацию под запуск блокчейна на GPU, можно масштабировать его до 100 млн переводов в секунду.
Производительность в реальном мире
Если у нас есть процессор, способный производить 10 млн переводов в секунду, мы получим блокчейн, способный поддерживать 1000 транзакций в секунду со скоростью разрастания 100KB/sec или 3 TB в год и скоростью ресинхронизации 1 час в год, требующий скорости чтения блокчейна с диска в 1GB в секунду.
Очевидно, что скачивание 30TB блокчейна с каналом соединения в гигабит займет целые дни после 10 лет работы блокчейна со скоростью 1000 транзакций в секунду. Отслеживание всей истории блокчейна за все время будет очень дорогостоящим мероприятием при скорости 1000 транзакций в секунду.
Устраняя необходимость повторного воспроизведения
По большей части наша проблема масштабируемости состоит в том, что всем нодам требуется воспроизводить все транзакции, чтобы достичь истинного текущего состояния. Это время воспроизведения можно полностью устранить, если блокчейн будет иметь фиксированное и вполне определенное “текущее состояние”. Если бы единственной вещью, которая требуется от блокчейна, был баланс переводов, то каждый владелец смартфона в этом мире мог бы иметь аккаунт при размере всей базы данных меньше 256GB.
Steem специально оставлен с “неопределенной” структурой блокчейна, дабы быть максимально гибким для оптимизации роста, тем более, что мы продолжаем добавлять новые функции. Блокчейну просто валюты не нужна возможность добавления бесчисленного количества функций. Это означает, что мы можем определить оптимальную для его состояния структуру базы данных. Хэш этой структуры данных может время от времени включаться в блокчейн, так что новые пользователи смогут просто скачать это состояние и начать производить новые блоки.
Ключ к росту
Блокчейн, который предполагается масштабировать, должен соответствовать следующим условиям:
- Обрабатывать небольшое число хорошо определенных задач
- Работать на определенном протоколом состоянии
- Почти не изменять функции со временем
- Гарантировать независимость всех транзакций в блоке
- Минимизировать число последовательных шагов в блоке
Наилучший путь к достижению этих характеристик при той же гибкости это внедрение надежного протокола между цепями и сохранение всех новых / измененных функций на отдельных цепях. Можно сделать одну цепь для STEEM, одну для SBD, одну для STEALTH STEEM, и еще одну для STEALTH SBD. Каждая из этих параллельных цепей будет иметь потенциал для обработки тысяч транзакций в секунду и фиксированное, строго определенное состояние. Только одно это даст пропускной способности переводов четырехкратное увеличение в масштабе.
Использование полноценной мощности в реальном времени
Существует заметная пропасть между обработкой 1000 транзакций в секунду в реальном времени и 10 млн транзакций в секунду в повторном воспроизведении. Во время оценки блокчейна в реальном времени процессор простаивает 99,9% времени. Мы можем использовать это время простоя для вычислений, не столь необходимых во время воспроизведения.
Среди таких вычислений и расписание порядка операций в блоке. Протокол может требовать, чтобы все действительные блоки сортировали операции по аккаунту. Можно даже организовать операции по шаблонам доступа к памяти и вычислить оптимальную стратегию выполнения. Эти вычисления занимают дополнительное время на этапе построения блокчейна, но могут быть полностью пропущены во время воспроизведения. Во время воспроизведения блокчейна нам нужно лишь достичь истинного состояния, но не подтверждать, что все шаги авторизованы и правильно сформированы (это гарантируется перелинкованными хэшами блоков).
Это можно представить как компилятор, интерпретирующий программу для создания сборки. Как только сборка готова, процессор может обработать ее очень быстро. Другая аналогия - это процессор, изменяющий порядок операций для максимизации производительности. Производители блоков ответственны за то, чтобы транзакции в блоке имели правильный порядок для оптимальной работы. Любые блоки, произведенные с конфликтом доступа к памяти будут отклонены.
Заключение
Неточно очерченная проблема может потребовать совершенно последовательного решения; однако, если мы добавим к проблеме несколько небольших ограничений, она легко может стать тривиально параллельна. Производители блоков могут проделать немного дополнительной работы для обеспечения того, чтобы все блоки могли повторно воспроизводиться с помощью параллельной оценки операций. Упрощая проблему и определяя формат состояния на выходе в самом протоколе, мы можем также устранить необходимость воспроизведения в целом.
Оригинальный пост и его обсуждение ЗДЕСЬ
Данный пост опубликован в рамках бета тестирования проекта RuSteemitBlog
Перевод осуществлен: @mayamarinero
Критика, комментарии и предложения приветствуются.
Если сказанное в статье будет реализовано даже на половину это уже будет огромный прорыв для наших платформ, вместе с остальными фичами + WREN смарт-контрактами позволит стать действительно массовой универсальной платформой.
Пора дарить словарь :D