A typical distributed visualization environment is based on a server – client architecture, when the server generates the visual data (for simplicity we’ll call it a frame) and sends it to the client. The client displays the frame, and can send events to the server. We’ll start by (very) briefly analyzing the process, from the servers perspective. It looks something like this:

So lets define the time intervals involved in the process:
t_app – The time it takes the application to generate a new frame, usually we have no control over this.
t_blit – The time it takes to copy the new frame data to our local buffer.
t_proc – The time it takes to process the frame.
t_net_client – The time spent from the moment we finished processing the frame and asked to send it, until we received an acknowledge (ACK) from the client on that frame. It includes network and client processing time.
So we get:
totalFrameTime = t_app + t_blit + t_proc + t_net_client
After we have sent a frame, we don’t want to wait for an ACK and then do all the processing for the new frame. We want to use this time to prepare a new frame. The other extreme is never to wait for an ACK, and just send frames as fast as possible. In this case, if the client or network are slow (slower than processing a new frame), the frames will buffer up on the net or the client. If, theoretically, those buffers are infinite, then the latency will infinitely grow.
We don’t want this to happen, so we introduce a maximum latency (maxL) limit. Until we reach this limit, we process and send frames as fast as possible. When we reach it we can stop the application or drop frames, until we get below the limit again. If maxL is big, the latency will grow, and the frame rate can also potentially grow, because we spend less time waiting. If maxL is small, we can minimise latency, but we’ll pay in performance, because we’ll be waiting most of the time. Obviously this value needs to be adjusted to the environment and it’s needs. It would be even better if it could be adjusted dynamically.
So that ends the brief theory and implementation, now lets see how we can measure stuff. We won’t be measuring the time it takes for the application to generate a frame, because as mentioned before, we usually don’t have control over this. There are many ways and tools to measure application frame rate.
So how do we measure frame latency? We need to measure the time when the application finishes generating a frame, and we start our process (t_start), and save this time, until we get an ACK on that frame (t_ack). So:
latency = t_ack - t_start
We should average on N frames to get more robust measures.
One thing worth mentioning, is that the ACK on the client side can be sent after processing – to include the client processing time in our measure. Sometimes we may gain performance by sending the ACK before processing, as soon as the client gets a new frame, in order to allow the server to send new frame immediately. Measuring the difference between both cases can give us an idea about client processing time.
It is also easy to measure server processing time, it’s the time from t_start until we send the frame (t_send), so:
server processing time = t_send - t_start
We can measure the blit and frame processing time, by simply timing these functions.
You may have noticed that this post describes a situation where the all the server processing is done in a single thread. This is not always the case, sometimes the application runs in a different thread or process, or we want to use different CPU’s or hardware for blit or processing. There things get more complicated. We’ll talk about this and see some examples next time.
[...] displayed. The time consuming parts are server & client processing and network limitations. See this post for more [...]