{"id":3702,"date":"2010-06-24T15:45:43","date_gmt":"2010-06-24T20:45:43","guid":{"rendered":"http:\/\/bobbeaty.com\/wp\/?p=3702"},"modified":"2010-06-25T07:31:47","modified_gmt":"2010-06-25T12:31:47","slug":"identifying-sorting-classifying-a-ton-of-messages","status":"publish","type":"post","link":"https:\/\/bobbeaty.com\/wp\/archives\/3702","title":{"rendered":"Identifying, Sorting, Classifying a Ton of Messages"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/bobbeaty.com\/wp\/wp-content\/uploads\/2010\/06\/SchoolBus.jpg\" alt=\"The Magic School Bus\" title=\"SchoolBus.jpg\" border=\"0\" width=\"130\" height=\"101\" style=\"float:right;\" \/><\/p>\n<p>Today I started the process of trying to consolidate the 300+ messages in <em>The Magic Schoolbus<\/em> into a few reasonable categories: OPRA messages (tons of them, space is critical, data format very rigid), Price Messages (little looser, but still important and small), and everything else. The remainder of the messages are really suitable for fitting into self-describing message formats like JSON, or more likely BSON, as they are very flexible - have variable number of components, and don't need to get shot around the network all the time.<\/p>\n<h3>The Really Wasteful<\/h3>\n<p>Take for instance, the Holiday Calendar. This is just like every other Holiday Calendar I've ever seen: give it a date (or default to today, and it'll give you all the trading holidays for the next 'n' months. Very simple data structure. Even simpler when all you're talking about are US Equities and their options - you don't even need to tell it which exchange you're asking about as they are <strong>all<\/strong> the same.<\/p>\n<p>But here's what <em>The Magic Schoolbus<\/em> does: <em>Every minute<\/em> it will publish a list of all holidays for the next <em>ten years<\/em> and those that are registered for this data will receive it. Over, and over again. Every minute. The format is pretty simple as well. There's the basic header of the message (far too verbose and general) but the payload of the message looks like this:<\/p>\n<pre class=\"cpp\" style=\"font-family:monospace;\">  <span style=\"color: #0000ff;\">struct<\/span> <span style=\"color: #008000;\">&#123;<\/span>\n    <span style=\"color: #0000ff;\">uint16_t<\/span>       modifiedBy<span style=\"color: #008080;\">;<\/span>    <span style=\"color: #666666;\">\/\/ trader ID<\/span>\n    <span style=\"color: #0000ff;\">char<\/span>           today<span style=\"color: #008000;\">&#91;<\/span><span style=\"color: #0000dd;\">9<\/span><span style=\"color: #008000;\">&#93;<\/span><span style=\"color: #008080;\">;<\/span>      <span style=\"color: #666666;\">\/\/ YYYYMMDD<\/span>\n    <span style=\"color: #0000ff;\">uint8_t<\/span>        numHolidays<span style=\"color: #008080;\">;<\/span>   <span style=\"color: #666666;\">\/\/ # of holidays<\/span>\n    Holidays_NEST  holidays_nest<span style=\"color: #008000;\">&#91;<\/span><span style=\"color: #008000;\">&#93;<\/span><span style=\"color: #008080;\">;<\/span>\n  <span style=\"color: #008000;\">&#125;<\/span> HolidayCalendar<span style=\"color: #008080;\">;<\/span><\/pre>\n<p>where <tt>Holidays_NEST<\/tt> looks like:<\/p>\n<pre class=\"cpp\" style=\"font-family:monospace;\">  <span style=\"color: #0000ff;\">struct<\/span> <span style=\"color: #008000;\">&#123;<\/span>\n    <span style=\"color: #0000ff;\">char<\/span>      holidayDate<span style=\"color: #008000;\">&#91;<\/span><span style=\"color: #0000dd;\">9<\/span><span style=\"color: #008000;\">&#93;<\/span><span style=\"color: #008080;\">;<\/span>   <span style=\"color: #666666;\">\/\/ YYYYMMDD<\/span>\n    <span style=\"color: #0000ff;\">uint8_t<\/span>   holidayType<span style=\"color: #008080;\">;<\/span>      <span style=\"color: #666666;\">\/\/ 1=no trading; 2=half day<\/span>\n  <span style=\"color: #008000;\">&#125;<\/span> Holidays_NEST<span style=\"color: #008080;\">;<\/span><\/pre>\n<p>Now even if we put aside the problems with this content - like a date that's 9 bytes when 2 would do (as a uint16_t) - in fact, we could compress the entire message to look like this:<\/p>\n<pre class=\"cpp\" style=\"font-family:monospace;\">  <span style=\"color: #0000ff;\">struct<\/span> <span style=\"color: #008000;\">&#123;<\/span>\n    <span style=\"color: #0000ff;\">uint16_t<\/span>    modifiedBy<span style=\"color: #008080;\">;<\/span>    <span style=\"color: #666666;\">\/\/ trader ID<\/span>\n    <span style=\"color: #0000ff;\">uint16_t<\/span>    today<span style=\"color: #008080;\">;<\/span>         <span style=\"color: #666666;\">\/\/ YYYYMMDD<\/span>\n    <span style=\"color: #0000ff;\">uint8_t<\/span>     numHolidays<span style=\"color: #008080;\">;<\/span>   <span style=\"color: #666666;\">\/\/ # of holidays<\/span>\n    <span style=\"color: #0000ff;\">uint16_t<\/span>    holidays<span style=\"color: #008000;\">&#91;<\/span><span style=\"color: #008000;\">&#93;<\/span><span style=\"color: #008080;\">;<\/span>    <span style=\"color: #666666;\">\/\/ tYYYYMMDD<\/span>\n  <span style=\"color: #008000;\">&#125;<\/span> HolidayCalendar<span style=\"color: #008080;\">;<\/span><\/pre>\n<p>where the 't' is the type of day and the date immediately follows. A simple mask gets us what you need and size comparison (assuming 64-bit pointers) is:<\/p>\n<pre>\n  old size = 12 + n * 10\n  new size = 5 + n * 2\n<\/pre>\n<p>and for a typical year we have, say 7 holidays, and ten years, so n = 70:<\/p>\n<pre>\n  old size = 12 + 70 * 10 = 712\n  new size = 5 + 70 * 2 = 145\n  savings: 79%\n<\/pre>\n<p>It's just stunning how bad some of these messages are.<\/p>\n<h3>The Horrible Congestion<\/h3>\n<p>Look again at the Holiday Calendar - it's sending this data out <em>every minute<\/em>. Why? Because the designers believed that this was the <em>only<\/em> way the data was going to get delivered to the client. What about a data cache\/data service? They even have a cache server in the architecture - but it holds <strong>all<\/strong> the messages sent and as such, it's not nearly as efficient as a more customized data service.<\/p>\n<p>So I need to do something here - basically, <strong><em>stop the insanity<\/em><\/strong> of sending all this data all the time. I need to have the client get it when it requests it and when it fundamentally changes. This means something a lot more intelligent and flexible than <em>read from the database, make a monster message, send it, repeat<\/em>.<\/p>\n<h3>The Task<\/h3>\n<p>It's <strong>huge<\/strong>. I have to look at all the used messages and then try to see what can be combined into a nice, compact format for sending at high speed to a lot of clients, and what can be more free-form and possibly even skip the 29West sending in the first place.<\/p>\n<p>It's a monster job. But it's gotta be done. The reason this is in such a horrible state is because no one has taken it upon themselves to do this until now. It's ugly, and it's painful, but it's got to be done.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Today I started the process of trying to consolidate the 300+ messages in The Magic Schoolbus into a few reasonable categories: OPRA messages (tons of them, space is critical, data format very rigid), Price Messages (little looser, but still important and small), and everything else. The remainder of the messages are really suitable for fitting [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3,6],"tags":[],"class_list":["post-3702","post","type-post","status-publish","format-standard","hentry","category-coding","category-cube-life"],"_links":{"self":[{"href":"https:\/\/bobbeaty.com\/wp\/wp-json\/wp\/v2\/posts\/3702","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/bobbeaty.com\/wp\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bobbeaty.com\/wp\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bobbeaty.com\/wp\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/bobbeaty.com\/wp\/wp-json\/wp\/v2\/comments?post=3702"}],"version-history":[{"count":3,"href":"https:\/\/bobbeaty.com\/wp\/wp-json\/wp\/v2\/posts\/3702\/revisions"}],"predecessor-version":[{"id":3709,"href":"https:\/\/bobbeaty.com\/wp\/wp-json\/wp\/v2\/posts\/3702\/revisions\/3709"}],"wp:attachment":[{"href":"https:\/\/bobbeaty.com\/wp\/wp-json\/wp\/v2\/media?parent=3702"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bobbeaty.com\/wp\/wp-json\/wp\/v2\/categories?post=3702"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bobbeaty.com\/wp\/wp-json\/wp\/v2\/tags?post=3702"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}