Click or drag to resize
Rationale
Other Libraries Require a High Effort to Implement a New Consumer

Currently, all other publicly available Ember+ libraries only offer APIs for the the serialization and deserialization of Glow DTD objects. Every company that decides to have one of their products act as a fully functional Ember+ consumer therefore needs to repeat the following steps:

  • Newly implement a data structure or extend an existing data structure so that it offers the following capabilities:

    • Apply a change received from the provider.

    • Apply a locally made change.

    • Enable client code to be notified about changes.

    • Defer the application of provider changes until pending local changes have been sent to the provider.

  • Recursively retrieve from the provider the parts of the tree the consumer is interested in.

  • Detect and handle mismatches between the tree structure expected by the consumer and the tree structure received from the provider.

  • Apply change messages received from the provider to the local data structure.

  • Serialize local changes into appropriate messages and send them to the provider.

  • Implement the keep alive mechanism.

The Ember+ Sharp Library on the other hand implements all of the above in easily reusable components such that a consumer can be implemented in less than an hour. With any other publicly available library this currently takes at least days if not weeks.

EmberLib.net is Unsuitable as a Foundation

Some of the types in the Lawo.EmberPlusSharp.S101 and Lawo.EmberPlusSharp.Ember namespaces duplicate functionality already offered by EmberLib.net in the ember-plus repository. For the reasons documented below, it has been decided to reimplement all functionality from scratch.

  • There are no unit tests for EmberLib.net. It seems obvious that for just about any serious application, reliable communication over Ember+ is of the utmost importance. It is therefore dangerous to use a library that cannot be easily tested whenever a new library release is published. By comparison, the Ember+ Sharp Library is currently covered with automated tests to ~95% statement coverage.

  • In many places the API provided by EmberLib.net, does not seem to follow well-established .NET conventions, for example:

    • Error conditions are largely undocumented.

    • Some error conditions are reported by callbacks instead of exceptions.

    • The library makes it overly difficult to operate on Stream objects. Most .NET communication APIs however provide streams (e.g. NetworkStream or PipeStream).

  • For applications that visualize data communicated over Ember+, it seems best when messages are processed directly on the GUI thread. With such an approach, it is absolutely crucial that all code involved in the processing Ember+ traffic must offer the best possible performance. From a cursory glance at the EmberLib.net source code, it appears that the implementation is unnecessarily inefficient in many places. This impression is partially confirmed by a Performance Comparison of the GlowOutput class with the S101Writer class. The former is ~1.9 times slower than the latter.

Indefinite Length Form for Outgoing Messages

Whenever permitted by the specification, the library uses the indefinite length form for payloads of outgoing messages with EmberData commands (both forms are supported for incoming messages). This simplifies the implementation and reduces the necessary memory and CPU resources to assemble a message at the expense of message size.

Informal measurements for messages with EmberData command and Glow DTD have shown the following overheads:

  • Small messages with nested containers and little other data:

    • 100% for a message with an empty RootElementCollection (worst case)

    • ~50% for typical messages

  • <20% for larger messages with more data. For example, the overhead for the following payload is 10.39%:

    <Root type="RootElementCollection">
      <RootElement type="Node">
        <number type="Integer">7</number>
        <children type="ElementCollection">
          <Element type="Node">
            <number type="Integer">5</number>
            <children type="ElementCollection">
              <Element type="Node">
                <number type="Integer">0</number>
                <children type="ElementCollection">
                  <Element type="Node">
                    <number type="Integer">0</number>
                    <contents type="Set">
                      <identifier type="UTF8String">Properties</identifier>
                      <description type="UTF8String">Properties</description>
                      <isOnline type="Boolean">true</isOnline>
                    </contents>
                  </Element>
                  <Element type="Node">
                    <number type="Integer">1</number>
                    <contents type="Set">
                      <identifier type="UTF8String">TestStaticItems</identifier>
                      <description type="UTF8String">TestStaticItems</description>
                      <isOnline type="Boolean">true</isOnline>
                    </contents>
                  </Element>
                  <Element type="Node">
                    <number type="Integer">2</number>
                    <contents type="Set">
                      <identifier type="UTF8String">TestDynamicItems</identifier>
                      <description type="UTF8String">TestDynamicItems</description>
                      <isOnline type="Boolean">true</isOnline>
                    </contents>
                  </Element>
                </children>
              </Element>
            </children>
          </Element>
        </children>
      </RootElement>
    </Root>

Bandwidth-wise it seems the indefinite length form approach will have a barely noticeable impact because the library allows for value changes to multiple parameters to be sent in a single message:

  • A change that involves many parameters will thus be sent in a large message where the overhead is typically below 20%.

  • Changes involving few parameters will be relatively rare with small message sizes, which makes the large percentual overheads insignificant.