Какой самый эффективный способ анализа сообщений протокола FIX в .NET? - PullRequest
8 голосов
/ 05 февраля 2011

Я встречал этот очень похожий вопрос , но этот вопрос помечен QuickFIX (что не относится к моему вопросу), и большинство ответов связано с QuickFIX.

Мой вопросшире.Я ищу наиболее эффективный способ анализа сообщения FIX Protocol с использованием C # .В качестве фона, сообщение FIX состоит из серии пар тег / значение, разделенных символом ASCII <SOH> (0x01).Количество полей в сообщении является переменной.

Пример сообщения может выглядеть следующим образом:

8=FIX.4.2<SOH>9=175<SOH>35=D<SOH>49=BUY1<SOH>56=SELL1<SOH>34=2482<SOH>50=frg<SOH>
52=20100702-11:12:42<SOH>11=BS01000354924000<SOH>21=3<SOH>100=J<SOH>55=ILA SJ<SOH>
48=YY77<SOH>22=5<SOH>167=CS<SOH>207=J<SOH>54=1<SOH>60=20100702-11:12:42<SOH>
38=500<SOH>40=1<SOH>15=ZAR<SOH>59=0<SOH>10=230<SOH>

Для каждого поля, тег (целое число) и значение (для наших целей, строка) разделяются символом '='.(Точная семантика каждого тега определена в протоколе, но это не особенно уместно для этого вопроса.)

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

  • Использование String.Split, итерация по каждому элементу и помещение тега в отображение индекса в Hashtable - обеспечивает полный произвольный доступ ко всем полям, если это необходимо в некоторыхpoint

  • (небольшая оптимизация) Используя String.Split, сканируйте массив для поиска интересующих тегов и помещайте тег в отображение индекса в другой контейнер (не обязательно Hashtable, поскольку это может быть довольнонебольшое количество элементов, и количество элементов известно до разбора)

  • Сканирование поля сообщения по полю с использованием String.IndexOf и сохранение смещения и длины интересующих полей всоответствующая структура

Относительно первых двух - хотя мои измерения показывают, что String.Split довольно быстро, согласно документации метод выделяет новую строку для каждого элементарезультирующий массив, который может генерировать много мусора, если вы анализируете много сообщений.Кто-нибудь может найти лучший способ решения этой проблемы в .NET?

РЕДАКТИРОВАТЬ:

Три важные части информации, которые я пропустил:

  1. Теги не обязательно являются уникальными в сообщениях FIX, т. Е. Дубликаты тегов могут возникать при определенных обстоятельствах.

  2. Некоторые типы полей FIX могут содержать «встроенный <SOH>» вданные - эти теги относятся к типу «данные» - в словаре перечислены номера тегов этого типа.

  3. В конечном итоге необходимо иметь возможность редактироватьсообщение (в частности, заменить значения).

Ответы [ 4 ]

8 голосов
/ 04 марта 2011

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

Вы сможете легко избежать выделения большинства объектов. Вы можете легко и очень быстро разобрать типы данных FIX с плавающей запятой, не создавая объектов (вы можете значительно превзойти double.parse с вашей собственной версией здесь). Единственное, о чем вам может потребоваться подумать, это значения тегов, которые являются строками, например значения символов в FIX. Чтобы избежать создания здесь строк, вы можете придумать простой метод определения уникального int-идентификатора для каждого символа (который является типом значения), и это снова поможет вам избежать выделения в куче.

Настроенный оптимизированный синтаксический анализ сообщения, выполненный правильно, должен легко превзойти QuickFix, и вы можете делать все это без сборки мусора в .NET или Java.

3 голосов
/ 05 февраля 2011

Я бы определенно приступил к реализации вашего первого подхода, потому что это звучит ясно и легко.

A Dictionary<int,Field> кажется мне очень хорошим, может быть, заключен в классы FixMessage, предоставляющие такие методы, как GetFieldHavingTag(int tag) и т.д ...

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

Конечно, единственный способ убедиться, что подход хорош для вас или нет, это реализовать его и протестировать.

Если вы заметили, что в случае большого количества сообщений метод медленный, то профилируйте его и найдите, в чем / где проблема.

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

Итак, давайте представим, что после вашей первой реализации вы заметили, что при большом количестве сообщений распределение строк замедляет вашу производительность.

Тогда да, я бы выбрал подход, аналогичный вашему третьему, давайте назовем его "подход по требованию / ленивый".

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

2 голосов
/ 15 ноября 2011

Я знаю, что это ответ на старый вопрос - я только недавно понял, что есть много вопросов, связанных с FIX, по SO, поэтому я решил попробовать ответить на этот вопрос.

ОтветВаш вопрос может зависеть от конкретных сообщений FIX, которые вы на самом деле анализируете.В некоторых случаях да - вы могли бы просто сделать «разбиение» на строку, или что там у вас, но если вы собираетесь анализировать все сообщения, определенные в протоколе, у вас нет выбора, кроме как ссылатьсясловарь данных FIX и для разбора сообщения побайтно.Это связано с тем, что в сообщениях FIX имеются поля с закодированной длиной, в соответствии со спецификацией, которые могут содержать данные, которые могут помешать любому подходу «разделения», который вы, возможно, захотите использовать.

Самый простой способ сделать этоэто ссылка на словарь и получение определения сообщения на основе типа (тег 35) полученного сообщения.Затем вам нужно извлечь теги один за другим, ссылаясь на соответствующее определение тега в определении сообщения, чтобы понять, как должны анализироваться данные, связанные с тегом.Это также помогает вам в случае «повторяющихся групп», которые могут существовать в сообщении - и вы сможете понять, что тег представляет начало повторяющейся группы, если у вас есть определение сообщения из словаря.

Надеюсь, это поможет.Если вам нужен справочный пример, я написал движок FIX с открытым исходным кодом VersaFix для .NET, в котором есть анализатор сообщений на основе словаря.Вы можете скачать исходный код прямо с нашего сервера Subversion, указав клиенту SVN:

svn://assimilate.com/VfxEngine/Trunk

Cheers.

1 голос
/ 08 февраля 2011

Вам, вероятно, лучше честно использовать QuickFix и создать для него оболочку Managed C ++.Если вас вообще беспокоит задержка, вы не можете выполнять выделения как часть анализа, так как это может привести к запуску GC, который приостанавливает работу вашего механизма FIX.Когда пауза, вы не можете отправлять или получать сообщения, которые, как я уверен, вы знаете, очень и очень плохо.

Была одна компания, которую Microsoft несколько лет назад подчеркнула, что она создает движок FIX полностью на c #.Они будут создавать пул объектов, которые будут использоваться в течение торгового дня, и не будут распределяться в течение дня.

Я не знаю, каковы ваши требования к задержке, но для того, что я делаю, мы использовали codegenразличные типы многопоточных куч, чтобы получить производительность и уменьшить задержку.Мы используем смесь c ++ и haskell.

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

@ Hans:10 микросекунд это очень долго.NASDAQ соответствует заказам за 98 микросекунд, а SGX объявила, что пересечение их новой платформы в этом году займет 90 микросекунд.

...