iOS Technical Reference
- SDK architecture
- Threading model
- Internal buffer capacity
- Flushing events
- Session management
- Performance and resources
The diagram below illustrates the high level architecture of the SDK.
The SDK methods are thread-safe so your application can call them on different threads. The SDK itself does not use threads and relies on asynchronous callbacks to perform some of its tasks.
Internal buffer capacity
When the internal buffer capacity limit is reached, the SDK will purge or throw out a small number of the oldest events to make room for new events. This results in data loss but should only happen in extreme situations such as when events cannot be flushed to Medio due to prolonged lack of data connectivity or a misbehaving application logging too many events and disabling flushing.
By default, the SDK automatically flushes events to the Medio Data Collection Service (DCS). You can also flush events on demand by calling the
The SDK sends events to the Medio DCS over an HTTP Post request. Once the Medio DCS successfully acknowledges receipt of the events, the SDK removes the events from iOS Core Data. If the HTTP request fails for any reason, then the events are not removed. The SDK does not retry failed requests immediately. Events that are not sent to the Medio DCS successfully remain queued up (stored persistently) in the database to be sent on the next call to
flushEvents. The SDK will ignore new calls to
flushEvents if it is currently performing a flush.
Flushing events assumes that a data connection is available and relies on the iOS HTTP implementation to fail gracefully when a data connection is not available.
Flushing events and application behavior
The SDK’s automatic flush behavior may not meet every application’s requirements. For example, if you find Auto-Flush affecting critical application processing like game play, then you can disable automatic flushing temporarily during these critical processing points using the
disableAutomaticFlushing: selector. Auto-Flush can be re-enabled again using the
enableAutomaticFlushing: selector once the critical processing section is complete. Note your application can still flush events on demand using the
flushEvents selector while automatic flushing is disabled or enabled.
In extreme cases, you may disable automatic flushing entirely for the life of your application. In this case, we recommend calling the
flushEvents selector when you perform some other networking activity (if any). If your application does not have any networking activity, then we recommend calling
flushEvents during pauses in user interaction. For example, in the case of a game, you may wish to flush events in a “Game Over” screen or a “Main Menu” screen.
If you choose to flush events on demand instead of or in addition to automatic flushing, your application should not call
flushEvents too frequently to avoid compromising battery life. On the other hand, you also don’t want to take the risk of losing data by calling
flushEvents too infrequently, a old events are purged to allow for new ones when the internal buffer capacity limit is reached.
- The first time your application calls
openSession, the SDK will create a new session (labeled as Session_A in the diagram below).
- When your application calls
closeSession, the SDK may expire the current session.
- If your application calls
openSessionwithin 10 seconds of the last call to
closeSession, then the SDK will resume the previous session. This behavior means that the SDK will resume the previous session if the user accidentally exits your application and restarts it.
- Your application makes the final call to
- If your application calls
openSessionmore than 10 seconds after the last call to
closeSession, the SDK will create a new session (labeled as Session_B in the diagram below).
Performance and resources
Effect on application size
The SDK only adds an additional 130KB to your application size once your integrate it. This does not include any additional instrumentation code or event logging code that you may add to your application.
We collected the following performance measurements on an iPhone 4 running iOS 5.
openSession and closeSession
Average time to persist an event
The average execution time of the
logEvent call is 7ms based on logging 4,000 events (average size 58 characters including the event name and key-value pairs). Note that the execution time increases as the size of the event increases as shown in the chart below.
When the database is full (when it contains 5,000 events), the average execution time of the
logEvent call is 17ms based on logging an additional 4,000 events (average size 58 characters including the event name and key-value pairs). In this case, the call is slower because the SDK has to delete older events periodically to make sure that there is enough room for newer events.
Our stress tests logged 10 events per second with auto-flush enabled and on-demand flushing of events to the Medio DCS done after every 500 events logged. Each event in the test was comprised of the data shown below, equating to an average of 58 characters.
- Event name: select_next
- Key-value pair 1: page = stop_page_x
- Key-value pair 2: select_next = redirect_id_value_x
The blue horizontal line in the chart below shows the average CPU utilization (approximately 8%) of the SDK during these tests.
We measure RAM usage using Xcode Instruments. A demo application without an SDK session being opened consumed 6.41 MB of real memory. The same application with an SDK session open consumed 6.45 MB.
We have also estimated that a typical
logEvent call consumes approximately 140 KB of RAM, so in our demo application, memory consumption goes up to 6.55 MB. However, since we create our own short-living auto-release pool when required, and don’t use the main auto-release pool, this memory is reclaimed immediately.
The chart below illustrates the SDK’s memory utilization for a scenario when we log 1000 events with an on-demand flush done at the end. The memory spike that you see on the right of the chart is when memory consumption goes up because of the flush events process. Here memory consumption temporarily increases by 1.5 MB to process 1000 events.
Internal buffer size
We calculated the average size of a single event in the SDK internal buffer and found the following:
- 25 characters in an Event occupies approximately 110 bytes.
- 50 characters in an Event occupies approximately 143 bytes.
- 100 characters in an Event occupies approximately 211 bytes.
- 150 characters in an Event occupies approximately 281 bytes.
- 200 characters in an Event occupies approximately 349 bytes.