среда, 24 марта 2010 г.

[prog] Еще несколько слов о TLV

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

TLV-представление можно, условно, разделить на два типа:

1. С фиксированными размерами полей Tag и Length. Например, Tag – 2 байта, Length – 4 байта. Это очень простой тип TLV. Его главная проблема – в выборе подходящего размера полей. Например, если под Length отвести 4 байта, а значения не будут превышать 100 байт длиной (а то и 20 байт, что довольно часто происходит в моих задачах), то на каждый TLV будет приходиться три лишних байта в Length. На одном-двух TLV это, может быть, еще и не заметно. А вот на 10-20 TLV полях в PDU и сотнях тысяч PDU – эти лишние байты стремительно складываются в килобайты, а потом и в мегабайты никому не нужных нулей.

2. C “плавающими” размерами полей Length и/или Tag (обычно плавает размер Length). Например (если мне не изменяет склероз, так происходит в ASN.1), если длина Value не превышает 127 байт, то под Length отводится один байт (старший бит у него нулевой). Если же длина Value > 127, то первый байт Length хранит количество байт, необходимых для двоичного представления длины Value. И в первом байте Length старший бит установлен в единицу – это и есть признак того, что Length длиннее одного байта. В таком представлении значение 128 будет представлено двумя байтами: 0x81, 0x80. А значение 256 – тремя: 0x82, 0x01, 0x00. В ряде случаев плавающим делается еще и значение Tag, хотя это усложняет, на мой взгляд, работу с TLV.

Имхо, TLV представление достаточно удобно, когда нужно сериализовать набор объектов. Но здесь, по крайней мере по моему опыту, следует применять двухпроходную схему. На первом проходе вычисляется общий размер будущего представления объектов и выделяется необходимая память. На втором проходе в выделенный буфер (поток) записываются теги, ранее вычисленные длины и значения.

Однако, если же нужно оформлять в TLV уже готовые блоки данных (т.е. есть готовый байтовый массив, который нужно обрамить TLV), то здесь могут начаться проблемы с производительностью. Если в вашем распоряжении нет средств ввода-вывода с поддержкой gather-scatter, то придется выполнять копирование уже готовых данных в новый буфер, в котором будут присутствовать Tag и Length. В некоторых случаях (когда речь будет идти о передачи больших объемов данных) такое копирование обойдется дорого.

Комментариев нет: