Measuring maximum sampling speed.
SSM2 Request Content
|0x00000D||Manifold Absolute Pressure|
→ 4 paramaters, 5 data bytes to request in total
- Reading above five SSM2 addresses using a single ‘A8’ request message in a tight loop.
- There’s no result data processing at all, except response packet validation (header and checksum). Of course this is unrealistic but this is meant for measuring maximum possible sampling speed.
- Messages are being created on the fly by the (rather efficient) library code so they’re not being cached. Not caching the send-message should have negligible effect. Very likely native well optimized C++ code probably won’t be noticeably faster, especially on the slow serial protocol.
- The benchmark program is a console application, preventing any GUI overhead. No progress output or anything within the loop.
- Languages used were both F# and C# running on Linux (Mono 2.8.0) and Windows (Microsoft.NET 4.0)
- Benchmark runtime: 60 seconds for each mode.
- Car engine not running.
- SSM2 via Serial: standard 4800 baud. Request message:
80 10 F0 11 A8 00 00 00 08 00 00 0D 00 00 0E 00 00 0F 00 00 10 7B
- SSM2 via CAN (ISO 15765) : 500 kbit. Request message:
00 00 07 E0 A8 00 00 00 08 00 00 0D 00 00 0E 00 00 0F 00 00 10
Tests were performed on a 2009 Forester 2.0 Turbo Diesel.
OBD-II interface used was Tactrix Openport 2.0 with latest firmware.
|Protocol||Response messages within 60 seconds runtime||Samplerate [samples/second]|
|SSM2 via Serial||313||5.22|
|SSM2 via CAN||5991||99.85|
→ CAN speed improvement = 5991/313 = 19.14 times faster.
Benchmarks written in C# vs. F# and running these on Linux vs. Windows did not make any performance difference which is good. Laptop (medium speed, dual core) never had maximum CPU utilization.
All response messages were valid, there haven’t been any errors as usual.
Benchmark Code F# Version
This is the non-optimized F# version. Results compared to well coded C# showed no performance differences.
Used libraries will be open-sourced in the future. Public APIs need improvement, for F# use cases in particular, we’re just lacking developers to get everything done.
#light open System open System.Collections.Generic open Subaru open Subaru.SSM2 type Benchmark (ipt : J2534.IPassThruV0404, device : Device) = member b.Run(mode : ConnectionMode, secondsToRun : int) = printfn "Benchmark ConnectionMode = %s | secondsToRun = %d" (mode.ToString()) secondsToRun if secondsToRun < 0 || secondsToRun > 3600 then failwith "secondsToRun out of range" let mutable count = 0 use conn = Ssm2Connection.Create(ipt, mode, device) if not (conn.Open()) then failwith "Could not open connection!" else let addresses = [|0x8; 0xD; 0xE; 0xF; 0x10 |] // int array let millisecondsToRun = int64(1000 * secondsToRun) let sw = System.Diagnostics.Stopwatch.StartNew() while sw.ElapsedMilliseconds < millisecondsToRun do addresses |> conn.ReadAddresses |> ignore count <- count + 1 sw.Stop() let sampleRate = float count / (0.001 * float sw.ElapsedMilliseconds) printfn "Elapsed = %s | Count = %d | Samplerate = %f" (sw.Elapsed.ToString()) count sampleRate count do Console.WriteLine("SSM2 Benchmark in F#") let seconds = 60 use passThruDevice = new J2534.Device.OpenPort20Dll() let bm = new Benchmark(passThruDevice, Device.EngineControlUnit) // run shortly to JIT (just-in-time) compile any required code bm.Run(ConnectionMode.SSM2viaSerial, 1) |> ignore bm.Run(ConnectionMode.SSM2viaCAN, 1) |> ignore // now the real tests let countSerial = bm.Run(ConnectionMode.SSM2viaSerial, seconds) let countCan = bm.Run(ConnectionMode.SSM2viaCAN, seconds) let factor = float countCan / float countSerial printfn "CAN/Serial speed factor = %f" factor ()