`

СПЕЦИАЛЬНЫЕ
ПАРТНЕРЫ
ПРОЕКТА

Архив номеров

Как изменилось финансирование ИТ-направления в вашей организации?

Best CIO

Определение наиболее профессиональных ИТ-управленцев, лидеров и экспертов в своих отраслях

Человек года

Кто внес наибольший вклад в развитие украинского ИТ-рынка.

Продукт года

Награды «Продукт года» еженедельника «Компьютерное обозрение» за наиболее выдающиеся ИТ-товары

 

У XML появился конкурент

Статья опубликована в №29-30 (647) от 12 августа

+26
голосов

Вряд ли кто-то в состоянии назвать хотя бы приблизительное число языков, предназначенных для описания данных. По крайней мере, можно с уверенностью сказать, что таковых немало. В свое время создание еще одного, Protocol Buffers, не только не стало сенсацией, но и вовсе прошло незамеченным. И даже открытие доступа к исходным кодам этого проекта (формировавшегося в недрах Google) тоже было воспринято как рядовое событие. Шум поднялся лишь после заявления специалистов о том, что Protocol Buffers способен заменить язык XML или хотя бы существенно потеснить его позиции.

За десять лет, прошедшие с того момента, как консорциум W3C утвердил первую версию спецификации eXtensible Markup Language, язык XML прочно завоевал репутацию одного из краеугольных камней современных информационных технологий. Он весьма успешно используется для публикации в Веб, применяется в конфигурационных файлах и офисных документах, но основным его назначением, конечно же, является кросс-платформенная передача данных. Сегодня идея заменить XML чем-то другим может показаться посягательством чуть ли не на сами принципы фон Неймана. Но для того чтобы реально оценить перспективы языка Protocol Buffers в качестве конкурента XML, надо хотя бы в общих чертах разобраться в его возможностях. Конечно, в рамках небольшой статьи абсолютно нереально не только полностью описать язык, но даже более или менее детально познакомить читателя с его основными характеристиками. Поэтому мы вынуждены ограничиться скорее намеками, которые, однако, позволяют составить приблизительное представление о «соотношении сил» между XML и Protocol Buffers.

Неожиданный знак равенства

Если полное описание самого языка XML можно уместить в одном небольшом абзаце и успеть ознакомиться с ним меньше чем за пять минут (сложности начнутся потом, когда придется разбираться с XSchema, XPath, XPoint и т. д.), то с Protocol Buffers дело обстоит по-другому. Прежде чем описать хотя бы небольшой фрагмент данных, нужно потратить некоторое время на изучение этого языка. Поэтому давайте по порядку.

Предположим, что в нашем распоряжении есть XML-документ, описывающий возраст, рост и вес человека:

<person>
<name>Иванов</name>
<age>40</age>
<height>180</height>
<weight>75</weight>
<person>

Оставим на долю Иванова радоваться, что в свои сорок лет он пребывает в идеальной форме, а сами переведем ту же информацию в формат Protocol Buffers:

message Person {
required string name = 1;
optional int32 age = 2;
optional int32 height = 3;
optional int32 weight = 4;
}

Уже при первом знакомстве с Protocol Buffers в глаза бросается его крупный недостаток – формат представления данных никак нель-зя назвать интуитивно понятным. Действительно, у любого программиста сразу же возникает ассоциация с инициализацией переменных. И если слишком малые значения age, height и weight лишь вызывают недоумение, то выражение name = 1 кажется явной ошибкой! Однако ее здесь нет. Чтобы использовать Protocol Buffers, надо привыкнуть к тому, что после знака равенства задаются не непосредственные значения элементов, а числовые дескрипторы, призванные идентифицировать их в дальнейшем. Сами же значения появятся позднее, уже после того, как описание данных будет преобразовано в текст программы на целевом языке.

Короче невозможно

Итак, недоразумение с дескрипторами, слишком похожими на значения, вроде бы разъяснено, но пока совершенно непонятно, какие преимущества такой подход дает Protocol Buffers. Впрочем, и не удивительно – ведь заключаются они вовсе не в самом синтаксисе.

Если в XML элемент <age>40</age> определяет имя и соответствующее ему значение и в неизменном виде помещается в файл или передается по сети, то в Protocol Buffers строка optional int32 age = 2 играет лишь роль своеобразного шаблона. Реальные данные записываются гораздо компактнее, к примеру, если в нашем случае элементу age присваивается значение 40, то его двоичное представление займет в памяти всего два байта: 16 40

Согласитесь, существенная экономия по сравнению с тринадцатью символами, которыми те же данные представляются в формате XML. Очевидно, что второй байт содержит собственно значение. В первом же находятся номер дескриптора (именно стоящий справа от знака равенства) и тип элемента. Несмотря на то что в Protocol Buffers определено большое количество типов данных, они удачно объединены в группы и для их кодирования достаточно трех битов. Поэтому значение дескриптора сдвигается влево на три позиции и полученная величина (в данном случае 16) складывается с кодом типа (который для int32, как и для ряда других целочисленных типов, равен нулю).

Казалось бы, присвоив элементу height значение 180, мы также сможем записать его в виде двух байтов, однако на этот раз ситуация не столь проста, и чтобы разобраться в ней, надо сперва рассмотреть формат varint.

Жертва бита во имя оптимизации

Сколько битов достаточно для представления целого числа? Шестнадцать? Тридцать два? Шестьдесят четыре? Удачный ответ на этот вопрос нашли создатели Protocol Buffers. Они предложили выделять ровно столько битов, сколько необходимо. Ну или, может быть, чуть больше, но совсем ненамного. Для этой цели они разработали специальный формат под названием varint, согласно которому в каждом байте 7 бит выделяется для хранения значения, а восьмой сообщает о том, поместилось ли оно. То есть если восьмой бит сброшен (равен нулю), то это означает, что данный байт – последний в цепочке, представляющей значение элемента. И наоборот, единица в восьмом бите говорит о том, что для кодирования значения пришлось задействовать и следующий байт.

Так как число 40, присвоенное ранее age, помещается в семи битах, то старший бит этого байта попросту сбрасывается. Значение же 180 элемента height (двоичный код 10110100) поместится только в двух байтах. Первый по случайному совпадению будет равен 180, но на самом деле представление данных им не исчерпывается. Значащих битов в нем только семь (т. е. 0110100, или 52), а старший разряд переносится в следующий байт. Таким образом, состояние элемента height описывается тремя байтами, а именно 24 180 1

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

Числовой дескриптор, идентифицирующий элемент, также представляется в формате varint. Учитывая сдвиг влево на три разряда, нетрудно заметить, что дескрипторы от 1 до 15 могут быть представлены одним байтом, а для больших значений приходится использовать дополнительный. Таким образом, значения из первой группы целесообразно применять для наиболее востребованных элементов. Вероятно, именно поэтому в Protocol Buffers дескрипторы задаются вручную, а не генерируются автоматически.

Библиотека on the fly

Каждый, кому приходилось работать с XML-файлами, конечно же, знаком с основными средствами их формирования и разбора. Независимо от того, надо ли строить XML-дерево с помощью DOM или фиксировать события, возникающие при потоковой обработке данных, посредством SAX, в любом случае приходится обращаться к соответствующим библиотекам, которыми снабжен практически каждый серьезный язык программирования. Но где же искать библиотеки для Protocol Buffers? К счастью, об этом позаботились специалисты Google, и их решение нельзя не признать элегантным.

Создав описание данных, подобное приведенному выше, его надо скомпилировать с помощью программы protoc.exe, на выходе которой и будет получена библиотека, предназначенная для работы с ними. В нее помещается структура, определяющая соответствие между именами элементов и числовыми дескрипторами, а также формируется отдельный класс, содержащий методы доступа к конкретным элементам. Так, для приведенного выше документа будет создан класс Person. Поскольку в нем среди прочих определены имена name и age, то в Java-версии библиотеки, сформированной на его основе, будут присутствовать методы getName(), setName(), getAge() и setAge(), а в библиотеке для C++ соответственно – name(), set_name(), age() и set_age(). Именно с помощью set-методов и устанавливаются значения элементов.

В классе определяются и методы для сериализации элементов (в данном случае под этим понимается генерация последовательности байтов, представляющих числовой дескриптор, тип и значение) и разбора данных, полученных из потока, – перевода их в формат, пригодный для дальнейшей работы.

Придется ли XML потесниться?

Скажем сразу, появившиеся в Интернете броские заголовки статей, гласящие о том, что язык Protocol Buffers призван заменить XML, следует воспринимать крайне скептически. Разумеется, в задачах, предполагающих передачу больших объемов информации, Protocol Buffers должен быть эффективнее XML, но в ущерб наглядности и легкости восприятия. На малых же объемах его преимущества сомнительны. Например, вряд ли кому-то придет в голову переводить в формат Protocol Buffers конфигурационный файл приложения.

Как утверждают специалисты Google, Protocol Buffers по сравнению с XML позволит в 3–10 раз уменьшить объем памяти, необходимой для хранения данных, и в 20–100 раз увеличить скорость их обработки. Реальность этих цифр можно легко оценить, сравнивая способы представления информации в XML и Protocol Buffers.

Очевидно, что наибольшую экономию памяти дает замена символьных имен XML-элементов числовыми дескрипторами. Конечно, ограничиться однобайтовыми дескрипторами трудно, 15 элементов – слишком мало для реальных приложений, но два бай-та (2047 вариантов) – уже вполне допустимая цифра. Заменив двумя байтами символьное имя, действительно можно добиться сокращения объема памяти. Но вот насколько – зависит от самих имен. Если отдавать предпочтение развернутым XML-дескрипторам наподобие <number_of_years_that_person_lives>, то экономия будет существенной, а компактным вроде <age> – то не слишком. Если же разработчик сознательно формирует часто повторяющиеся имена так, чтобы документ занимал как можно меньше места (а именно так поступают создатели промышленных форматов на основе XML, к примеру, в Office Open XML для текстовых фрагментов используется <w:t>), то преимущество Protocol Buffers перед XML будет незначительным.

Возможности экономии памяти при представлении значений элементов также весьма ограничены. Максимальное (трехкратное) сокращение объема дадут целые числа в интервале от 100 до 127. Любые другие значения, которые можно представить в формате varint, «сжимаются» хуже, числа фиксированного размера (fixed32, fixed64 и др.) – совсем плохо, а текстовые данные – и вовсе никак. Кстати, сами создатели Protocol Buffers признают, что для чисто текстовой информации формат XML предпочтительнее.

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

На сегодняшний день компилятор Protocol Buffers поддерживает только С++, Java и Python. Очевидно, что на данном этапе выбор целевых языков диктовался исключительно интересами Google (которая уже активно использует данный формат), но расширение их списка не вызовет принципиальных затруднений. Однако произойдет это только в том случае, если Protocol Buffers сумеет выйти за пределы одной (пусть и довольно большой) компании и будет признан во всем мире.

Итак, в настоящее время XML вне опасности. Язык Protocol Buffers, скорее всего, останется нишевым, ориентированным на специфические задачи, предполагающие обработку больших объемов данных. Но сам факт того, что кто-то допускает возможность замены XML, должен стать поводом для серьезных размышлений. Вероятно, XML действительно требует дальнейшего развития. И, в первую очередь, именно в вопросах обеспечения компактного хранения данных и эффективной их обработки.

+26
голосов

Напечатать Отправить другу

Читайте также

Вот прочитал статью.

В одной из телевизионных программ времен Андроповской перстройки было какое-то интеллектуальное соревнование двух команд молодых людей. Команде состоящей из молодых людей давали указания и наставления немолодые люди. Но команда упорно не слушала, наставлений и в какой-то момент начала выигрывать. Потом кто-то из членов команды рассказал о художнике-абстракционисте, который нарисовал картину на которой был белый кролик. Кролика надо убрать - говорили ему критики, и будет выдающаяся картина. Но он настоял на своем, и оставил белого кролика на полотне. Молодой человек из команды также сказал что будет следовать за белым кроликом. (Follow white rabbit.) Через много лет, следования за белым кроликом я понял как работало советское телевидение. Пора мне перестать следовать за белым кроликом.

Увидев в статье синтаксис языка, я вдруг заметил что это почти тот язык которым я описывал базу данных в своем несостоявшемся поисковом сервере, который в интернете пробыл с месяц, и после чего и у меня и у интернет провайдера случилась чреда неудач. Господин Сергей Гульчук даже написал развернутую статью о каких-то "подрезанных крыльях". Надо думать Google был бесперспективным проектом в которых "маркетологи" на деньги американского фонда не увидели "никаких перспектив", если "идти мимо посольств" прямо в "демократически избранный" спец. приемник распределитель. Скорее проще всего посмотреть на какие "демократически избранные" деньги в Калифорнии и Флориде некоторые государственные служащие домики выстроили.

Кстати идея о упаковке битов в с одним сигнальным пришла из системы команд Matrix'а, а точнее Transputer'ов фирмы Inmos. В системе команд (наборе инструкций) этих микропроцессоров, несколько подряд записанных инструкций константа имела свойство накапливаться в рабочем регистре. То есть две подряд записанные инструкции константы составляли один байт. Где собственно код инструкции содержался в 4-х битах а еще 4 - содержали данные собственно константы. Вместо того чтобы код инструкции и байт данных (как в большинстве тогдашних 8-битовых микропроцессоров) записывали две 8-битовых инструкции где было по 4 бита данных константы. И работало это все очень быстро, за счет обеспечения многих критериев которые тогда казались недосягаемыми для всяких Американских фирмочек-выскочек с ихними "Искорками", "тройками", "четверками" и др.. В Языке описания базы поискового сервера, я хотел применить похожий принцип, но командой (или инструкцией был бы один бит в состояниях "продолжать" и "конец".) Аналогичный принцип используется и в компрессии данных но тут ближе как раз к обработке поскольку базу данных должен был обрабатывать обработчик как бы по ходу без ненужных переключений между сегментами (диска или памяти) которые замедляли работу. По этому пожертвованные бит больше походил на инструкцию.

Кстати в перспективе обработчик должен был быть аппаратным. Но не сложилось.

Другой аналог был - язык Basic для ZX-Spectrum, наполовину литеральный наполовину индексный.

Хотя в том варианте который работал в интернете, хоть и не долго, цифры записывались как они есть в литеральном виде..

Сегодня меня убедили в преимуществах XML. Да и проект достиг только частичного развития. В конце концов, я даже согласился не найдя доводов в пользу других языков, при условии что язык XML - будет иметь "дальнейшее развитие". Это развитие в отличии от точки зрения демагогов должно иди по улучшения возможностей обработки данных в этом языке. Поскольку сама по себе компактность может быть обеспечена даже специализированной микросхемой компрессором, или быстрым алгоритмом компрессии. Касательно языка у меня куча наработок, и наблюдений.

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

Багато нових бібліотек, фреймворків та сервісів стараються додати інтерфейси на базі Google Protocol Buffers. Так виглядає, що всюди де буде потребуватись велика пропускна задатність, будуть використовуватись або Protocol Buffers, або Apache Thrift

btw, недавно вийшла свіжа версія Protocol Buffers. Деталі на Розробці - http://www.rozrobka.com/blog/scalability/26.html

 
 
IDC
Реклама

  •  Home  •  Рынок  •  ИТ-директор  •  CloudComputing  •  Hard  •  Soft  •  Сети  •  Безопасность  •  Наука  •  IoT