Recorder Performance Recommendations

Data Capture with Recorders

Goals

  • I want to implement something that behaves like the MotionScope but is something that I can automate. (Sadly, MotionScope is very onerous to automate.)
  • I do not want to interfere with other threads/code that uses their own recorders.
  • I want to minimize synchronization time between my app, the host and the firmware. (Some API calls do some internal locking/waiting, and that is what I want to minimize.)

Performance

The topic and API doc about recorders are useful, but don’t directly answer all my questions, particularly about performance.

Algorithm

This algorithm seems like it might be what I want.

  1. The count of recorders is set elsewhere (earlier), but reserves enough for this facility.
  2. Configure a subset of recorders (say 0 & 1) that this facility owns. For recorder_number in (0,1):
    0. RecorderStop(recorder_number)
    1. RecorderCircularBufferSet(recorder_number, false) // don’t overwrite data
    2. RecorderPeriodSet(recorder_number, 1) // max resolution
    3. RecorderDataCountSet(recorder_number, <sufficiently_high_number_ASTERISK>)
    4. For each item/address to be tracked in this recorder, data_index:
    1. RecorderDataAddressSet(recorder_number, data_index, <host_address>)
  3. Start capturing data (some time later), For recorder_number in (0,1):
    1. RecorderStart(recorder_number)
  4. Periodically gather the data. For recorder_number in (0,1):
    1. record_count = RecorderRecordDataRetrieveBulk(recorder_number, <sufficiently_high_number_ASTERISK>)
    2. For each item/address to be tracked in this recorder, data_index:
    1. For each record, record_index in (0,record_count-1):
      1. value = RecorderRecordDataValueGet(recorder_number,data_index,record_index)
      2. Do something with the value.
  5. Stop capturing data (some time later), For recorder_number in (0,1):
    1. RecorderStop(recorder_number)

sufficiently_high_number_ASTERISK

This should probably be larger than frequency with which I intend to gather the data. How high? If I want 1-sample resolution, and I intend to gather the data every ms, should I just choose some number that’s (probably) large enough that the Windows thread scheduler can meet most of the time?

Because I already have an interrupt handler (running in a different thread) for the MotionController* object, if I wanted to have event-driven behavior, I’d have to add a scheme for the interrupt-wait thread to notify the thread handling these recorders. This could introduce delays that I don’t want, particularly when the recorder data will be coming in at a regular rate. I can’t have multiple threads waiting for (different) interrupts on the same object, right?

Questions

  1. Does this algorithm minimize sync/locking time/requests?
  2. Does RecorderRecordDataRetrieveBulk(...) move a bunch of data out of the (small) firmware (?) containers and into the MotionCotroller object, so that retrieving it via RecorderRecordDataValueGet(...) avoids synchronization?
  3. The recorder.cs sample does something queer: it sets the data count to 2 and the sample rate to 1, then waits 250 milliseconds before retrieving the data. That would result in getting two records from 249 ms ago (ancient, in terms of run time), right?
  4. What’s the total amount of data that a recorder can handle? RecorderRecordMaxCountGet() * data_item_count? Does the max count ever change?
  1. Have you looked at using Interrupts & RSIEventTypeRECORDER_HIGH to determine the rate at which you do Bulk reads of the Recorder? You can set the interrupt to go off with RecorderBufferHighCountSet to whatevever rate you feel you need to process at.

  2. Yes data reads move data into a MotionController storage. There are locks on retrieving the data from the firmware. We don’t have guards MotionController data access on these two functions. Do you plan to have multiple threads interacting with the recorder data?

  3. The Recorder sample shows a loops through the records until it finds an input then reports the position at that change. Nothing like what you’d want. It assumes you are happy with processing recorded data at some later rather than constantly. See the answer to 1 for a tool to get what you are looking for.

  4. The max is fixed for each recorder. (16384) Each additional address slims the number of captures you can have stored. 4 addresses = 16384 / 4.

Events

I like the event-driven model, but like I said, I already have a (different) thread listening for events on the MotionController object. Can multiple threads do that?

MotionController Storage

I could have 2+ threads managing recorders, but they each have their own disjoint set of recorder numbers that they use. Should I expect a problem with that? I’ve used the scope at the same time as our recorder code without issues.

Is there any problem getting data from the MotionController object from different threads that are using different recorder numbers?

Events - you can only have one thread consuming MotionController interrupts.

Storage - you’ll be fine using separate threads for reading recorded data on separate recorders. I would not recommend using multiple threads reading data from a single recorder.

1 Like