You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Bad Performance on first Power.From() call in .netCore #1126
Hi
Thank you for the answer and the ideas how to deal with this.
I did not read all the release notes between V4.72.0 and V4.144.0.
But since you mentioned the large number of types and type members is the causing this issue;
Did you add a lot of new types after V4.72.0?
I know i run on a "low power" cpu and thus i cannot compare my time measurement with all the benchmark tests done listed in issue #965. But the difference between the two versions i mentioned is a factor of 100 times slower (or even more).
So this makes me think that there is yet another problem, unless you did add hundreds of types after V4.72.
@Jens88 I'm not sure, we added a bunch of units for sure, but 100x sounds a lot.
Are you able to profile the difference between the two? Maybe find what exact hotspot in the code differs between them. Maybe we have introduced some regression.
There was one known performance regression, but it should have been fixed in 4.142.0. #1069 (comment)
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Thanks for the update on this issue. Since we went back in version we had no actual suffer anymore.
I quickly tested the newest version. Unfortunately all the "Undefined" entities vanished, so my code needs some adaption to get back running again. I will come back to this thread when I converted the code and have a test setup again.
Clearly we did something between 4.72 and 4.144 to make the JIT choke hard on this platform, that is still not fixed in v5.
I don't have much time to profile and look into this anytime soon, but I did run PerfView to get the JITStats for our 3 sample apps:
PerfTests\PerfTest_Startup_v4_72_0
PerfTests\PerfTest_Startup_v4_144_0
PerfTests\PerfTest_Startup
Summary of JIT durations
What
v4.72 [ms / count]
v4.144 [ms / count]
latest [ms / count]
Quantity static .cctor()
0
19
1
Static ctors of ~120 quantity types
0
57
70
UnitAbbreviationsCache..cctor()
43
0
0
UnitConverter.RegisterDefaultConversions
0
84
108
UnitConverter.SetConversionFunction
0
26
26
QuantityInfo
2 ms / 21
71 ms / 940
52 ms / 500
UnitInfo
0 ms / 6
11 ms / 240
15 ms / 240
Quantity.GetQuantityTypes (new)
0
0
51
...HashSet`1[UnitsNet.Units...]
1
135
0
System.Linq
2
180
25
Other
18
152
79
Total
78 ms
872 ms
470 ms
Take-aways
The main difference in 4.72 from 4.144 and latest:
A lot less JITing (140 compilations vs 8000 and 4000 compilations)
Fewer generics, latest has a lot of variants in QuantityInfo, SetConversionFunction and various dictionaries/collection types
Fewer invoked static constructors .cctor(); only Power, QuantityInfo, QuantityFormatter, BaseUnits, UnitAbbreviationsCache. In v4.144 and latest it invokes ALL 120 quantity static constructors even if only Power is used.
If we can avoid invoking all static ctors for all 120 quantities, we should be able to improve this.
I'm not sure how much we can reduce the use of generics, it has some real benefits, but maybe there are some redundancies here.
Hi, I want to throw in some performance metrics I've measured on my Arm64 device.
Environment:
.NET 8
Xilinx Zynq UltraScale+ MPSoC (ARM64)
Linux 6.1.30-xilinx-v2023.2 aarch64
UnitsNet 5.50.0
Due to some shenanigans I end up loading 4 instances of UnitsNet using a AssemblyLoadContext, Though that's outside of the scope of this issue and I'm just bringing it up to explain why RegisterDefaultConversions shows up 4 times in the below image.
Here are some measurements I got from DotTrace I'm still a bit new to this tool so if there is any more in-depth info you'd like me to grab I can.
Stacktrace
100% RegisterDefaultConversions • 3,723 ms • UnitsNet.UnitConverter.RegisterDefaultConversions(UnitConverter)
44.9% [JIT] • 1,671 ms
1.32% [Unknown] • 49 ms
► 1.21% RegisterDefaultConversions • 45 ms • UnitsNet.ForcePerLength.RegisterDefaultConversions(UnitConverter)
► 0.82% RegisterDefaultConversions • 31 ms • UnitsNet.Density.RegisterDefaultConversions(UnitConverter)
► 0.82% RegisterDefaultConversions • 31 ms • UnitsNet.PowerDensity.RegisterDefaultConversions(UnitConverter)
► 0.66% RegisterDefaultConversions • 25 ms • UnitsNet.VolumeFlow.RegisterDefaultConversions(UnitConverter)
► 0.65% RegisterDefaultConversions • 24 ms • UnitsNet.Length.RegisterDefaultConversions(UnitConverter)
► 0.65% RegisterDefaultConversions • 24 ms • UnitsNet.MassConcentration.RegisterDefaultConversions(UnitConverter)
► 0.62% RegisterDefaultConversions • 23 ms • UnitsNet.AbsorbedDoseOfIonizingRadiation.RegisterDefaultConversions(UnitConverter)
► 0.60% RegisterDefaultConversions • 22 ms • UnitsNet.Volume.RegisterDefaultConversions(UnitConverter)
► 0.60% RegisterDefaultConversions • 22 ms • UnitsNet.Pressure.RegisterDefaultConversions(UnitConverter)
► 0.59% RegisterDefaultConversions • 22 ms • UnitsNet.Power.RegisterDefaultConversions(UnitConverter)
► 0.59% RegisterDefaultConversions • 22 ms • UnitsNet.Speed.RegisterDefaultConversions(UnitConverter)
► 0.59% RegisterDefaultConversions • 22 ms • UnitsNet.Energy.RegisterDefaultConversions(UnitConverter)
► 0.55% RegisterDefaultConversions • 21 ms • UnitsNet.ElectricPotentialChangeRate.RegisterDefaultConversions(UnitConverter)
► 0.54% RegisterDefaultConversions • 20 ms • UnitsNet.AmountOfSubstance.RegisterDefaultConversions(UnitConverter)
► 0.53% RegisterDefaultConversions • 20 ms • UnitsNet.Mass.RegisterDefaultConversions(UnitConverter)
► 0.53% RegisterDefaultConversions • 20 ms • UnitsNet.BitRate.RegisterDefaultConversions(UnitConverter)
► 0.52% RegisterDefaultConversions • 19 ms • UnitsNet.Acceleration.RegisterDefaultConversions(UnitConverter)
► 0.48% RegisterDefaultConversions • 18 ms • UnitsNet.Radioactivity.RegisterDefaultConversions(UnitConverter)
► 0.47% RegisterDefaultConversions • 18 ms • UnitsNet.MassFlow.RegisterDefaultConversions(UnitConverter)
► 0.47% RegisterDefaultConversions • 17 ms • UnitsNet.Jerk.RegisterDefaultConversions(UnitConverter)
► 0.47% RegisterDefaultConversions • 17 ms • UnitsNet.RotationalStiffness.RegisterDefaultConversions(UnitConverter)
► 0.47% RegisterDefaultConversions • 17 ms • UnitsNet.CoefficientOfThermalExpansion.RegisterDefaultConversions(UnitConverter)
► 0.46% RegisterDefaultConversions • 17 ms • UnitsNet.PressureChangeRate.RegisterDefaultConversions(UnitConverter)
► 0.46% RegisterDefaultConversions • 17 ms • UnitsNet.Area.RegisterDefaultConversions(UnitConverter)
► 0.46% RegisterDefaultConversions • 17 ms • UnitsNet.Temperature.RegisterDefaultConversions(UnitConverter)
► 0.45% RegisterDefaultConversions • 17 ms • UnitsNet.SpecificEnergy.RegisterDefaultConversions(UnitConverter)
► 0.45% RegisterDefaultConversions • 17 ms • UnitsNet.LinearPowerDensity.RegisterDefaultConversions(UnitConverter)
► 0.45% RegisterDefaultConversions • 17 ms • UnitsNet.VolumeConcentration.RegisterDefaultConversions(UnitConverter)
► 0.45% RegisterDefaultConversions • 17 ms • UnitsNet.PorousMediumPermeability.RegisterDefaultConversions(UnitConverter)
► 0.45% RegisterDefaultConversions • 17 ms • UnitsNet.AreaMomentOfInertia.RegisterDefaultConversions(UnitConverter)
► 0.45% RegisterDefaultConversions • 17 ms • UnitsNet.MassFraction.RegisterDefaultConversions(UnitConverter)
► 0.44% RegisterDefaultConversions • 16 ms • UnitsNet.ElectricCurrentGradient.RegisterDefaultConversions(UnitConverter)
► 0.44% RegisterDefaultConversions • 16 ms • UnitsNet.MassMomentOfInertia.RegisterDefaultConversions(UnitConverter)
► 0.43% RegisterDefaultConversions • 16 ms • UnitsNet.Torque.RegisterDefaultConversions(UnitConverter)
► 0.43% RegisterDefaultConversions • 16 ms • UnitsNet.Capacitance.RegisterDefaultConversions(UnitConverter)
► 0.43% RegisterDefaultConversions • 16 ms • UnitsNet.RadiationEquivalentDose.RegisterDefaultConversions(UnitConverter)
► 0.43% RegisterDefaultConversions • 16 ms • UnitsNet.MassFlux.RegisterDefaultConversions(UnitConverter)
► 0.43% RegisterDefaultConversions • 16 ms • UnitsNet.MolarMass.RegisterDefaultConversions(UnitConverter)
► 0.43% RegisterDefaultConversions • 16 ms • UnitsNet.SpecificWeight.RegisterDefaultConversions(UnitConverter)
► 0.43% RegisterDefaultConversions • 16 ms • UnitsNet.MolarFlow.RegisterDefaultConversions(UnitConverter)
► 0.42% RegisterDefaultConversions • 16 ms • UnitsNet.Force.RegisterDefaultConversions(UnitConverter)
► 0.42% RegisterDefaultConversions • 16 ms • UnitsNet.Permittivity.RegisterDefaultConversions(UnitConverter)
► 0.42% RegisterDefaultConversions • 16 ms • UnitsNet.ReactiveEnergy.RegisterDefaultConversions(UnitConverter)
► 0.42% RegisterDefaultConversions • 16 ms • UnitsNet.TorquePerLength.RegisterDefaultConversions(UnitConverter)
► 0.42% RegisterDefaultConversions • 16 ms • UnitsNet.HeatFlux.RegisterDefaultConversions(UnitConverter)
► 0.42% RegisterDefaultConversions • 16 ms • UnitsNet.Information.RegisterDefaultConversions(UnitConverter)
► 0.42% RegisterDefaultConversions • 16 ms • UnitsNet.ElectricCurrentDensity.RegisterDefaultConversions(UnitConverter)
► 0.42% RegisterDefaultConversions • 16 ms • UnitsNet.WarpingMomentOfInertia.RegisterDefaultConversions(UnitConverter)
► 0.42% RegisterDefaultConversions • 16 ms • UnitsNet.StandardVolumeFlow.RegisterDefaultConversions(UnitConverter)
► 0.42% RegisterDefaultConversions • 15 ms • UnitsNet.VolumetricHeatCapacity.RegisterDefaultConversions(UnitConverter)
► 0.42% RegisterDefaultConversions • 15 ms • UnitsNet.ApparentEnergy.RegisterDefaultConversions(UnitConverter)
► 0.42% RegisterDefaultConversions • 15 ms • UnitsNet.RadiationExposure.RegisterDefaultConversions(UnitConverter)
► 0.41% RegisterDefaultConversions • 15 ms • UnitsNet.Duration.RegisterDefaultConversions(UnitConverter)
► 0.41% RegisterDefaultConversions • 15 ms • UnitsNet.Luminance.RegisterDefaultConversions(UnitConverter)
► 0.41% RegisterDefaultConversions • 15 ms • UnitsNet.Irradiation.RegisterDefaultConversions(UnitConverter)
► 0.41% RegisterDefaultConversions • 15 ms • UnitsNet.Angle.RegisterDefaultConversions(UnitConverter)
► 0.41% RegisterDefaultConversions • 15 ms • UnitsNet.RotationalSpeed.RegisterDefaultConversions(UnitConverter)
► 0.41% RegisterDefaultConversions • 15 ms • UnitsNet.VolumePerLength.RegisterDefaultConversions(UnitConverter)
► 0.41% RegisterDefaultConversions • 15 ms • UnitsNet.Molarity.RegisterDefaultConversions(UnitConverter)
► 0.41% RegisterDefaultConversions • 15 ms • UnitsNet.RotationalAcceleration.RegisterDefaultConversions(UnitConverter)
► 0.41% RegisterDefaultConversions • 15 ms • UnitsNet.AreaDensity.RegisterDefaultConversions(UnitConverter)
► 0.41% RegisterDefaultConversions • 15 ms • UnitsNet.Irradiance.RegisterDefaultConversions(UnitConverter)
► 0.41% RegisterDefaultConversions • 15 ms • UnitsNet.Impulse.RegisterDefaultConversions(UnitConverter)
► 0.41% RegisterDefaultConversions • 15 ms • UnitsNet.Frequency.RegisterDefaultConversions(UnitConverter)
► 0.40% RegisterDefaultConversions • 15 ms • UnitsNet.ForceChangeRate.RegisterDefaultConversions(UnitConverter)
► 0.40% RegisterDefaultConversions • 15 ms • UnitsNet.LinearDensity.RegisterDefaultConversions(UnitConverter)
► 0.40% RegisterDefaultConversions • 15 ms • UnitsNet.ElectricResistivity.RegisterDefaultConversions(UnitConverter)
► 0.40% RegisterDefaultConversions • 15 ms • UnitsNet.TemperatureChangeRate.RegisterDefaultConversions(UnitConverter)
► 0.40% RegisterDefaultConversions • 15 ms • UnitsNet.ElectricCharge.RegisterDefaultConversions(UnitConverter)
► 0.40% RegisterDefaultConversions • 15 ms • UnitsNet.ElectricPotentialDc.RegisterDefaultConversions(UnitConverter)
► 0.40% RegisterDefaultConversions • 15 ms • UnitsNet.EnergyDensity.RegisterDefaultConversions(UnitConverter)
► 0.40% RegisterDefaultConversions • 15 ms • UnitsNet.ThermalResistance.RegisterDefaultConversions(UnitConverter)
► 0.39% RegisterDefaultConversions • 15 ms • UnitsNet.Luminosity.RegisterDefaultConversions(UnitConverter)
► 0.39% RegisterDefaultConversions • 15 ms • UnitsNet.TemperatureGradient.RegisterDefaultConversions(UnitConverter)
► 0.39% RegisterDefaultConversions • 15 ms • UnitsNet.VolumeFlowPerArea.RegisterDefaultConversions(UnitConverter)
► 0.39% RegisterDefaultConversions • 15 ms • UnitsNet.TemperatureDelta.RegisterDefaultConversions(UnitConverter)
► 0.39% RegisterDefaultConversions • 15 ms • UnitsNet.Turbidity.RegisterDefaultConversions(UnitConverter)
► 0.39% RegisterDefaultConversions • 15 ms • UnitsNet.ReciprocalArea.RegisterDefaultConversions(UnitConverter)
► 0.39% RegisterDefaultConversions • 14 ms • UnitsNet.ElectricChargeDensity.RegisterDefaultConversions(UnitConverter)
► 0.39% RegisterDefaultConversions • 14 ms • UnitsNet.SpecificEntropy.RegisterDefaultConversions(UnitConverter)
► 0.39% RegisterDefaultConversions • 14 ms • UnitsNet.Scalar.RegisterDefaultConversions(UnitConverter)
► 0.38% RegisterDefaultConversions • 14 ms • UnitsNet.KinematicViscosity.RegisterDefaultConversions(UnitConverter)
► 0.38% RegisterDefaultConversions • 14 ms • UnitsNet.ReciprocalLength.RegisterDefaultConversions(UnitConverter)
► 0.38% RegisterDefaultConversions • 14 ms • UnitsNet.ElectricPotentialAc.RegisterDefaultConversions(UnitConverter)
► 0.38% RegisterDefaultConversions • 14 ms • UnitsNet.ElectricConductivity.RegisterDefaultConversions(UnitConverter)
► 0.38% RegisterDefaultConversions • 14 ms • UnitsNet.ReactivePower.RegisterDefaultConversions(UnitConverter)
► 0.38% RegisterDefaultConversions • 14 ms • UnitsNet.MolarEntropy.RegisterDefaultConversions(UnitConverter)
► 0.38% RegisterDefaultConversions • 14 ms • UnitsNet.ElectricResistance.RegisterDefaultConversions(UnitConverter)
► 0.38% RegisterDefaultConversions • 14 ms • UnitsNet.SpecificVolume.RegisterDefaultConversions(UnitConverter)
► 0.38% RegisterDefaultConversions • 14 ms • UnitsNet.ApparentPower.RegisterDefaultConversions(UnitConverter)
► 0.38% RegisterDefaultConversions • 14 ms • UnitsNet.AmplitudeRatio.RegisterDefaultConversions(UnitConverter)
► 0.37% RegisterDefaultConversions • 14 ms • UnitsNet.LeakRate.RegisterDefaultConversions(UnitConverter)
► 0.37% RegisterDefaultConversions • 14 ms • UnitsNet.Illuminance.RegisterDefaultConversions(UnitConverter)
► 0.37% RegisterDefaultConversions • 14 ms • UnitsNet.SolidAngle.RegisterDefaultConversions(UnitConverter)
► 0.37% RegisterDefaultConversions • 14 ms • UnitsNet.Compressibility.RegisterDefaultConversions(UnitConverter)
► 0.37% RegisterDefaultConversions • 14 ms • UnitsNet.DynamicViscosity.RegisterDefaultConversions(UnitConverter)
► 0.37% RegisterDefaultConversions • 14 ms • UnitsNet.ThermalConductivity.RegisterDefaultConversions(UnitConverter)
► 0.37% RegisterDefaultConversions • 14 ms • UnitsNet.Ratio.RegisterDefaultConversions(UnitConverter)
► 0.37% RegisterDefaultConversions • 14 ms • UnitsNet.ElectricCurrent.RegisterDefaultConversions(UnitConverter)
► 0.37% RegisterDefaultConversions • 14 ms • UnitsNet.RotationalStiffnessPerLength.RegisterDefaultConversions(UnitConverter)
► 0.37% RegisterDefaultConversions • 14 ms • UnitsNet.Entropy.RegisterDefaultConversions(UnitConverter)
► 0.36% RegisterDefaultConversions • 14 ms • UnitsNet.ElectricSurfaceChargeDensity.RegisterDefaultConversions(UnitConverter)
► 0.36% RegisterDefaultConversions • 14 ms • UnitsNet.Molality.RegisterDefaultConversions(UnitConverter)
► 0.36% RegisterDefaultConversions • 14 ms • UnitsNet.Magnetization.RegisterDefaultConversions(UnitConverter)
► 0.36% RegisterDefaultConversions • 13 ms • UnitsNet.MagneticFlux.RegisterDefaultConversions(UnitConverter)
► 0.36% RegisterDefaultConversions • 13 ms • UnitsNet.RatioChangeRate.RegisterDefaultConversions(UnitConverter)
► 0.36% RegisterDefaultConversions • 13 ms • UnitsNet.SpecificFuelConsumption.RegisterDefaultConversions(UnitConverter)
► 0.36% RegisterDefaultConversions • 13 ms • UnitsNet.HeatTransferCoefficient.RegisterDefaultConversions(UnitConverter)
► 0.36% RegisterDefaultConversions • 13 ms • UnitsNet.ElectricInductance.RegisterDefaultConversions(UnitConverter)
► 0.36% RegisterDefaultConversions • 13 ms • UnitsNet.MagneticField.RegisterDefaultConversions(UnitConverter)
► 0.36% RegisterDefaultConversions • 13 ms • UnitsNet.MolarEnergy.RegisterDefaultConversions(UnitConverter)
► 0.35% RegisterDefaultConversions • 13 ms • UnitsNet.ElectricConductance.RegisterDefaultConversions(UnitConverter)
► 0.35% RegisterDefaultConversions • 13 ms • UnitsNet.VitaminA.RegisterDefaultConversions(UnitConverter)
► 0.35% RegisterDefaultConversions • 13 ms • UnitsNet.Permeability.RegisterDefaultConversions(UnitConverter)
► 0.35% RegisterDefaultConversions • 13 ms • UnitsNet.ElectricField.RegisterDefaultConversions(UnitConverter)
► 0.35% RegisterDefaultConversions • 13 ms • UnitsNet.ElectricAdmittance.RegisterDefaultConversions(UnitConverter)
► 0.35% RegisterDefaultConversions • 13 ms • UnitsNet.LuminousIntensity.RegisterDefaultConversions(UnitConverter)
► 0.34% RegisterDefaultConversions • 13 ms • UnitsNet.Level.RegisterDefaultConversions(UnitConverter)
► 0.34% RegisterDefaultConversions • 13 ms • UnitsNet.FuelEfficiency.RegisterDefaultConversions(UnitConverter)
► 0.34% RegisterDefaultConversions • 13 ms • UnitsNet.LuminousFlux.RegisterDefaultConversions(UnitConverter)
► 0.34% RegisterDefaultConversions • 13 ms • UnitsNet.PowerRatio.RegisterDefaultConversions(UnitConverter)
► 0.34% RegisterDefaultConversions • 13 ms • UnitsNet.BrakeSpecificFuelConsumption.RegisterDefaultConversions(UnitConverter)
► 0.33% RegisterDefaultConversions • 12 ms • UnitsNet.RelativeHumidity.RegisterDefaultConversions(UnitConverter)
0.26% GetMemberList • 9.8 ms • System.RuntimeType+RuntimeTypeCache+MemberInfoCache`1.GetMemberList(MemberListType, String, CacheType)
0.03% InitializeCache • 1.2 ms • System.RuntimeType.InitializeCache()
► <0.01% GetQuantityTypes • 0.3 ms • UnitsNet.Quantity.GetQuantityTypes()
Activity
angularsen commentedon Sep 8, 2022
Hi, this is a known issue: #965
Due to a large number of types and type members for all our 100+ quantities and 1000+ units, the JIT spends a long time on the initial usages.
We don't currently have a solution to this, but a few ideas have been floated:
structtoclassto make use of inheritanceJens88 commentedon Sep 14, 2022
Hi
Thank you for the answer and the ideas how to deal with this.
I did not read all the release notes between V4.72.0 and V4.144.0.
But since you mentioned the large number of types and type members is the causing this issue;
Did you add a lot of new types after V4.72.0?
I know i run on a "low power" cpu and thus i cannot compare my time measurement with all the benchmark tests done listed in issue #965. But the difference between the two versions i mentioned is a factor of 100 times slower (or even more).
So this makes me think that there is yet another problem, unless you did add hundreds of types after V4.72.
angularsen commentedon Oct 31, 2022
@Jens88 I'm not sure, we added a bunch of units for sure, but 100x sounds a lot.
Are you able to profile the difference between the two? Maybe find what exact hotspot in the code differs between them. Maybe we have introduced some regression.
There was one known performance regression, but it should have been fixed in 4.142.0.
#1069 (comment)
stale commentedon Jun 18, 2023
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Move unit abbreviation strings into culture-specific resource files (#…
angularsen commentedon Jul 11, 2023
@JeCodeFu Long overdue, but I think this improved a lot in v5, plus some recent improvements in #1210.
Could you give it another go?
I can't replicate the extreme slowness you reported though, since you were testing on ARM32 and I'm testing on a fast computer:
Maybe the application complexity and size also affects how much work JIT needs to do for UnitsNet.
Benchmark
Comparing 4.144.0 with latest v5.
Using TimeItSharp to run a net7.0 console app with this code:
Results
Before: 850 ms
After: 523 ms
This includes the overhead of starting and running the console app. The idea was to capture any slowness in the JIT.
Before (v4.144.0)
For some reason this crashed the timeit tool, so I had to run fewer iterations on this nuget.
After (v5)
angularsen commentedon Jul 11, 2023
@tmilnthorp Some benchmarks posted above, can't spot much different in v5 versions in this simple test setup, but significantly faster than v4.
🧪Add PerfTests for startup and JIT comparing v4 and v5 (#1283)
Jens88 commentedon Jul 11, 2023
Hi Andreas
Thanks for the update on this issue. Since we went back in version we had no actual suffer anymore.
I quickly tested the newest version. Unfortunately all the "Undefined" entities vanished, so my code needs some adaption to get back running again. I will come back to this thread when I converted the code and have a test setup again.
Jens88 commentedon Jul 11, 2023
So now the measurement of the very first call of Power.From() call:
V4.72 : 633ms
V4.144: 17256ms (this was the version i reported here)
V5.21 : 9121 ms
So to summarize:
angularsen commentedon Jul 11, 2023
cc @tmilnthorp
Thanks for reporting back and testing again.
Clearly we did something between 4.72 and 4.144 to make the JIT choke hard on this platform, that is still not fixed in v5.
I don't have much time to profile and look into this anytime soon, but I did run PerfView to get the
JITStatsfor our 3 sample apps:PerfTests\PerfTest_Startup_v4_72_0PerfTests\PerfTest_Startup_v4_144_0PerfTests\PerfTest_StartupSummary of JIT durations
Quantitystatic.cctor()UnitAbbreviationsCache..cctor()UnitConverter.RegisterDefaultConversionsUnitConverter.SetConversionFunctionQuantityInfoUnitInfoQuantity.GetQuantityTypes(new)...HashSet`1[UnitsNet.Units...]System.LinqTake-aways
The main difference in 4.72 from 4.144 and latest:
QuantityInfo,SetConversionFunctionand various dictionaries/collection types.cctor(); onlyPower, QuantityInfo, QuantityFormatter, BaseUnits, UnitAbbreviationsCache. In v4.144 and latest it invokes ALL 120 quantity static constructors even if onlyPoweris used.If we can avoid invoking all static ctors for all 120 quantities, we should be able to improve this.
I'm not sure how much we can reduce the use of generics, it has some real benefits, but maybe there are some redundancies here.
PerfView data
Raw data here:
PerfViewData_UnitsNet_comparison_4.72_4.144_latest.xlsx
4.72
4.144
Latest
Anthonywolfe commentedon Apr 16, 2024
Hi, I want to throw in some performance metrics I've measured on my Arm64 device.
Environment:
Due to some shenanigans I end up loading 4 instances of UnitsNet using a AssemblyLoadContext, Though that's outside of the scope of this issue and I'm just bringing it up to explain why RegisterDefaultConversions shows up 4 times in the below image.
Here are some measurements I got from DotTrace I'm still a bit new to this tool so if there is any more in-depth info you'd like me to grab I can.
Stacktrace