WikiSort.ru - Не сортированное

ПОИСК ПО САЙТУ | о проекте
Protocol Buffers
Тип формат сериализации данных
Разработчик Google
Операционная система Любая ОС
Первый выпуск 7 июля 2008
Аппаратная платформа Cross-platform
Последняя версия 3.4.1 (15 сентября 2017)
Состояние Действующий
Лицензия BSD
Сайт developers.google.com/pr…

Protocol Buffers — протокол сериализации (передачи) структурированных данных, предложенный Google как эффективная бинарная альтернатива текстовому формату XML. Разработчики сообщают, что Protocol Buffers проще, компактнее и быстрее, чем XML, поскольку осуществляется передача бинарных данных, оптимизированных под минимальный размер сообщения.[1]

Общие сведения

По замыслу разработчиков, сначала должна быть описана структура данных, которая затем компилируется в классы. Вместе с классами идёт код их сериализации в компактном формате представления. Чтение и запись данных доступна в высокоуровневых языках программирования — таких как Java, C++ или Python.

В 2010 году бэкенд Twitter перешёл на Protocol Buffers. По заявлению разработчиков Twitter, база в триллион твитов на XML занимала бы десять петабайт вместо одного.[2]

По заявлениям Google, Protocol Buffers по сравнению с XML:[1]

  • проще;
  • от 3 до 10 раз меньше;
  • от 20 до 100 раз быстрее;
  • более однозначный;
  • позволяет создавать классы, которые в дальнейшем легче использовать программно.

Protocol Buffers не предназначен для чтения пользователем и представляет собой двоичный формат. Для десериализации данных необходим отдельный .proto-файл, в котором определяется формат сообщения.

Сравнение с Apache Thrift[3]

Protocol Buffers Apache Thrift
Разработчик Google Facebook, Apache
Поддерживаемые языки C++, Java, Python (Perl, Ruby и C# обсуждаются) C++, Java, JavaScript, Python, PHP, XSD, Ruby, C#, Perl, Objective C, Erlang, Smalltalk, OCaml, and Haskell
Исходящие форматы Binary Binary, JSON
Простые типы bool

32/64-bit integers float double string byte sequence повторные свойства работают как списки

bool

byte 16/32/64-bit integers double string byte sequence map<t1,t2> list<t> set<t>

Константы Нет Да
Составной тип message struct
Исключения Нет Да
Документация Хорошая Проблематично
Лицензия BSD-style Apache
Расширения составных типов Да Нет

Формат протокола

В общем виде формат представляет из себя закодированную последовательность полей, состоящих из ключа и значения. В качестве ключа выступает номер, определённый для каждого поля сообщения в proto-файле. Перед каждым полем указываются совместно закодированные номер поля в формате varint и тип поля. Если в качестве типа указана строка (string), вложенное сообщение, повторяющееся сообщение или набор байт (bytes), то следом идёт размер данных в формате varint. Далее идёт значение, соответствующее полю (данные)[4].

Формат восьмиразрядного varint был выбран для уменьшения размера пакета при передаче небольших чисел. Так, если число меньше 128, то оно будет занимать лишь 1 байт. Однако, если числа близкие к максимально возможным, то количество байт, необходимое для хранения, может, наоборот, увеличиваться. Например, максимальное значение, которое можно сохранить в 8-ми байтах, в формате varint будет занимать 10 байт. Идея формата varint заключается в том, что старший бит (MSB (англ.)) очередного байта числа, выставленный в 1, будет являться флагом окончания последовательности байт, составляющих число. При преобразовании в стандартное представление старший бит каждого байта отбрасывается, а все оставшиеся биты соединяются друг с другом. Проблема кодирования отрицательных чисел была решена использованием алгоритма ZigZag, суть которого сводится к переносу бита знака из старшего разряда в младший.

Кодирование алгоритмом ZigZag предполагает, что положительные и отрицательные числа будут чередоваться друг с другом с увеличением закодированного числа. Пусть value — искомое значение, N — разрядность типа данных искомого значения, а encoded_value — закодированное алгоритмом ZigZag значение, тогда кодирование можно осуществить с помощью выражения:

encoded_value = (value << 1) ^ (value >> (N - 1));

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

uvalue = ((encoded_value & 1) * MAX_VALUE(N)) ^ (encoded_value >> 1);

Значение MAX_VALUE(N) соответствует значению с N разрядами, заполненными единицами (например, 0xffffffff при N=32). Таким образом, умножение младшего бита, установленного в 1, на это число будет соответствовать значению -1 в знаковом типе данных.

Все числовые значения, кроме fixed64, sfixed64 и double, в протоколе кодируются в формате varint.

Примеры использования

Для того чтобы определить структуру сериализуемых данных, необходимо создать .proto-файл с исходным кодом этой структуры. Ниже приведён пример .proto-файла для 2-й версии Protocol Buffers, где описывается информация о машине: марка, тип кузова, цвет, год выпуска, и информация о предыдущих владельцах.

message Car {
  required string model = 1;

  enum BodyType {
    sedan = 0;
    hatchback = 1;
    SUV = 2;
  }

  required BodyType type = 2 [default = sedan];
  optional string color = 3;
  required int32 year = 4;

  message Owner {
    required string name = 1;
    required string lastName = 2; 
    required int64 driverLicense = 3;
  }

  repeated Owner previousOwner = 5;
}

После того как файл с нужной структурой данных создан, необходимо скомпилировать его компилятором для вашего языка программирования, чтобы сгенерировать класс доступа к этим данным. Этот класс будет содержать простейшие методы доступа ко всем полям типа get/set, а также методы для сериализации и десериализации вашей структуры данных в/из массива байтов.

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

Реализация

На данный момент компанией Google созданы компиляторы для языков программирования: C++, Java, Python, Go, C#, Objective C, Javascript[5]. Но существует ряд проектов сторонних разработчиков, которые создали компиляторы для следующих языков программирования: Action Script, C, C#, Clojure, Common Lisp, D, Erlang, Go, Haskell, Haxe, JavaScript, Lua, Matlab, Mercury, Objective C, Swift, OCaml, Perl, PHP, Python, Ruby, Scala, Visual Basic, Delphi[6].

Реализация для языка Си

Чтобы использовать протокол в языке Си без сторонних библиотек необходимо либо использовать вставки на языке C++, если таковые поддерживаются используемым компилятором, либо делать обёртки над сгенерированным для C++ кодом в виде библиотек. Если подобные варианты не подходят, то известны следующие генераторы кода:

  • protobuf-c (нет поддержки обработки ошибок выделения памяти, но возможно использование собственных механизмов выделения памяти);
  • nanopb (оптимизирован под низкое потребление памяти);
  • protobuf-embedded-c (архивный проект).

Примечания

Ссылки

Данная страница на сайте WikiSort.ru содержит текст со страницы сайта "Википедия".

Если Вы хотите её отредактировать, то можете сделать это на странице редактирования в Википедии.

Если сделанные Вами правки не будут кем-нибудь удалены, то через несколько дней они появятся на сайте WikiSort.ru .




Текст в блоке "Читать" взят с сайта "Википедия" и доступен по лицензии Creative Commons Attribution-ShareAlike; в отдельных случаях могут действовать дополнительные условия.

Другой контент может иметь иную лицензию. Перед использованием материалов сайта WikiSort.ru внимательно изучите правила лицензирования конкретных элементов наполнения сайта.

2019-2024
WikiSort.ru - проект по пересортировке и дополнению контента Википедии