"
ASP.NET (snapshot 2017) Microsoft documentation and samples

SignalR Performance

by Patrick Fletcher

This topic describes how to design for, measure, and improve performance in a SignalR application.

Software versions used in this topic

Previous versions of this topic

For information about earlier versions of SignalR, see SignalR Older Versions.

Questions and comments

Please leave feedback on how you liked this tutorial and what we could improve in the comments at the bottom of the page. If you have questions that are not directly related to the tutorial, you can post them to the ASP.NET SignalR forum or StackOverflow.com.

For a recent presentation on SignalR performance and scaling, see Scaling the Real-time Web with ASP.NET SignalR.

This topic contains the following sections:

Design considerations

This section describes patterns that can be implemented during the design of a SignalR application, to ensure that performance is not being hindered by generating unnecessary network traffic.

Throttling message frequency

Even in an application that sends out messages at a high frequency (such as a realtime gaming application), most applications don’t need to send more than a few messages a second. To reduce the amount of traffic that each client generates, a message loop can be implemented that queues and sends out messages no more frequently than a fixed rate (that is, up to a certain number of messages will be sent every second, if there are messages in that time interval to be sent). For a sample application that throttles messages to a certain rate (from both client and server), see High-Frequency Realtime with SignalR.

Reducing message size

You can reduce the size of a SignalR message by reducing the size of your serialized objects. In server code, if you’re sending an object that contains properties that don’t need to be transmitted, prevent those properties from being serialized by using the JsonIgnore attribute. The names of properties are also stored in the message; the names of properties can be shortened using the JsonProperty attribute. The following code sample demonstrates how to exclude a property from being sent to the client, and how to shorten property names:

.NET server code that demonstrates the JsonIgnore attribute to exclude data from being sent to the client, and the JsonProperty attribute to reduce message size

[!code-csharpMain]

   1:  using Newtonsoft.Json; 
   2:  using System; 
   3:  public class ShapeModel
   4:  {
   5:      [JsonProperty("l")]
   6:      public double Left { get; set; }
   7:      [JsonProperty("t")]
   8:      public double Top { get; set; }
   9:      // We don't want the client to get the "LastUpdatedBy" property
  10:      [JsonIgnore]
  11:      public string LastUpdatedBy { get; set; }
  12:  }

In order to retain readability/ maintainability in the client code, the abbreviated property names can be remapped to human-friendly names after the message is received. The following code sample demonstrates one possible way of remapping shortened names to longer ones, by defining a message contract (mapping), and using the reMap function to apply the contract to the optimized message class:

Client-side JavaScript code that remaps shortened property names to human-readable names

[!code-javascriptMain]

   1:  function reMap(smallObject, contract) {
   2:      var largeObject = {};
   3:      for (var smallProperty in contract) {
   4:          largeObject[contract[smallProperty]] = smallObject[smallProperty];
   5:      }
   6:      return largeObject;
   7:  }
   8:  var shapeModelContract = {
   9:      l: "left",
  10:      t: "top"
  11:  };
  12:  myHub.client.setShape = function (shapeModelSmall) {
  13:      var shapeModel = reMap(shapeModelSmall, shapeModelContract);
  14:      // shapeModelSmall has "l" and "t" properties  but after remapping
  15:      // shapeModel now has "left" and "top" properties
  16:  };

Names can be shortened in messages from the client to the server as well, using the same method.

Reducing the memory footprint (that is, the amount of memory used for the message) of the message object can also improve performance. For example, if the full range of an int is not needed, a short or byte can be used instead.

Since messages are stored in the message bus in server memory, reducing the size of messages can also address server memory issues.

Tuning your SignalR server for performance

The following configuration settings can be used to tune your server for better performance in a SignalR application. For general information on how to improve performance in an ASP.NET application, see Improving ASP.NET Performance.

SignalR configuration settings

IIS configuration settings

ASP.NET configuration settings

This section includes configuration settings that can be set in the aspnet.config file. This file is found in one of two locations, depending on platform:

ASP.NET settings that may improve SignalR performance include the following:

Troubleshooting performance issues

This section describes ways to find performance bottlenecks in your application.

Verifying that WebSocket is being used

While SignalR can use a variety of transports for communication between client and server, WebSocket offers a significant performance advantage, and should be used if the client and server support it. To determine if your client and server meet the requirements for WebSocket, see Transports and Fallbacks. To determine what transport is being used in your application, you can use the browser developer tools, and examine the logs to see what transport is being used for the connection. For information on using the browser development tools in Internet Explorer and Chrome, see Transports and Fallbacks.

Using SignalR performance counters

This section describes how to enable and use SignalR performance counters, found in the Microsoft.AspNet.SignalR.Utils package.

Installing signalr.exe

Performance counters can be added to the server using a utility called SignalR.exe. To install this utility, follow these steps:

  1. In your Visual Studio application, select Tools, Library Package Manager, Manage NuGet Packages for Solution…
  2. Search for signalr.utils, and select Install.

  3. Accept the license agreement to install the package.
  4. SignalR.exe will be installed to <project folder>/packages/Microsoft.AspNet.SignalR.Utils.<version>/tools.

Installing performance counters with SignalR.exe

To install SignalR performance counters, run SignalR.exe in an elevated command prompt with the following parameter:

[!code-consoleMain]

   1:  SignalR.exe ipc

To remove SignalR performance counters, run SignalR.exe in an elevated command prompt with the following parameter:

[!code-consoleMain]

   1:  SignalR.exe upc

SignalR Performance counters

The utilities package installs the following performance counters. The “Total” counters measure the number of events since the last application pool or server restart.

Connection metrics

The following metrics measure the connection lifetime events that occur. For more information, see Understanding and Handling Connection Lifetime Events.

Message metrics

The following metrics measure the message traffic generated by SignalR.

Message bus metrics

The following metrics measure traffic through the internal SignalR message bus, the queue in which all incoming and outgoing SignalR messages are placed. A message is Published when it is sent or broadcast. A Subscriber in this context is a subscription on the message bus; this should equal the number of clients plus the server itself. An Allocated Worker is a component that sends data to active connections; a Busy Worker is one that is actively sending a message.

Error metrics

The following metrics measure errors generated by SignalR message traffic. Hub Resolution errors occur when a hub or hub method cannot be resolved. Hub Invocation errors are exceptions thrown while invoking a hub method. Transport errors are connection errors thrown during an HTTP request or response.

Scaleout metrics

The following metrics measure traffic and errors generated by the scaleout provider. A Stream in this context is a scale unit used by the scaleout provider; this is a table if SQL Server is used, a Topic if Service Bus is used, and a Subscription if Redis is used. Each stream ensures ordered read and write operations; a single stream is a potential scale bottleneck, so the number of streams can be increased to help reduce that bottleneck. If multiple streams are used, SignalR will automatically distribute (shard) messages across these streams in a way that ensures messages sent from any given connection are in order.

The MaxQueueLength setting controls the length of the scaleout send queue maintained by SignalR. Setting it to a value greater than 0 will place all messages in a send queue to be sent one at a time to the configured messaging backplane. If the size of the queue goes above the configured length, subsequent calls to send will fail immediately with an InvalidOperationException until the number of messages in the queue is less than the setting again. Queueing is disabled by default because the implemented backplanes generally have their own queuing or flow-control in place. In the case of SQL Server, connection pooling effectively limits the number of sends going on at any one time.

By default, only one stream is used for SQL Server and Redis, five streams are used for Service Bus, and queueing is disabled, but these settings can be changed through configuration on SQL Server and Service Bus:

.NET Server Code for configuring table count and queue length for SQL Server backplane

[!code-csharpMain]

   1:  var connectionString = "(your connection string)";
   2:  var config = new SqlScaleoutConfiguration(connectionString) { 
   3:  TableCount = 3,
   4:  MaxQueueLength = 50 };
   5:  GlobalHost.DependencyResolver.UseSqlServer(config);

.NET Server Code for configuring topic count and queue length for Service Bus backplane

[!code-csharpMain]

   1:  string connectionString = "(your connection string)";
   2:  var config = new ServiceBusScaleoutConfiguration(connectionString, "YourAppName") { 
   3:  TopicCount = 3,
   4:  MaxQueueLength = 50 };
   5:  GlobalHost.DependencyResolver.UseServiceBus(config);

A Buffering stream is one that has entered a faulted state; when the stream is in the faulted state, all messages sent to the backplane will fail immediately until the stream is no longer faulting. The Send Queue Length is the number of messages that have been posted but not yet sent.

For more information on what these counters are measuring, see SignalR Scaleout with Azure Service Bus.

Using other performance counters

The following performance counters may also be useful in monitoring your application’s performance.

Memory

ASP.NET

CPU

TCP/IP

Web Service

Threading

Other Resources

For more information on ASP.NET performance monitoring and tuning, see the following topics:



Comments ( )
Link to this page: //www.vb-net.com/AspNet-DocAndSamples-2017/aspnet/signalr/overview/performance/signalr-performance.htm
< THANKS ME>