Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions source/Quantities.Benchmark/Compare/Creation.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
using BenchmarkDotNet.Configs;
using Quantities.Prefixes;
using Quantities.Units.Si;
using Quantities.Units.Si.Metric;

namespace Quantities.Benchmark.Compare;

[MemoryDiagnoser]
[CategoriesColumn]
[GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)]
public class Creation
{
private const String Scalar = nameof(Scalar);
private const String Cubed = nameof(Cubed);
private const String Aliasing = nameof(Aliasing);
private static readonly Double value = Math.E;

[BenchmarkCategory(Scalar), Benchmark(Baseline = true)]
public Length CreateScalarQuantity() => Length.Of(value, Si<Centi, Metre>());

[BenchmarkCategory(Scalar), Benchmark]
public UnitsNet.Length CreateScalarUnitsNet() => UnitsNet.Length.FromCentimeters(value);

[BenchmarkCategory(Cubed), Benchmark(Baseline = true)]
public Volume CreateCubedQuantity() => Volume.Of(value, Cubic(Si<Centi, Metre>()));

[BenchmarkCategory(Cubed), Benchmark]
public UnitsNet.Volume CreateCubedUnitsNet() => UnitsNet.Volume.FromCubicCentimeters(value);

[BenchmarkCategory(Aliasing), Benchmark(Baseline = true)]
public Volume CreateAliasedQuantity() => Volume.Of(value, Metric<Centi, Litre>());

[BenchmarkCategory(Aliasing), Benchmark]
public UnitsNet.Volume CreateAliasedUnitsNet() => UnitsNet.Volume.FromCentiliters(value);
}

/* Summary *

BenchmarkDotNet v0.13.12, Windows 11 (10.0.22631.3007/23H2/2023Update/SunValley3)
12th Gen Intel Core i7-1260P, 1 CPU, 16 logical and 12 physical cores
.NET SDK 8.0.101
[Host] : .NET 8.0.1 (8.0.123.58001), X64 RyuJIT AVX2
DefaultJob : .NET 8.0.1 (8.0.123.58001), X64 RyuJIT AVX2


| Method | Categories | Mean | Error | Ratio | Allocated | Alloc Ratio |
|---------------------- |----------- |----------:|----------:|------:|----------:|------------:|
| CreateAliasedQuantity | Aliasing | 11.847 ns | 0.1295 ns | 1.00 | - | NA |
| CreateAliasedUnitsNet | Aliasing | 3.543 ns | 0.0291 ns | 0.30 | - | NA |
| | | | | | | |
| CreateCubedQuantity | Cubed | 1.576 ns | 0.0293 ns | 1.00 | - | NA |
| CreateCubedUnitsNet | Cubed | 3.562 ns | 0.0355 ns | 2.26 | - | NA |
| | | | | | | |
| CreateScalarQuantity | Scalar | 1.349 ns | 0.0181 ns | 1.00 | - | NA |
| CreateScalarUnitsNet | Scalar | 2.943 ns | 0.0353 ns | 2.18 | - | NA |
*/
37 changes: 37 additions & 0 deletions source/Quantities.Benchmark/Compare/Division.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using Quantities.Prefixes;
using Quantities.Units.Imperial.Length;
using Quantities.Units.Si.Metric;
using nLength = UnitsNet.Length;
using nVolume = UnitsNet.Volume;

namespace Quantities.Benchmark.Compare;

[MemoryDiagnoser]
public class Division
{
private static readonly Volume left = Volume.Of(32, Metric<Centi, Litre>());
private static readonly Length right = Length.Of(4, Imperial<Foot>());
private static readonly nVolume nLeft = nVolume.FromCentiliters(32);
private static readonly nLength nRight = nLength.FromFeet(4);

[Benchmark(Baseline = true)]
public Area Quantity() => left / right;

[Benchmark]
public UnitsNet.Area UnitsNet() => nLeft / nRight;
}

/* Summary *

BenchmarkDotNet v0.13.12, Windows 11 (10.0.22631.3007/23H2/2023Update/SunValley3)
12th Gen Intel Core i7-1260P, 1 CPU, 16 logical and 12 physical cores
.NET SDK 8.0.101
[Host] : .NET 8.0.1 (8.0.123.58001), X64 RyuJIT AVX2
DefaultJob : .NET 8.0.1 (8.0.123.58001), X64 RyuJIT AVX2


| Method | Mean | Error | Ratio | Allocated | Alloc Ratio |
|--------- |----------:|----------:|------:|----------:|------------:|
| Quantity | 6.624 ns | 0.0736 ns | 1.00 | - | NA |
| UnitsNet | 24.402 ns | 0.1962 ns | 3.68 | - | NA |
*/
37 changes: 37 additions & 0 deletions source/Quantities.Benchmark/Compare/Multiplication.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using Quantities.Prefixes;
using Quantities.Units.Imperial.Length;
using Quantities.Units.Si;

using nLength = UnitsNet.Length;

namespace Quantities.Benchmark.Compare;

[MemoryDiagnoser]
public class Multiplication
{
private static readonly Length left = Length.Of(3, Si<Milli, Metre>());
private static readonly Length right = Length.Of(4, Imperial<Foot>());
private static readonly nLength nLeft = nLength.FromMillimeters(3);
private static readonly nLength nRight = nLength.FromMillimeters(4);

[Benchmark(Baseline = true)]
public Area Quantity() => left * right;

[Benchmark]
public UnitsNet.Area UnitsNet() => nLeft * nRight;
}

/* Summary *

BenchmarkDotNet v0.13.12, Windows 11 (10.0.22631.3007/23H2/2023Update/SunValley3)
12th Gen Intel Core i7-1260P, 1 CPU, 16 logical and 12 physical cores
.NET SDK 8.0.101
[Host] : .NET 8.0.1 (8.0.123.58001), X64 RyuJIT AVX2
DefaultJob : .NET 8.0.1 (8.0.123.58001), X64 RyuJIT AVX2


| Method | Mean | Error | Ratio | Allocated | Alloc Ratio |
|--------- |----------:|----------:|------:|----------:|------------:|
| Quantity | 6.646 ns | 0.0605 ns | 1.00 | - | NA |
| UnitsNet | 21.431 ns | 0.1119 ns | 3.22 | - | NA |
*/
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using BenchmarkDotNet.Configs;
using Quantities.Prefixes;
using Quantities.Units.Imperial.Length;
using Quantities.Units.Si;
using UnitsNet.Units;
using nLength = UnitsNet.Length;

namespace Quantities.Benchmark.Compare;

[MemoryDiagnoser(displayGenColumns: false)]
[GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)]
public class QuantityConversionComparison
{
private const String ToSi = nameof(ToSi);
private const String ToImperial = nameof(ToImperial);
private const String ToSame = nameof(ToSame);
private static readonly Length si = Length.Of(3, Si<Milli, Metre>());
private static readonly Length imperial = Length.Of(4, Imperial<Foot>());
private static readonly nLength nSi = nLength.FromMillimeters(3);
private static readonly nLength nImperial = nLength.FromFeet(4);

[BenchmarkCategory(ToSi), Benchmark(Baseline = true)]
public Length QuantityToSi() => imperial.To(Si<Milli, Metre>());
[BenchmarkCategory(ToSi), Benchmark]
public nLength UnitsNetToSi() => nImperial.ToUnit(LengthUnit.Millimeter);

[BenchmarkCategory(ToImperial), Benchmark(Baseline = true)]
public Length QuantityToImperial() => si.To(Imperial<Foot>());
[BenchmarkCategory(ToImperial), Benchmark]
public nLength UnitsNetToImperial() => nSi.ToUnit(LengthUnit.Foot);

[BenchmarkCategory(ToSame), Benchmark(Baseline = true)]
public Length QuantityToSame() => imperial.To(Imperial<Foot>());
[BenchmarkCategory(ToSame), Benchmark]
public nLength UnitsNetToSame() => nImperial.ToUnit(LengthUnit.Foot);
}

/* Summary *

BenchmarkDotNet v0.13.12, Windows 11 (10.0.22631.3007/23H2/2023Update/SunValley3)
12th Gen Intel Core i7-1260P, 1 CPU, 16 logical and 12 physical cores
.NET SDK 8.0.101
[Host] : .NET 8.0.1 (8.0.123.58001), X64 RyuJIT AVX2
DefaultJob : .NET 8.0.1 (8.0.123.58001), X64 RyuJIT AVX2


| Method | Mean | Error | Ratio | Allocated | Alloc Ratio |
|------------------- |----------:|----------:|------:|----------:|------------:|
| QuantityToImperial | 1.925 ns | 0.0554 ns | 1.00 | - | NA |
| UnitsNetToImperial | 36.503 ns | 0.5333 ns | 18.94 | 48 B | NA |
| | | | | | |
| QuantityToSame | 1.924 ns | 0.0620 ns | 1.00 | - | NA |
| UnitsNetToSame | 11.712 ns | 0.0609 ns | 5.76 | - | NA |
| | | | | | |
| QuantityToSi | 1.946 ns | 0.0489 ns | 1.00 | - | NA |
| UnitsNetToSi | 38.461 ns | 0.4820 ns | 19.77 | 48 B | NA |
*/
56 changes: 56 additions & 0 deletions source/Quantities.Benchmark/Compare/ValueConversionComparison.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
using BenchmarkDotNet.Configs;
using Quantities.Prefixes;
using Quantities.Units.Imperial.Length;
using Quantities.Units.Si;
using nLength = UnitsNet.Length;

namespace Quantities.Benchmark.Compare;

[MemoryDiagnoser(displayGenColumns: false)]
[GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)]
public class ValueConversionComparison
{
private const String ToSi = nameof(ToSi);
private const String ToImperial = nameof(ToImperial);
private const String ToSame = nameof(ToSame);
private static readonly Length si = Length.Of(3, Si<Milli, Metre>());
private static readonly Length imperial = Length.Of(4, Imperial<Foot>());
private static readonly nLength nSi = nLength.FromMillimeters(3);
private static readonly nLength nImperial = nLength.FromFeet(4);

[BenchmarkCategory(ToSi), Benchmark(Baseline = true)]
public Double QuantityToSi() => imperial.To(Si<Milli, Metre>());
[BenchmarkCategory(ToSi), Benchmark]
public Double UnitsNetToSi() => nImperial.Millimeters;

[BenchmarkCategory(ToImperial), Benchmark(Baseline = true)]
public Double QuantityToImperial() => si.To(Imperial<Foot>());
[BenchmarkCategory(ToImperial), Benchmark]
public Double UnitsNetToImperial() => nSi.Feet;

[BenchmarkCategory(ToSame), Benchmark(Baseline = true)]
public Double QuantityToSame() => imperial.To(Imperial<Foot>());
[BenchmarkCategory(ToSame), Benchmark]
public Double UnitsNetToSame() => nImperial.Feet;
}

/* Summary *

BenchmarkDotNet v0.13.12, Windows 11 (10.0.22631.3007/23H2/2023Update/SunValley3)
12th Gen Intel Core i7-1260P, 1 CPU, 16 logical and 12 physical cores
.NET SDK 8.0.101
[Host] : .NET 8.0.1 (8.0.123.58001), X64 RyuJIT AVX2
DefaultJob : .NET 8.0.1 (8.0.123.58001), X64 RyuJIT AVX2


| Method | Mean | Error | Ratio | Allocated | Alloc Ratio |
|------------------- |-----------:|----------:|------:|----------:|------------:|
| QuantityToImperial | 0.7591 ns | 0.0442 ns | 1.00 | - | NA |
| UnitsNetToImperial | 39.1487 ns | 0.4276 ns | 51.91 | 48 B | NA |
| | | | | | |
| QuantityToSame | 0.3554 ns | 0.0148 ns | 1.00 | - | NA |
| UnitsNetToSame | 0.1525 ns | 0.0145 ns | 0.43 | - | NA |
| | | | | | |
| QuantityToSi | 0.7803 ns | 0.0433 ns | 1.00 | - | NA |
| UnitsNetToSi | 39.7448 ns | 0.3878 ns | 51.33 | 48 B | NA |
*/
1 change: 1 addition & 0 deletions source/Quantities.Benchmark/Quantities.Benchmark.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="UnitsNet" Version="5.43.0" />
<PackageReference Include="BenchmarkDotNet" Version="0.13.12" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
using UnitsNet;
using Quantities.Units.Si.Metric;
using Quantities.Units.Si.Metric.UnitsOfInformation;
using Quantities.Units.Si.Derived;
using Quantities.Units.Imperial.Temperature;
using Quantities.Units.NonStandard.Temperature;

using nLength = UnitsNet.Length;
using nTemperature = UnitsNet.Temperature;
using Bytes = Quantities.Units.Si.Metric.UnitsOfInformation.Byte;

namespace Quantities.Test.Compare;

public class QuantitiesAndUnitsNetAreEquallyAccurate
{
[Fact]
public void ÅngströmToNanoMetre()
{
const Double expectedNanoMetre = 1d;

// Quantities
Length ångström = Length.Of(10, Metric<Ångström>());
Length nanoMetres = ångström.To(Si<Nano, Metre>());

// UnitsNet
nLength nÅngström = nLength.FromAngstroms(10);
nLength nNanoMetre = nÅngström.ToUnit(UnitsNet.Units.LengthUnit.Nanometer);

// Equally precise
Assert.Equal(expectedNanoMetre, nanoMetres);
Assert.Equal(expectedNanoMetre, nNanoMetre.Value);
}

[Fact]
public void GibiBitPerHourToKiloBytePerMinute()
{
const Double expectedRate = 1024d * 1024d * 1024d / 1000d;

// Quantities
DataRate speed = DataRate.Of(8, Binary<Gibi, Bit>().Per(Si<Second>()));
DataRate actual = speed.To(Metric<Kilo, Bytes>().Per(Si<Second>()));

// UnitsNet
BitRate nSpeed = BitRate.FromGibibitsPerSecond(8);
BitRate nActual = nSpeed.ToUnit(UnitsNet.Units.BitRateUnit.KilobytePerSecond);

// Equally precise
Assert.Equal(expectedRate, actual);
Assert.Equal(expectedRate, (Double)nActual.Value); // but Value is a Decimal here :-/
}

[Fact]
public void CelsiusToFahrenheit()
{
const Double expectedFahrenheit = 98.6;

// Quantities
Temperature temperature = Temperature.Of(37.0, Metric<Celsius>());
Temperature actual = temperature.To(Imperial<Fahrenheit>());

// UnitsNet
nTemperature nTemperature = nTemperature.FromDegreesCelsius(37.0);
nTemperature nActual = nTemperature.ToUnit(UnitsNet.Units.TemperatureUnit.DegreeFahrenheit);

// Equally precise :-)
Assert.Equal(expectedFahrenheit, actual);
Assert.Equal(expectedFahrenheit, nActual.Value);
}

[Fact]
public void KelvinToRømer()
{
const Double expectedRømer = -1.8345; // calculated using full precision math.

// Quantities
Temperature temperature = Temperature.Of(255.37, Si<Kelvin>());
Temperature actual = temperature.To(NonStandard<Rømer>());

// UnitsNet
nTemperature nTemperature = nTemperature.FromKelvins(255.37);
nTemperature nActual = nTemperature.ToUnit(UnitsNet.Units.TemperatureUnit.DegreeRoemer);

// Quantities and UnitsNet are equally bad (measured by precision parameter only)
Assert.Equal(expectedRømer, actual, 13); // -1.8344999999999885
Assert.Equal(expectedRømer, nActual.Value, 13); // -1.83449999999999
}
}
Loading