51Degrees Device Detection .NET  4.4

Device detection services for 51Degrees Pipeline


This example shows how to change the performance profile when creating a 51Degrees device detection engine. It also includes a simple method of benchmarking the engine that can illustrate the performance differences. Note that benchmarking is a complex area and this is not a sophisticated solution. It is simply intended to demonstrate the approximate, relative performance of the pre-configured profiles.

This example is available in full on GitHub.

This example requires a local data file. The free 'Lite' data file can be acquired by pulling the git submodules under this repository (run `git submodule update --recursive`) or from the device-detection-data GitHub repository.

The Lite data file is only used for illustration, and has limited accuracy and capabilities. Find out about the more capable data files that are available on our pricing page

Required NuGet Dependencies:

/* *********************************************************************
* This Original Work is copyright of 51 Degrees Mobile Experts Limited.
* Copyright 2019 51 Degrees Mobile Experts Limited, 5 Charlotte Close,
* Caversham, Reading, Berkshire, United Kingdom RG4 7BY.
* This Original Work is licensed under the European Union Public Licence (EUPL)
* v.1.2 and is subject to its terms as set out below.
* If a copy of the EUPL was not distributed with this file, You can obtain
* one at https://opensource.org/licenses/EUPL-1.2.
* The 'Compatible Licences' set out in the Appendix to the EUPL (as may be
* amended by the European Commission) shall be deemed incompatible for
* the purposes of the Work and the provisions of the compatibility
* clause in Article 5 of the EUPL shall not apply.
* If using the Work as, or as part of, a network application, by
* including the attribution notice(s) required under Article 5 of the EUPL
* in the end user terms of the application under an appropriate heading,
* such notice(s) shall fulfill the requirements of that article.
* ********************************************************************* */
using FiftyOne.Pipeline.Core.FlowElements;
using FiftyOne.Pipeline.Engines;
using FiftyOne.Pipeline.Engines.FiftyOne.Data;
using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
public class Program
public class Example : ExampleBase
public void Run(string dataFile, string uaFile, int count)
FileInfo f = new FileInfo(dataFile);
Console.WriteLine($"Using data file at '{f.FullName}'");
// Build a pipeline containing a Device Detection Hash engine
// using the Device Detection Pipeline Builder.
using (var pipeline = new DeviceDetectionPipelineBuilder()
.UseOnPremise(dataFile, null, false)
// Prefer maximum performance profile where all data loaded
// into memory. Experiment with other profiles.
Run(uaFile, count, pipeline);
private static void Run(
string uaFile,
int count,
IPipeline pipeline)
var isMobileTrue = 0;
var isMobileFalse = 0;
var isMobileUnknown = 0;
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
int maxDistinctUAs = 1000;
var starts = DateTime.UtcNow;
Console.WriteLine($"Processing {count} User-Agents from {uaFile}");
Console.WriteLine($"The {count} process calls will use a " +
$"maximum of {maxDistinctUAs} distinct User-Agents");
// Start multiple threads to process a set of User - Agents, making a note of
// the time at which processing was started.
Parallel.ForEach(Report(GetUserAgents(uaFile, count).ToList(), count, maxDistinctUAs, 40),
new ParallelOptions()
//MaxDegreeOfParallelism = 1,
CancellationToken = cancellationTokenSource.Token
userAgent =>
// Create a new flow data to add evidence to and get
// device data back again.
using (var data = pipeline.CreateFlowData())
// Add the User-Agent as evidence to the flow data.
data.AddEvidence("header.User-Agent", userAgent)
// Get the device from the engine.
var device = data.Get<IDeviceData>();
// Update the counters depending on the IsMobile
// result.
var isMobile = device.IsMobile;
if (isMobile.HasValue)
if (isMobile.Value)
Interlocked.Increment(ref isMobileTrue);
Interlocked.Increment(ref isMobileFalse);
Interlocked.Increment(ref isMobileUnknown);
// Wait for all processing to finish, and make a note of the time elapsed
// since the processing was started.
var time = DateTime.UtcNow - starts;
// Output the average time to process a single User-Agent.
Console.WriteLine($"Average {(double)time.TotalMilliseconds / (double)count} ms per User-Agent");
Console.WriteLine($"IsMobile = True : {isMobileTrue}");
Console.WriteLine($"IsMobile = False : {isMobileFalse}");
Console.WriteLine($"IsMobile = Unknown : {isMobileUnknown}");
catch (OperationCanceledException) { }
static void Main(string[] args)
var filename = "51Degrees-LiteV4.1.hash";
var uaFilename = "20000 User Agents.csv";
var dataFile = args.Length > 0 ? args[0] : ExampleUtils.FindFile(filename);
var uaFile = args.Length > 1 ? args[1] : ExampleUtils.FindFile(uaFilename);
new Example().Run(dataFile, uaFile, 10000);
#if (DEBUG)
Console.WriteLine("Complete. Press key to exit.");