Автор Protobuf не рекомендует использовать Protobuf в Deno

внешний интерфейс Безопасность protobuf V8
Автор Protobuf не рекомендует использовать Protobuf в Deno

0. Фон

я был«Как оценить новый проект RY (Райан Даль) Deno?»Написал в:

Что меня больше всего интересует, так это то, что deno использует Protobuf, а не Mojo. Поскольку цель состоит в том, чтобы быть совместимым с браузером, а не использовать Mojo...

...

Если вы хотите быть совместимым с экосистемой браузера, выбор Mojo — это кратчайший путь, а если целью является высокопроизводительный сервер, вам следует выбрать несериализованную библиотеку с нулевым копированием. protobuf не подходит для deno с любой точки зрения.

Однако, из выпуска, видно, что Райан Даль никогда не слышал о Mojo, но после того, как он прочитал Моджо, он все же чувствует, что Protobuf является правильным выбором.

Райан Даль сначала выбрал голанг, а затем полностью удалил голанг из дено. Несколько дней назад автор Protobuf Кентон Варда (kentonv) открыл вопрос:Protobuf seems like a lot of overhead for this use case? #269В тексте Кентонв указал:

I was surprised by the choice of Protobuf for intra-process communications within Deno. Protobuf's backwards compatibility guarantees and compact wire representation offer no benefit here, while the serialize/parse round-trip on every I/O seems like it would be pretty expensive.

Вероятно: Kentonv очень удивлен Deno Select Protobuf, потому что преимущество совместимости Protobuf не нужно, напротив, сериализация Protobuf и обратные последовательности потребляют производительность ввода-вывода.

1. Производительность Cap'n Proto

Кентонв разработал Cap'n Proto после выхода из Google.

Cap'n Proto сравнил Protobuf, в конце концов, насколько он быстр? 10 раз? 100 раз? 1000 раз? Официальный сайт дает сравнительную таблицу:

Cap'n Proto кодирует и декодирует в ∞ раз быстрее, чем Protobuf. 2333

По сути, эта картинка является заглавной.Картинка сравнивает кодирование и декодирование двух, но в Cap'n Proto кодирование и декодирование (кодирование/декодирование) вообще не требуются. Формат данных, закодированный Cap'n Proto, хранится непосредственно в памяти, а структура данных соответствует расположению в памяти, поэтому закодированная структура может быть непосредственно сохранена на жестком диске в соответствии с байтами или передана через сеть.

Означает ли это, что кодировка Cap'n Proto зависит от платформы?

Не делайте! Схема кодирования байтов, используемая Cap'n Proto, не зависит от какой-либо платформы, но будет иметь лучшую производительность на современных процессорах общего назначения. Организация данных аналогична тому, как компилятор организует структуры: фиксированная ширина, фиксированное смещение и выравнивание памяти.Для переменных элементов массива используются указатели, и указатели также хранятся по смещениям вместо абсолютных адресов. Целые числа используют обратный порядок байтов, потому что большинство современных процессоров имеют обратный порядок байтов, и даже процессоры с обратным порядком байтов обычно имеют инструкции для чтения данных с прямым порядком байтов.

Примечание. Прямой и прямой порядок байтов вместе называются порядком байтов. Для многобайтовых данных, таких как 32-битные целые, 4 байта, в разных процессорах, по-разному, в памяти0x0A0B0C0DНапример, способ хранения:

В большом Endian, если данные в 8-битных единицах хранения, самый значительный байт0x0AХранится по наименьшему адресу памяти.

地址增长方向  →
0x0A, 0x0B, 0x0C, 0x0D

Если данные хранятся в 16-битных единицах, самая высокая 16-битная единица0x0A0BХранится в низком:

地址增长方向  →
0x0A0B, 0x0C0D

Little endian наоборот. Большинство основных процессоров имеют обратный порядок байтов, поэтому Cap'n Proto использует обратный порядок байтов.

Если вы знакомы с структурами C или C ++, вы можете увидеть, что PAP'N Proto кодируется очень похожим на структуру памяти структуры структуры. Даже внутри двигателя V8 аналогичная структура используется для быстрой считывания свойств. По сравнению с использованием карт HASH, существует высокое улучшение производительности.

2. Сериализация/десериализация

Protobuf каждый раз создает объект, представляющий сообщение, а затем сериализует объект в ArrayBuffer.Получателю сообщения необходимо прочитать сообщение из буфера, а затем разобрать его в соответствующий объект, который будет использоваться в последующем программировании. . В Cap'n Proto структура сообщения сохраняется непосредственно в ArrayBuffer, когда мы вызываемmessage.setFoo(123), на самом деле похож наuint32Array[offset] = 123, на стороне получателя сообщения мы можем прочитать сообщение прямо из буфера.

Может использоваться расширенное кодирование Protobuf, которое может иметь меньшую длину кода для некоторых сцен. Из соображений производительности, а Cap'n Proto будет кодировать целое число постоянной ширины, дополнительный байт заполняется 0 (это похоже на хранение в memcached). Это пространство для времени, это время для пространства. При отправке сообщений по сети мы надеемся, что тело сообщения будет как можно меньше, но если общение происходит в одном и том же адресном пространстве, мы имеем неограниченную пропускную способность. В документе Cap'n Proto также указано, что когда пропускная способность действительно важна, независимо от используемого формата кодирования, следует использовать универсальное сжатие тела сообщения, например zlib или LZ4.

3. FlatBuffers

Автор deno, ry, также участвовал в обсуждении в номере, и был очень тронут всеобщим восторженным вниманием к ry, а потом. . . . Затем создал ветку flatbuffers: P

FlatBuffers также является библиотекой, созданной в Google, с улучшенной документацией иBenchmarks. А у Cap'n Proto нет никаких тестовых данных, кроме несправедливого теста «неограниченная скорость».

И отношение kentonv к бенчмаркингу такое:

Что касается бенчмаркинга — я потратил много времени на бенчмаркинг систем сериализации и, к сожалению, пришел к выводу, что результаты бенчмаркинга почти всегда бессмысленны.

...

Действительно значимый эталон требует написания двух версий реального применения с двумя разными сериализациями и сравнивая их ... Но это много работы, которые вряд ли кто-либо делал.

Это действительно большой проект. Напротив, V8 и Chrome делают каждый выпускReal-world JavaScript performance

4. Безопасность

При текущем использовании protobuf deno копия создается для каждого сообщения. deno использует protobuf только для связи между V8 и другим привилегированным кодом, даже если вам действительно нужна копия сообщения, вы можете использовать ее напрямуюmemcpy()для достижения более высокой производительности.

Если в одном и том же буфере (ArrayBuffer), когда разные потоки работают одновременно, вам нужна копия, чтобы предотвратить уязвимость TOCTOU, или осторожно обрабатывать код JavaScript, но это не поддается контролю, потому что вы не можете запретить сторонним модулям также делают те же предположения (если сторонние расширения также используют тот же механизм связи).

Весь процесс TOCTOU — это «от времени проверки до времени использования», а TOCTOU — это своего рода дефект состояния гонки. Эта уязвимость часто встречается в многопоточных многоядерных системах. Когда мы обращаемся к общему ресурсу, система сначала определяет, есть ли разрешение у текущего пользователя или кода, и проверка и использование разделены, а не атомарны. После того, как система проверит, предоставлено ли ресурсу разрешение пользователя, злоумышленник может временно заблокировать пользовательский поток, а затем заменить ресурс в течение разницы во времени, чтобы получить несанкционированный доступ.

Вот простой пример:

if (hasPermission("file")) {
    // (1)
    buffer = open("file");
    // (2) dosth
    write("file", buffer);
    // (3)
}

Злоумышленник может(1)Создайте следующий код:

// ...
// hasPermission 检查通过
symlink("/etc/passwd", "file");
// 文件打开之前
// ...

Таким образом, у пользователя есть больше прав"/etc/passwd"Контроль.

/tmpа также/var/tmp

Для того, чтобы обеспечить временную потерю производительности является последним средством компромисса, до того, как V8 также столкнулся, для анализа уязвимости побега привел непосредственно к проблемам безопасности, в дополнение к анализу побега команда выпуска Chrome была следующей.

5. Подводя итоги

Дено похож на новорожденного ребенка, и Райан Даль тоже постоянно исследует, и неизбежно, что он пойдет в обход. Как рядовые разработчики, можем обратить внимание на исходники deno и коммит на github.

Для очень зрелого проекта, такого как Node.js, нам сложно прочитать весь его исходный код, и мы даже не знаем, с чего начать. И deno - это возможность. Мы были свидетелями рождения deno. На момент написания этой статьи у deno было всего 249 коммитов.