Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enum boxing optimizations (UnitKey) #1507

Open
wants to merge 6 commits into
base: release/v6
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
1 change: 1 addition & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="System.Runtime.CompilerServices.Unsafe" Version="6.1.0" />
<PackageVersion Include="BenchmarkDotNet" Version="0.14.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
Expand Down
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before:

Method Job Runtime NbAbbreviations Mean Error StdDev Ratio RatioSD Gen0 Gen1 Allocated Alloc Ratio
FromMassString .NET 8.0 .NET 8.0 1000 29.54 ms 0.443 ms 0.415 ms 1.00 0.02 2833.3333 - 47.57 MB 1.00
FromVolumeUnitAbbreviation .NET 8.0 .NET 8.0 1000 66.68 ms 1.132 ms 1.004 ms 2.26 0.04 5750.0000 500.0000 93.34 MB 1.96
FromPressureUnitAbbreviation .NET 8.0 .NET 8.0 1000 69.09 ms 1.319 ms 1.234 ms 2.34 0.05 6000.0000 333.3333 100.31 MB 2.11
FromVolumeFlowUnitAbbreviation .NET 8.0 .NET 8.0 1000 133.05 ms 2.236 ms 2.092 ms 4.51 0.09 12000.0000 1000.0000 200.47 MB 4.21
                         
FromMassString .NET Framework 4.8 .NET Framework 4.8 1000 65.22 ms 0.542 ms 0.507 ms 1.00 0.01 13000.0000 500.0000 78.08 MB 1.00
FromVolumeUnitAbbreviation .NET Framework 4.8 .NET Framework 4.8 1000 135.02 ms 1.001 ms 0.937 ms 2.07 0.02 25250.0000 1500.0000 152.05 MB 1.95
FromPressureUnitAbbreviation .NET Framework 4.8 .NET Framework 4.8 1000 123.84 ms 1.260 ms 1.117 ms 1.90 0.02 23000.0000 1250.0000 139.26 MB 1.78
FromVolumeFlowUnitAbbreviation .NET Framework 4.8 .NET Framework 4.8 1000 211.69 ms 2.007 ms 1.779 ms 3.25 0.04 44333.3333 5000.0000 267.62 MB 3.43

After:

Method Job Runtime NbAbbreviations Mean Error StdDev Ratio RatioSD Gen0 Gen1 Allocated Alloc Ratio
FromMassString .NET 8.0 .NET 8.0 1000 19.25 ms 0.364 ms 0.341 ms 1.00 0.02 2406.2500 93.7500 38.85 MB 1.00
FromVolumeUnitAbbreviation .NET 8.0 .NET 8.0 1000 42.83 ms 0.779 ms 0.691 ms 2.22 0.05 4800.0000 400.0000 77.39 MB 1.99
FromPressureUnitAbbreviation .NET 8.0 .NET 8.0 1000 47.75 ms 0.742 ms 0.694 ms 2.48 0.05 5250.0000 500.0000 85.49 MB 2.20
FromVolumeFlowUnitAbbreviation .NET 8.0 .NET 8.0 1000 92.35 ms 1.824 ms 1.873 ms 4.80 0.12 10500.0000 1500.0000 174 MB 4.48
                         
FromMassString .NET Framework 4.8 .NET Framework 4.8 1000 29.24 ms 0.142 ms 0.119 ms 1.00 0.01 10031.2500 437.5000 60.37 MB 1.00
FromVolumeUnitAbbreviation .NET Framework 4.8 .NET Framework 4.8 1000 59.12 ms 0.530 ms 0.470 ms 2.02 0.02 19555.5556 1333.3333 117.49 MB 1.95
FromPressureUnitAbbreviation .NET Framework 4.8 .NET Framework 4.8 1000 54.80 ms 0.732 ms 0.685 ms 1.87 0.02 17555.5556 1111.1111 105.38 MB 1.75
FromVolumeFlowUnitAbbreviation .NET Framework 4.8 .NET Framework 4.8 1000 98.17 ms 0.625 ms 0.554 ms 3.36 0.02 35000.0000 4333.3333 211.02 MB 3.50

Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
using System;
using System.Globalization;
using System.Linq;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using UnitsNet.Units;

namespace UnitsNet.Benchmark.Conversions.FromString;

[MemoryDiagnoser]
[SimpleJob(RuntimeMoniker.Net48)]
[SimpleJob(RuntimeMoniker.Net80)]
public class QuantityFromStringBenchmarks
{
private static readonly CultureInfo Culture = CultureInfo.InvariantCulture;
private static readonly string ValueToParse = 123.456.ToString(Culture);

private readonly Random _random = new(42);
private string[] _quantitiesToParse;

[Params(1000)]
public int NbAbbreviations { get; set; }

[GlobalSetup(Target = nameof(FromMassString))]
public void PrepareMassStrings()
{
// can't have "mg" or "g" (see Acceleration.StandardGravity) and who knows what more...
_quantitiesToParse = _random.GetItems(["kg", "lbs", "Mlbs"], NbAbbreviations).Select(abbreviation => $"{ValueToParse} {abbreviation}").ToArray();
}

[GlobalSetup(Target = nameof(FromVolumeUnitAbbreviation))]
public void PrepareVolumeStrings()
{
_quantitiesToParse = _random.GetItems(["ml", "l", "cm³", "m³"], NbAbbreviations).Select(abbreviation => $"{ValueToParse} {abbreviation}").ToArray();;
}

[GlobalSetup(Target = nameof(FromPressureUnitAbbreviation))]
public void PreparePressureUnits()
{
_quantitiesToParse = _random.GetRandomAbbreviations<PressureUnit>(UnitsNetSetup.Default.UnitAbbreviations, NbAbbreviations).Select(abbreviation => $"{ValueToParse} {abbreviation}").ToArray();;
}

[GlobalSetup(Target = nameof(FromVolumeFlowUnitAbbreviation))]
public void PrepareVolumeFlowUnits()
{
// can't have "bpm" (see Frequency)
_quantitiesToParse =
_random.GetItems(
UnitsNetSetup.Default.UnitAbbreviations.GetAllUnitAbbreviationsForQuantity(typeof(VolumeFlowUnit)).Where(x => x != "bpm").ToArray(),
NbAbbreviations).Select(abbreviation => $"{ValueToParse} {abbreviation}").ToArray();
}

[Benchmark(Baseline = true)]
public IQuantity FromMassString()
{
IQuantity quantity = null;
foreach (var quantityString in _quantitiesToParse)
{
quantity = Quantity.Parse(Culture, typeof(Mass), quantityString);
}

return quantity;
}

[Benchmark(Baseline = false)]
public IQuantity FromVolumeUnitAbbreviation()
{
IQuantity quantity = null;
foreach (var quantityString in _quantitiesToParse)
{
quantity = Quantity.Parse(Culture, typeof(Volume), quantityString);
}

return quantity;
}

[Benchmark(Baseline = false)]
public IQuantity FromPressureUnitAbbreviation()
{
IQuantity quantity = null;
foreach (var quantityString in _quantitiesToParse)
{
quantity = Quantity.Parse(Culture, typeof(Pressure), quantityString);
}

return quantity;
}

[Benchmark(Baseline = false)]
public IQuantity FromVolumeFlowUnitAbbreviation()
{
IQuantity quantity = null;
foreach (var quantityString in _quantitiesToParse)
{
quantity = Quantity.Parse(Culture, typeof(VolumeFlow), quantityString);
}

return quantity;
}
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before:

Method Job Runtime NbAbbreviations Mean Error StdDev Ratio RatioSD Gen0 Allocated Alloc Ratio
FromMassUnitAbbreviation .NET 8.0 .NET 8.0 1000 482.2 ms 4.45 ms 4.16 ms 1.00 0.01 28000.0000 450.85 MB 1.00
FromVolumeUnitAbbreviation .NET 8.0 .NET 8.0 1000 476.1 ms 8.37 ms 7.83 ms 0.99 0.02 28000.0000 450.85 MB 1.00
FromPressureUnitAbbreviation .NET 8.0 .NET 8.0 1000 480.2 ms 8.78 ms 8.21 ms 1.00 0.02 28000.0000 450.85 MB 1.00
FromVolumeFlowUnitAbbreviation .NET 8.0 .NET 8.0 1000 479.6 ms 3.31 ms 3.10 ms 0.99 0.01 28000.0000 450.85 MB 1.00
                       
FromMassUnitAbbreviation .NET Framework 4.8 .NET Framework 4.8 1000 1,391.4 ms 2.97 ms 2.78 ms 1.00 0.00 129000.0000 779.46 MB 1.00
FromVolumeUnitAbbreviation .NET Framework 4.8 .NET Framework 4.8 1000 1,392.8 ms 2.08 ms 1.84 ms 1.00 0.00 129000.0000 779.46 MB 1.00
FromPressureUnitAbbreviation .NET Framework 4.8 .NET Framework 4.8 1000 1,397.4 ms 3.15 ms 2.95 ms 1.00 0.00 129000.0000 779.46 MB 1.00
FromVolumeFlowUnitAbbreviation .NET Framework 4.8 .NET Framework 4.8 1000 1,406.1 ms 3.66 ms 3.42 ms 1.01 0.00 129000.0000 779.46 MB 1.00

After:

Method Job Runtime NbAbbreviations Mean Error StdDev Ratio RatioSD Gen0 Allocated Alloc Ratio
FromMassUnitAbbreviation .NET 8.0 .NET 8.0 1000 104.8 ms 1.00 ms 0.94 ms 1.00 0.01 14400.0000 230.67 MB 1.00
FromVolumeUnitAbbreviation .NET 8.0 .NET 8.0 1000 104.1 ms 2.03 ms 2.25 ms 0.99 0.02 14400.0000 230.67 MB 1.00
FromPressureUnitAbbreviation .NET 8.0 .NET 8.0 1000 103.6 ms 2.01 ms 2.15 ms 0.99 0.02 14400.0000 230.67 MB 1.00
FromVolumeFlowUnitAbbreviation .NET 8.0 .NET 8.0 1000 103.4 ms 1.08 ms 0.95 ms 0.99 0.01 14400.0000 230.67 MB 1.00
                       
FromMassUnitAbbreviation .NET Framework 4.8 .NET Framework 4.8 1000 199.5 ms 2.17 ms 2.03 ms 1.00 0.01 38333.3333 231.69 MB 1.00
FromVolumeUnitAbbreviation .NET Framework 4.8 .NET Framework 4.8 1000 200.9 ms 2.26 ms 2.11 ms 1.01 0.01 38333.3333 231.69 MB 1.00
FromPressureUnitAbbreviation .NET Framework 4.8 .NET Framework 4.8 1000 201.6 ms 1.68 ms 1.49 ms 1.01 0.01 38333.3333 231.69 MB 1.00
FromVolumeFlowUnitAbbreviation .NET Framework 4.8 .NET Framework 4.8 1000 199.3 ms 2.26 ms 2.12 ms 1.00 0.01 38333.3333 231.69 MB 1.00

Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
using System;
using System.Globalization;
using System.Linq;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using UnitsNet.Units;

namespace UnitsNet.Benchmark.Conversions.FromString;

[MemoryDiagnoser]
[SimpleJob(RuntimeMoniker.Net48)]
[SimpleJob(RuntimeMoniker.Net80)]
public class QuantityFromUnitAbbreviationBenchmarks
{
private static readonly CultureInfo Culture = CultureInfo.InvariantCulture;
private readonly Random _random = new(42);
private string[] _massUnits;
private string[] _pressureUnits;
private string[] _volumeFlowUnits;
private string[] _volumeUnits = [];

[Params(1000)]
public int NbAbbreviations { get; set; }

[GlobalSetup(Target = nameof(FromMassUnitAbbreviation))]
public void PrepareMassUnits()
{
// can't have "mg" or "g" (see Acceleration.StandardGravity) and who knows what more...
_massUnits = _random.GetItems(["kg", "lbs", "Mlbs"], NbAbbreviations);
}

[GlobalSetup(Target = nameof(FromVolumeUnitAbbreviation))]
public void PrepareVolumeUnits()
{
_volumeUnits = _random.GetItems(["ml", "l", "cm³", "m³"], NbAbbreviations);
}

[GlobalSetup(Target = nameof(FromPressureUnitAbbreviation))]
public void PreparePressureUnits()
{
_pressureUnits = _random.GetRandomAbbreviations<PressureUnit>(UnitsNetSetup.Default.UnitAbbreviations, NbAbbreviations);
}

[GlobalSetup(Target = nameof(FromVolumeFlowUnitAbbreviation))]
public void PrepareVolumeFlowUnits()
{
// can't have "bpm" (see Frequency)
_volumeFlowUnits =
_random.GetItems(
UnitsNetSetup.Default.UnitAbbreviations.GetAllUnitAbbreviationsForQuantity(typeof(VolumeFlowUnit)).Where(x => x != "bpm").ToArray(),
NbAbbreviations);
}

[Benchmark(Baseline = true)]
public IQuantity FromMassUnitAbbreviation()
{
IQuantity quantity = null;
foreach (var unitToParse in _massUnits)
{
quantity = Quantity.FromUnitAbbreviation(Culture, 1, unitToParse);
}

return quantity;
}

[Benchmark(Baseline = false)]
public IQuantity FromVolumeUnitAbbreviation()
{
IQuantity quantity = null;
foreach (var unitToParse in _volumeUnits)
{
quantity = Quantity.FromUnitAbbreviation(Culture, 1, unitToParse);
}

return quantity;
}

[Benchmark(Baseline = false)]
public IQuantity FromPressureUnitAbbreviation()
{
IQuantity quantity = null;
foreach (var unitToParse in _pressureUnits)
{
quantity = Quantity.FromUnitAbbreviation(Culture, 1, unitToParse);
}

return quantity;
}

[Benchmark(Baseline = false)]
public IQuantity FromVolumeFlowUnitAbbreviation()
{
IQuantity quantity = null;
foreach (var unitToParse in _volumeFlowUnits)
{
quantity = Quantity.FromUnitAbbreviation(Culture, 1, unitToParse);
}

return quantity;
}
}
Copy link
Collaborator Author

@lipchev lipchev Jan 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before:

Method Job Runtime NbAbbreviations Mean Error StdDev Ratio RatioSD Gen0 Gen1 Allocated Alloc Ratio
FromMassUnitName .NET 8.0 .NET 8.0 1000 453.0 μs 8.92 μs 9.55 μs 1.00 0.03 31.7383 - 523.49 KB 1.00
FromVolumeUnitAbbreviation .NET 8.0 .NET 8.0 1000 715.0 μs 2.71 μs 2.40 μs 1.58 0.03 44.9219 - 734.53 KB 1.40
FromPressureUnitAbbreviation .NET 8.0 .NET 8.0 1000 601.0 μs 3.31 μs 2.93 μs 1.33 0.03 41.9922 - 695.47 KB 1.33
FromVolumeFlowUnitAbbreviation .NET 8.0 .NET 8.0 1000 825.9 μs 13.83 μs 12.26 μs 1.82 0.05 54.6875 0.9766 898.74 KB 1.72
                         
FromMassUnitName .NET Framework 4.8 .NET Framework 4.8 1000 779.2 μs 4.34 μs 4.06 μs 1.00 0.01 103.5156 - 638.86 KB 1.00
FromVolumeUnitAbbreviation .NET Framework 4.8 .NET Framework 4.8 1000 1,257.2 μs 11.20 μs 10.47 μs 1.61 0.02 138.6719 - 861.88 KB 1.35
FromPressureUnitAbbreviation .NET Framework 4.8 .NET Framework 4.8 1000 1,044.7 μs 13.83 μs 12.93 μs 1.34 0.02 136.7188 - 846.97 KB 1.33
FromVolumeFlowUnitAbbreviation .NET Framework 4.8 .NET Framework 4.8 1000 1,446.6 μs 17.30 μs 16.18 μs 1.86 0.02 169.9219 - 1049.27 KB 1.64

After:

Method Job Runtime NbAbbreviations Mean Error StdDev Ratio RatioSD Gen0 Allocated Alloc Ratio
FromMassUnitName .NET 8.0 .NET 8.0 1000 124.5 μs 0.94 μs 0.88 μs 1.00 0.01 9.0332 148.44 KB 1.00
FromVolumeUnitName .NET 8.0 .NET 8.0 1000 186.9 μs 1.44 μs 1.35 μs 1.50 0.01 9.0332 148.44 KB 1.00
FromPressureUnitName .NET 8.0 .NET 8.0 1000 156.0 μs 1.22 μs 1.14 μs 1.25 0.01 9.0332 148.44 KB 1.00
FromVolumeFlowUnitName .NET 8.0 .NET 8.0 1000 215.1 μs 1.16 μs 1.08 μs 1.73 0.01 9.0332 148.44 KB 1.00
                       
FromMassUnitName .NET Framework 4.8 .NET Framework 4.8 1000 190.1 μs 1.67 μs 1.56 μs 1.00 0.01 24.1699 148.88 KB 1.00
FromVolumeUnitName .NET Framework 4.8 .NET Framework 4.8 1000 272.5 μs 2.01 μs 1.68 μs 1.43 0.01 23.9258 148.88 KB 1.00
FromPressureUnitName .NET Framework 4.8 .NET Framework 4.8 1000 247.6 μs 2.30 μs 1.92 μs 1.30 0.01 23.9258 148.88 KB 1.00
FromVolumeFlowUnitName .NET Framework 4.8 .NET Framework 4.8 1000 343.3 μs 1.85 μs 1.64 μs 1.81 0.02 23.9258 148.88 KB 1.00

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...must have missed to rename some of these methods..

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in 03973bf

Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
using System;
using System.Linq;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;

namespace UnitsNet.Benchmark.Conversions.FromString;

[MemoryDiagnoser]
[SimpleJob(RuntimeMoniker.Net48)]
[SimpleJob(RuntimeMoniker.Net80)]
public class QuantityFromUnitNameBenchmarks
{
private readonly Random _random = new(42);
private string[] _unitNames;

[Params(1000)]
public int NbAbbreviations { get; set; }

[GlobalSetup(Target = nameof(FromMassUnitName))]
public void PrepareMassUnits()
{
_unitNames = _random.GetItems(Mass.Info.UnitInfos.Select(x => x.Name).ToArray(), NbAbbreviations);
}

[GlobalSetup(Target = nameof(FromVolumeUnitAbbreviation))]
public void PrepareVolumeUnits()
{
_unitNames = _random.GetItems(Volume.Info.UnitInfos.Select(x => x.Name).ToArray(), NbAbbreviations);
}

[GlobalSetup(Target = nameof(FromPressureUnitAbbreviation))]
public void PreparePressureUnits()
{
_unitNames = _random.GetItems(Pressure.Info.UnitInfos.Select(x => x.Name).ToArray(), NbAbbreviations);
}

[GlobalSetup(Target = nameof(FromVolumeFlowUnitAbbreviation))]
public void PrepareVolumeFlowUnits()
{
_unitNames = _random.GetItems(VolumeFlow.Info.UnitInfos.Select(x => x.Name).ToArray(), NbAbbreviations);
}

[Benchmark(Baseline = true)]
public IQuantity FromMassUnitName()
{
IQuantity quantity = null;
foreach (var unitName in _unitNames)
{
quantity = Quantity.From(1, nameof(Mass), unitName);
}

return quantity;
}

[Benchmark(Baseline = false)]
public IQuantity FromVolumeUnitAbbreviation()
{
IQuantity quantity = null;
foreach (var unitName in _unitNames)
{
quantity = Quantity.From(1, nameof(Volume), unitName);
}

return quantity;
}

[Benchmark(Baseline = false)]
public IQuantity FromPressureUnitAbbreviation()
{
IQuantity quantity = null;
foreach (var unitName in _unitNames)
{
quantity = Quantity.From(1, nameof(Pressure), unitName);
}

return quantity;
}

[Benchmark(Baseline = false)]
public IQuantity FromVolumeFlowUnitAbbreviation()
{
IQuantity quantity = null;
foreach (var unitName in _unitNames)
{
quantity = Quantity.From(1, nameof(VolumeFlow), unitName);
}

return quantity;
}
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before:

Method Job Runtime NbConversions Format Mean Error StdDev Ratio RatioSD Gen0 Allocated Alloc Ratio
MassToUnit .NET 8.0 .NET 8.0 1000 A 218.4 μs 2.06 μs 1.82 μs 1.00 0.01 18.3105 299.32 KB 1.00
VolumeFlowToUnit .NET 8.0 .NET 8.0 1000 A 259.7 μs 1.56 μs 1.31 μs 1.19 0.01 18.5547 303.12 KB 1.01
                         
MassToUnit .NET Framework 4.8 .NET Framework 4.8 1000 A 688.3 μs 6.91 μs 6.13 μs 1.00 0.01 74.2188 460.19 KB 1.00
VolumeFlowToUnit .NET Framework 4.8 .NET Framework 4.8 1000 A 787.3 μs 12.25 μs 11.46 μs 1.14 0.02 81.0547 498.97 KB 1.08
                         
MassToUnit .NET 8.0 .NET 8.0 1000 E 328.7 μs 2.78 μs 2.32 μs 1.00 0.01 25.3906 417.59 KB 1.00
VolumeFlowToUnit .NET 8.0 .NET 8.0 1000 E 385.6 μs 3.53 μs 3.30 μs 1.17 0.01 25.8789 429.64 KB 1.03
                         
MassToUnit .NET Framework 4.8 .NET Framework 4.8 1000 E 1,204.0 μs 6.33 μs 5.62 μs 1.00 0.01 126.9531 781.48 KB 1.00
VolumeFlowToUnit .NET Framework 4.8 .NET Framework 4.8 1000 E 1,293.8 μs 10.65 μs 9.96 μs 1.07 0.01 132.8125 825.57 KB 1.06
                         
MassToUnit .NET 8.0 .NET 8.0 1000 G 323.7 μs 4.11 μs 3.85 μs 1.00 0.02 24.9023 408.62 KB 1.00
VolumeFlowToUnit .NET 8.0 .NET 8.0 1000 G 380.4 μs 3.00 μs 2.66 μs 1.18 0.02 25.3906 417.5 KB 1.02
                         
MassToUnit .NET Framework 4.8 .NET Framework 4.8 1000 G 1,221.0 μs 10.35 μs 9.68 μs 1.00 0.01 121.0938 751.29 KB 1.00
VolumeFlowToUnit .NET Framework 4.8 .NET Framework 4.8 1000 G 1,302.3 μs 15.53 μs 13.77 μs 1.07 0.01 128.9063 798.54 KB 1.06
                         
MassToUnit .NET 8.0 .NET 8.0 1000 N 353.0 μs 1.31 μs 1.16 μs 1.00 0.00 24.4141 403.69 KB 1.00
VolumeFlowToUnit .NET 8.0 .NET 8.0 1000 N 428.3 μs 3.79 μs 3.55 μs 1.21 0.01 25.3906 415.38 KB 1.03
                         
MassToUnit .NET Framework 4.8 .NET Framework 4.8 1000 N 1,217.6 μs 10.66 μs 9.97 μs 1.00 0.01 121.0938 750.96 KB 1.00
VolumeFlowToUnit .NET Framework 4.8 .NET Framework 4.8 1000 N 1,295.9 μs 9.27 μs 8.67 μs 1.06 0.01 128.9063 795.49 KB 1.06
                         
MassToUnit .NET 8.0 .NET 8.0 1000 S 437.3 μs 4.77 μs 4.23 μs 1.00 0.01 36.1328 596.14 KB 1.00
VolumeFlowToUnit .NET 8.0 .NET 8.0 1000 S 500.5 μs 4.92 μs 4.61 μs 1.14 0.01 36.1328 605.06 KB 1.01
                         
MassToUnit .NET Framework 4.8 .NET Framework 4.8 1000 S 1,389.8 μs 12.66 μs 11.23 μs 1.00 0.01 160.1563 986.45 KB 1.00
VolumeFlowToUnit .NET Framework 4.8 .NET Framework 4.8 1000 S 1,476.5 μs 8.74 μs 7.75 μs 1.06 0.01 167.9688 1033.87 KB 1.05

After:

Method Job Runtime NbConversions Format Mean Error StdDev Median Ratio RatioSD Gen0 Allocated Alloc Ratio
MassToString .NET 8.0 .NET 8.0 1000 A 32.53 μs 0.624 μs 1.656 μs 31.90 μs 1.00 0.07 8.1177 132.81 KB 1.00
VolumeFlowToString .NET 8.0 .NET 8.0 1000 A 33.46 μs 0.664 μs 1.604 μs 33.08 μs 1.03 0.07 8.1177 132.81 KB 1.00
                           
MassToString .NET Framework 4.8 .NET Framework 4.8 1000 A 95.63 μs 0.780 μs 0.651 μs 95.73 μs 1.00 0.01 21.6064 133.2 KB 1.00
VolumeFlowToString .NET Framework 4.8 .NET Framework 4.8 1000 A 121.64 μs 1.682 μs 1.574 μs 121.86 μs 1.27 0.02 21.4844 133.2 KB 1.00
                           
MassToString .NET 8.0 .NET 8.0 1000 E 136.75 μs 2.122 μs 1.984 μs 136.12 μs 1.00 0.02 15.1367 251.08 KB 1.00
VolumeFlowToString .NET 8.0 .NET 8.0 1000 E 136.72 μs 2.512 μs 2.350 μs 135.72 μs 1.00 0.02 15.8691 259.3 KB 1.03
                           
MassToString .NET Framework 4.8 .NET Framework 4.8 1000 E 518.30 μs 5.143 μs 4.294 μs 518.16 μs 1.00 0.01 73.2422 454.38 KB 1.00
VolumeFlowToString .NET Framework 4.8 .NET Framework 4.8 1000 E 584.19 μs 3.707 μs 3.467 μs 584.19 μs 1.13 0.01 74.2188 459.44 KB 1.01
                           
MassToString .NET 8.0 .NET 8.0 1000 G 138.71 μs 2.147 μs 2.008 μs 138.01 μs 1.00 0.02 14.6484 242.1 KB 1.00
VolumeFlowToString .NET 8.0 .NET 8.0 1000 G 135.84 μs 1.515 μs 1.343 μs 135.90 μs 0.98 0.02 14.8926 247.16 KB 1.02
                           
MassToString .NET Framework 4.8 .NET Framework 4.8 1000 G 513.74 μs 5.896 μs 5.515 μs 511.84 μs 1.00 0.01 68.3594 424.2 KB 1.00
VolumeFlowToString .NET Framework 4.8 .NET Framework 4.8 1000 G 530.12 μs 4.532 μs 4.018 μs 529.22 μs 1.03 0.01 70.3125 432.44 KB 1.02
                           
MassToString .NET 8.0 .NET 8.0 1000 N 148.71 μs 1.951 μs 1.825 μs 148.45 μs 1.00 0.02 14.4043 237.18 KB 1.00
VolumeFlowToString .NET 8.0 .NET 8.0 1000 N 148.93 μs 1.158 μs 1.026 μs 148.83 μs 1.00 0.01 14.8926 245.03 KB 1.03
                           
MassToString .NET Framework 4.8 .NET Framework 4.8 1000 N 511.71 μs 5.712 μs 5.343 μs 511.12 μs 1.00 0.01 68.3594 423.86 KB 1.00
VolumeFlowToString .NET Framework 4.8 .NET Framework 4.8 1000 N 537.45 μs 2.468 μs 1.927 μs 537.13 μs 1.05 0.01 69.3359 429.4 KB 1.01
                           
MassToString .NET 8.0 .NET 8.0 1000 S 232.09 μs 3.130 μs 2.928 μs 231.70 μs 1.00 0.02 26.1230 429.6 KB 1.00
VolumeFlowToString .NET 8.0 .NET 8.0 1000 S 233.04 μs 3.050 μs 2.704 μs 232.35 μs 1.00 0.02 26.3672 434.66 KB 1.01
                           
MassToString .NET Framework 4.8 .NET Framework 4.8 1000 S 669.36 μs 5.894 μs 5.514 μs 667.54 μs 1.00 0.01 106.4453 659.27 KB 1.00
VolumeFlowToString .NET Framework 4.8 .NET Framework 4.8 1000 S 700.49 μs 8.046 μs 7.526 μs 697.33 μs 1.05 0.01 108.3984 667.51 KB 1.01

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.. I fixed the method names, but didn't bother re-running the benchmark..

Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
using System;
using System.Globalization;
using System.Linq;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using UnitsNet.Units;

namespace UnitsNet.Benchmark.Conversions.ToString;

[MemoryDiagnoser]
[SimpleJob(RuntimeMoniker.Net48)]
[SimpleJob(RuntimeMoniker.Net80)]
public class ToStringWithDefaultPrecisionBenchmarks
{
private static readonly double Value = 123.456;
private readonly Random _random = new(42);

private Mass[] _masses = [];
private VolumeFlow[] _volumeFlows = [];

[Params(1000)]
public int NbConversions { get; set; }

[Params("G", "S", "E", "N", "A")]
public string Format { get; set; }

[GlobalSetup(Target = nameof(MassToString))]
public void PrepareMassesToTest()
{
_masses = _random.GetRandomQuantities<Mass, MassUnit>(Value, Mass.Units, NbConversions).ToArray();
}

[GlobalSetup(Target = nameof(VolumeFlowToString))]
public void PrepareVolumeFlowsToTest()
{
_volumeFlows = _random.GetRandomQuantities<VolumeFlow, VolumeFlowUnit>(Value, VolumeFlow.Units, NbConversions).ToArray();
}

[Benchmark(Baseline = true)]
public void MassToString()
{
foreach (Mass quantity in _masses)
{
var result = quantity.ToString(Format, CultureInfo.InvariantCulture);
}
}

[Benchmark]
public void VolumeFlowToString()
{
foreach (VolumeFlow quantity in _volumeFlows)
{
var result = quantity.ToString(Format, CultureInfo.InvariantCulture);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public double ConvertFromQuantity()
[GlobalSetup]
public void PrepareTo_ConvertWith_FullyCachedFrozenDictionary()
{
var nbQuantities = Quantity.Infos.Length;
var nbQuantities = Quantity.Infos.Count;
}

}
3 changes: 2 additions & 1 deletion UnitsNet.Benchmark/UnitsNet.Benchmark.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<TargetFrameworks>net8.0;net48</TargetFrameworks>
<LangVersion>preview</LangVersion>
<Version>4.0.0.0</Version>
<AssemblyVersion>4.0.0.0</AssemblyVersion>
<AssemblyTitle>UnitsNet.Benchmark</AssemblyTitle>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ protected virtual Enum FindUnit(string unitAbbreviation, out QuantityInfo quanti
/// <returns>The default abbreviation as provided by the associated <see cref="UnitAbbreviationsCache" /></returns>
protected string GetUnitAbbreviation(Enum unit)
{
return _abbreviations.GetDefaultAbbreviation(unit.GetType(), Convert.ToInt32(unit), CultureInfo.InvariantCulture);
return _abbreviations.GetDefaultAbbreviation(unit, CultureInfo.InvariantCulture);
}

/// <summary>
Expand Down
Loading