Как измерять производительность блокчейн сетей. Основные метрики
Существует много метрик, относящихся к логике и качеству работы блокчейна. Они помогают определить узкие места в коде и найти логические и оптимизационные проблемы в алгоритмах консенсуса и финальности в блокчейнах. Любая разработка распределенных систем, в том числе блокчейнов, требует анализа работы сразу множества узлов. Они позволяют команде проекта следить за состоянием всей блокчейн-сети, видеть проблемы с отдельными нодами, детектировать появление DoS атак на сеть и многое другое. Давайте рассмотрим основные из них. Let’s dive in.
“Transactions-per-second”
В случае распределенных систем, TPS — это очень капризное и неоднозначное число, которое не всегда отражает реальное качество предоставляемого пользователям сервиса. Измерения TPS пришли к нам из распределенных баз данных. TPS в базах данных — это некоторые стандартизованные для теста транзакции или их наборы (сколько то INSERT, сколько-то UPDATE, столько DELETE-ов на фоне постоянных SELECT) для жестко заданной конфигурации кластера или вообще на одной машине. Эти метрики обычно дают только приближенные оценки производительности распределенных БД или блокчейнов, так как время процессинга транзакции может сильно варьироваться в зависимости от множества факторов.
Базы данных, ориентированные на консистентность (см. “CAP-теорема”) не фиксируют транзакцию, пока не получат достаточное число подтверждений от других нод и это медленно. А базы данных, ориентированные на Availability, считают успешной транзакцию, которую просто удалось записать на диск. Они сразу отдают клиенту обновленные данные и это очень быстро (хотя в будущем, эта транзакция может быть откачена назад). Также, если транзакции, используемые в бенчмарке, обновляют лишь одну ячейку с данными, TPS явно будет выше, чем в случаях, когда транзакции могут затрагивать много ячеек и блокировать друг друга. Алгоритмы работы с этими блокировками в каждой БД реализованы по своему — как раз поэтому мы и не видим “соревнований по TPS” между Oracle, MSSQL, PostgreSQL с одной стороны и MongoDB, Redis, Tarantool с другой — уж очень разные внутренние механизмы и разные задачи.
По моему мнению, “измерить TPS” блокчейна означает провести полный комплекс измерений его производительности:
- в повторяемых условиях
- с близким к реальности числом валидаторов, производящих блоки
- используя различные виды транзакций:
- типовые для исследуемого блокчейна (например transfer() основной криптовалюты)
- нагружающие storage подсистему (большой объем изменений от каждой транзакции)
- нагружающие bandwidth (большой объем транзакции)
- нагружающие CPU (в случае массивных криптопреобразований или вычислений)
Чтобы говорить о заветных “transactions per second”, нужно описать все условия (число валидаторов, их гео-распределение, уровень packetloss и т.п.) и описать логику бенчмаркинга. В блокчейнах просто накатить транзакцию на внутреннюю БД не означает ее принятие консенсусом. Например, в случае c Proof-of-Work, статистически, транзакции не завершаются вообще никогда, и, если транзакция включена в блок на одной машине, это не означает, что она будет принята всей сетью (например, в случае победы другого форка).
Если в блокчейне есть дополнительный алгоритм обеспечения финальности транзакций (EOS, Ethereum 2.0, парачейны Polkadot, использующие консенсус с финальностью GRANDPA), то временем процессинга транзакции можно считать промежуток между тем, как нода “увидела” транзакцию и следующим финализированным блоком, куда эта транзакция была включена. Такие, более близкие к реальности “TPS” нечасто встретишь в обещаниях проектов. Они, естественно, ниже описанных в Whitepaper-ах, но зато максимально информативны.
Так что еще раз предупреждаю, в термин “TPS” может быть вложено очень много разных смыслов. Будьте скептичны и требуйте подробностей.
Метрики, специфичные для блокчейн сетей
Local TPS
Число обработанных нодой транзакций и max/avg/min время их обработки на локальной ноде очень удобно измерять, так как функции, выполняющие эту операцию, обычно явно выделены в коде. Можно просто измерить, сколько времени транзакция работала, обновляя state database. Эти транзакции, возможно, пока не приняты консенсусом, но уже прошли валидацию, и нода уже может отдавать клиенту обновленные данные (рассчитывая, что не появится форк цепочки).
Эта метрика не очень честная: если в качестве основной будет выбран другой форк цепочки, то статистику по откаченным транзакциям нужно тоже откатывать. Но для тестирования этим почти всегда можно пренебречь.
Часто, именно это число пишут в кратких отчетах: “у нашего блокчейна вчера получилось 8 000 tps”, так как ее просто измерить — достаточно одной запущенной ноды и скрипта, который ее нагружает. В этом случае отсутствует сетевая задержка, которая замедляет достижение сетью консенсуса, а метрика показывает быстродействие state database без влияния сети. Это число не является реальной пропускной способностью блокчейн-сети, но показывает предел, к которому она будет стремиться, если консенсус и сеть будут достаточно быстрыми.
Результат работы любой блокчейн-транзакции — несколько атомарных обновлений storage. Например, платежная транзакция в Bitcoin — это удаление нескольких старых UTXO (delete) и добавление нескольких новых UTXO (insert), а в Ethereum — это исполнение короткого кода смарт-контракта и, опять же, обновление нескольких пар “ключ-значение”. Количество этих “атомарных” операций записи могут быть отличной метрикой, позволяющей определять узкие места в storage-подсистеме и внутренней логике транзакций.
Также, блокчейн-ноды могут быть реализованы на нескольких языках программирования — так надежнее. Это нужно учитывать, оценивая производительность сети, например, нода Ethereum существует в имплементациях на Rust и Go. Другие блокчейны также стремятся иметь дополнительные имплементации для надежности.
Local produced blocks amount
Эта несложная метрика показывает, какой валидатор сколько блоков произвел. Она является продуктом консенсуса и ее можно считать основной для оценки “полезности” для сети отдельных валидаторов.
Зарабатывая на каждом блоке, валидаторы заинтересованы в стабильной работе и безопасности своих машин. Это число помогает определить, кто из валидаторов-кандидатов наиболее квалифицирован, защищен и подготовлен для работы в публичной сети с активами реальных пользователей. Значение метрики можно публично проверить, просто скачав блокчейн и посчитав кто сколько блоков произвел.
Finality и Last Irreversible Block
В сетях с явно реализованой финальностью (EOS, Ethereum, Tendermint, Polkadot, etc ) помимо основного, быстрого консенсуса (в котором достаточно одной подписи валидатора на блок) часть блоков требует согласования группой валидаторов. Эти блоки считаются финальными, а алгоритм сбора подписей — финальностью. Задача финальности — сделать так, чтобы все транзакции, включенные в блокчейн до финализированного блока уже никогда не были бы откачены и не заменены другим форком цепочки. Это защита от атаки double spend в proof-of-stake сетях, и способ быстро, за несколько секунд, вернуть пользователю надежное подтверждение криптовалютной транзакции.
С точки зрения пользователя блокчейна, транзакция завершается не в тот момент, когда он принята нодой, а когда появился блок, который финализирует цепочку, в которой находится транзакция. Чтобы финализировать блок, валидаторы должны получить этот блок по p2p сети, и обменяться подписями друг с другом. Именно здесь и проверяется реальная скорость блокчейна, ведь пользователю важен именно момент финализации блока с его транзакцией, а не просто принятие и запись ее на диск одной из нод.
Алгоритмы финальности также различаются, пересекаются и объединяются с основным консенсусом (to read: Casper в Ethereum, Last Irreversible Blocks в EOS, GRANDPA в Parity Polkadot и их модификации, например MixBytes RANDPA).
Для сетей, где финализируется не каждый блок, полезной метрикой является отставание последнего финализированного блока от текущего последнего блока. Это число показывает, насколько отстают валидаторы, согласуя правильную цепочку. Если отставание большое, значит алгоритм финализации требует дополнительного анализа и оптимизации.
Другие блокчейн-метрики
Остальные метрики обычно сильно зависят от типа консенсуса, поэтому представлять их в числе основных не очень правильно. В числе таких параметров, например: количество форков цепочки, их длина в блоках, заполняемость блоков транзакциями и т.п. По ним можно определить ситуации разделения сети или быстро локализовать проблемы конкретного валидатора.
P2P слой
Крайне важно помнить о промежуточной основе блокчейн-сетей — peer-to-peer подсистеме. Именно она вносит неопределенные задержки в доставке блоков и транзакций между валидаторами. Когда количество валидаторов небольшое, они локализованы, списки peer-ов жестко прописаны, все работает хорошо и быстро. Но стоит добавить валидаторов, разнести ноды географически и сэмулировать packetloss, как в “tps” появляются существенные провалы.
Например, при тестировании консенсуса EOS с дополнительным алгоритмом finality, увеличение числа валидаторов даже до 80-100 машин, разнесенных по четырем континентам несильно повлияло на скорость достижения finality. В то же время, увеличение packetloss сильно повлияло на отставание финальности, что говорит о необходимости дополнительной настройки p2p слоя для большей устойчивости к потере сетевых пакетов, а не к большому latency. К сожалению, различных настроек и факторов велико, поэтому, только бенчмарки позволяют понять эффективное количество валидаторов, которые обеспечивают достаточно комфортную скорость работы блокчейна.
Устройство p2p подсистемы можно понять из документации, например, по libp2p или документацию по протоколу Kademlia или BitTorrent.
Важными метриками для p2p являются:
- объем inbound-outbound трафика
- количество успешных/неуспешных соединений с другими peer-ами
- сколько раз были отданы ранее закешированные chunk-и данных, и сколько раз пришлось пересылать запрос далее в поисках нужного chunk-а (аналог cache hits/misses)
Например, большое число misses при обращении к данным означает, что запрашиваемыми данными обладают лишь небольшое число нод, и они не успевают раздать их всем желающим, а объем принятого/отданного p2p трафика позволит установить ноду, имеющую проблемы с сетевой конфигурацией или каналом.
Системные метрики блокчейн-нод
Стандартные системные метрики блокчейн-нод описаны в большом числе источников, поэтому опишу их кратко. Их роль — помогать искать узкие места и ошибки во всех частях кода, показывая какие подсистемы ноды наиболее загружены и какими задачами.
CPU
Говорят о том, сколько вычислений выполняет процессор. Если CPU load высокий, значит нода что-то вычисляет, активно использует логику или FPU (в блокчейнах почти не используется). В блокчейнах это может быть, например, из за того, что нода проверяет электронные подпиcи, процессит транзакции с тяжелой криптографией или делает сложные вычисления.
CPU можно “разрезать” ещё на несколько полезных метрик, чтобы понять, какие части кода наиболее затратны. Например, system — код ядра, user — пользовательские процессы, io — ожидание i/o от медленных внешних устройств(диск/сеть) и т.д. Вот хорошая статья по теме.
Memory
Современные блокчейны используют key-value базы-данных (LevelDB, RocksDB), которые постоянно держат в памяти “горячие” данные. Как и в любых нагруженных сервисах, здесь всегда возможны утечки памяти в результате ошибок или целенаправленных атак на код ноды. Если потребление нодой памяти растет, либо резко увеличилось, то, скорее всего, это вызвано увеличением числа ключей в state database, большими очередями транзакций, либо увеличением числа сообщений между разными подсистемами ноды. Недозагрузка памяти может говорить о возможном увеличении лимитов на данные в блоках или максимальную сложность транзакции.
Для full-нод, котоhttps://habrastorage.org/webt/qa/sn/m5/qasnm5bougkjuagneevjkpg9x0w.pngрые отвечают клиентам сети, важными также являются метрики файлового кеша. Клиенты обращаются к различным частям state database и логу транзакций. Это порождает подъем с диска старых блоков, которые могут вытеснять новые блоки, что, в свою очередь замедляет отдачу ответов клиенту.
Network
Основные внутренние метрики network — это объем трафика в байтах, число отправленных и принятых сетевых пакетов по каждому и протоколов, packet loss ratio. В блокчейнах тим метрикам часто не уделяют большого внимания, т.к. блокчейны пока еще не обрабатывают траназакции со скоростью в 1 Gbit/sec.
Существуют блокчейн-проекты, позволяющие пользователям делиться своим wifi или предоставлять услуги хранения и передачи файлов или сообщений. При тестировании таких сетей, количество и качество трафика через сетевой интерфейс становится крайне важными метриками, так переполненный сетевой канал влияет на все остальные сервисы на машине без исключения.
Storage
Дисковая подсистема — это самый медленный компонент в любых сервисах и часто бывает причиной серьезных проблем с производительностью. Избыточное логгирование, неожиданно пришедший backup, неудобный паттерн чтения/записи, большой суммарный объем блокчейна — все это может привести к существенному замедлению работы ноды или к серьезно завышенным требованиям к железу.
Лог транзакций технически можно рассматривать как WAL (WAL ) для state database, поэтому важны те метрики storage, которые позволяют искать узкие места в механизмах современных key-value баз данных. Это количество read/write IOPS, max/min/avg latency и множество других метрик, помогающих оптимизировать дисковые операции.
Заключение
Итак, мы рассмотрели несколько наборов метрик, которые могут давать очень ценную информацию о работе блокчейн сети и возможностях для ее оптимизации. Подытоживая, можно собрать их в три группы:
- блокчейн-метрики нод:
число производимых блоков, число обрабатываемых транзакций, время их процессинга, время финализации, и т.п. - метрики p2p подсистемы:
число hit/miss запросов, число активных peers, объем и структура p2p трафика т.п. - системные метрики нод:
cpu, memory, storage, network и и т.п.
Каждая из групп важна по своему, так как в каждой из подсистем возможно существование ошибок, ограничивающих работу других компонентов, а замедление даже небольшого количества валидаторов может оказывать серьезное влияние на всю сеть. Также, наиболее хитрые ошибки в алгоритмах консенсуса и финальности возникают только при большом потоке транзакций или изменении параметров консенсуса. Для их анализа требуются воспроизводимые условия тестирования и сложные сценарии нагрузки.
Разработка блокчейнов — это всегда оркестрация несколькими машинами, скрипты для раскладки конфигов и согласованного запуска нод и бенчмарков, сервера для сбора метрик и логов со всех машин. Поэтому, при разработке своего блокчейна, предусмотрите найм квалифицированного девопса — он окажет неоценимую поддержку команде разработки. Удачи!