|Understanding Client/Server Communications|
A user writes:
Does it negatively impact Helix Server performance when a Helix Client has connected, but is left at the log in (enter username and password) screen? If they are called away suddenly and leave it sitting there, does that slow the rest of the Clients down?
Alternatively, if a Client has a dialog (such as Print) open but the user does not respond to it, e.g. leaves the dialog open and goes to lunch, does this impact server performance? Is Helix Server actively waiting for a response from that Client and slowing everyone else down? Or is this a non-issue I shouldn’t worry about?
When a data change is made by any Client, the Server sends a message to every connected Client. For the purpose of this discussion, this initial message is, in essence: a record in relation X changed. Entering a record in a relation with 50 fields creates 1 message. Deleting 50 records on a list results in 50 messages. Entering a record in a window that also posts data to another relation results in 2 messages — one for the record being directly modified and one for the post’s target record. A Post Every operation can affect many target records, so many change messages can result. But at this stage, all the message says is "a record in relation X changed."
At this point an important factor must be brought into the discussion: When a message needs to be sent (by either Client or Server) the message is placed in a message queue (an internal list) that is processed on a "first in, first out" (FIFO) basis. Once a message has been queued up, it is ready to be handed off to the Mac OS TCP/IP code so it can be sent over the network. Keep this ‘queue’ concept in mind as you read on.
Back to the narrative: When Helix Server sends out a message about changed data, the Client’s first job is to receive those messages and determine whether it needs to be concerned about the change. If the Client has a window open and the change affects any relation that supplies data to that window it responds to that message, asking the Server for details about the change. Keep in mind that a view containing an abacus that retrieves data from a different relation (via a lookup or summary tile) is affected by changes in both relations, not just the relation in which the view is constructed. Also keep in mind that a Helix Client can have many windows open, and they must all be kept up to date when data changes.
If the Client determines that it does have an open window that might be affected by the change, it sends a return message to Server: “tell me more about that change.” The Server receives the request, the necessary data is exchanged, and the Client updates the open window.
Under normal circumstances, all of this happens instantaneously. But your question centers around ‘abnormal’ situations, where a Client is not able to immediately receive the message, or can receive it but can’t respond to it. When this happens the messages are queued up until they can be dealt with. Depending on the length of the delay and the amount of activity going on, this queue can grow to contain thousands of messages.
Given what has been established above, consider the ‘Print dialog left open’ scenario: There is at least one window open (the one being printed) and possibly others in the background. In general, when a dialog box is open, Helix doesn’t attempt to update the windows until the dialog is dismissed. But it can receive the messages during that time, so the messages received during that time are queued up, and acted on (in sequential order) once the dialog is dismissed. If a dialog is left unanswered for a long time, a Client can queue up thousands of messages. Dismissing the dialog could unleash a torrent of activity as Client works to catch up on what it missed, but there should not be any significant performance impact while the dialog itself remains open.
The first question posed above — what if a Client is connected but not yet logged in — is basically the same. While the login dialog is open, the Client is queueing up messages. Once the user logs in, those messages are processed. If the act of logging in results in windows that open immediately, those windows open and then the message queue is processed. If no windows are open, the messages are all discarded, following the rules outlined above.
There is also another factor to consider: the non-responsive Client. If the Client can’t even accept the messages coming from the Server — perhaps the Helix Client has been put into the background and the current foreground application is not yielding time for background tasks — then Server must queue up the messages so it can send them as soon as the Client becomes responsive again. As the TCP/IP protocol was designed with the concept of interrupted connections in mind, this has a minimal impact on Server performance, unless thousands of messages are generated in that 2 minutes. Even then the impact of queueing them on the Server would be minimal. However, if those messages are eventually delivered, another torrent of activity can occur if the Client requires the updates that happened while it was non-responsive.
If a Client remains non-responsive for more than 2 minutes, Server gives up and drops the connection altogether. This explains why a Client connection can not be maintained when the Mac it is on goes to into sleep mode.
Here are a few guidelines you can use to avoid unnecessary Server performance degradation:
|Cold Form Addendum||
At some point in the history of Helix, the Keep Current option (aka: Hot/Cold Forms) was added in an effort to cut down on needless message exchanges. Unfortunately, this feature is not well-implemented and although turning Keep Current off for some views does provide a performance benefit, it is not a cure-all for performance issues. (In fact, many bugs we have fixed while working on the macOS native Helix Client have been traced back to “cold forms.”)