C
C#dreadfullydistinct

✅ Am I using NumberFormatInfo properly?

I have a list of ca. 400 numbers which I want to convert to percentage strings as part of an endpoint. I know I will only ever want two decimal places or three decimal places. I was wondering about the impact of allocating a new NumberFormatInfo each time so I whipped up some code:
[Benchmark]
public static string NoCache2()
{
return ToPercentageString(0.0433m, 2);
}
[Benchmark]
public static string NoCache3()
{
return ToPercentageString(0.0433m, 3);
}
[Benchmark]
public static string Cache2()
{
return ToPercentageString2Dp(0.0433m);
}
[Benchmark]
public static string Cache3()
{
return ToPercentageString3Dp(0.0433m);
}

public static string ToPercentageString(decimal d, int decimalPlaces)
=> d.ToString(
"P",
new NumberFormatInfo()
{
PercentDecimalDigits = decimalPlaces,
PercentPositivePattern = 1
}
);

public static string ToPercentageString2Dp(decimal d)
=> d.ToString("P", TwoDpFormat);

public static string ToPercentageString3Dp(decimal d)
=> d.ToString("P", ThreeDpFormat);

private static readonly NumberFormatInfo TwoDpFormat = new NumberFormatInfo()
{
PercentDecimalDigits = 2,
PercentPositivePattern = 1
};

private static readonly NumberFormatInfo ThreeDpFormat = new NumberFormatInfo()
{
PercentDecimalDigits = 3,
PercentPositivePattern = 1
};
[Benchmark]
public static string NoCache2()
{
return ToPercentageString(0.0433m, 2);
}
[Benchmark]
public static string NoCache3()
{
return ToPercentageString(0.0433m, 3);
}
[Benchmark]
public static string Cache2()
{
return ToPercentageString2Dp(0.0433m);
}
[Benchmark]
public static string Cache3()
{
return ToPercentageString3Dp(0.0433m);
}

public static string ToPercentageString(decimal d, int decimalPlaces)
=> d.ToString(
"P",
new NumberFormatInfo()
{
PercentDecimalDigits = decimalPlaces,
PercentPositivePattern = 1
}
);

public static string ToPercentageString2Dp(decimal d)
=> d.ToString("P", TwoDpFormat);

public static string ToPercentageString3Dp(decimal d)
=> d.ToString("P", ThreeDpFormat);

private static readonly NumberFormatInfo TwoDpFormat = new NumberFormatInfo()
{
PercentDecimalDigits = 2,
PercentPositivePattern = 1
};

private static readonly NumberFormatInfo ThreeDpFormat = new NumberFormatInfo()
{
PercentDecimalDigits = 3,
PercentPositivePattern = 1
};

The results indicate caching is better but the end result after all the numbers in terms of allocs or nanoseconds saved seems unlikely to be significant (probably 217kB memory saved, or 12 microseconds faster). Is this premature optimization? OR is there a more idiomatic way to use NumberFormatInfo that I'm missing here?
D
dreadfullydistinct45d ago
| Method | Mean | Error | StdDev | Gen0 | Gen1 | Allocated |
|--------- |---------:|---------:|---------:|-------:|-------:|----------:|
| NoCache2 | 67.87 ns | 0.825 ns | 0.771 ns | 0.0324 | 0.0001 | 544 B |
| NoCache3 | 72.17 ns | 0.917 ns | 0.858 ns | 0.0329 | 0.0001 | 552 B |
| Cache2 | 38.18 ns | 0.343 ns | 0.304 ns | 0.0019 | 0.0001 | 32 B |
| Cache3 | 40.21 ns | 0.170 ns | 0.151 ns | 0.0024 | 0.0001 | 40 B |
| Method | Mean | Error | StdDev | Gen0 | Gen1 | Allocated |
|--------- |---------:|---------:|---------:|-------:|-------:|----------:|
| NoCache2 | 67.87 ns | 0.825 ns | 0.771 ns | 0.0324 | 0.0001 | 544 B |
| NoCache3 | 72.17 ns | 0.917 ns | 0.858 ns | 0.0329 | 0.0001 | 552 B |
| Cache2 | 38.18 ns | 0.343 ns | 0.304 ns | 0.0019 | 0.0001 | 32 B |
| Cache3 | 40.21 ns | 0.170 ns | 0.151 ns | 0.0024 | 0.0001 | 40 B |
L
lycian45d ago
depends on scale tbh. It's not really bad to prematurely optimize here if you know you'll ever only need one or two formats, but beyond that I'd have to see more discrepancy in benchmarks at the scale you're expecting to care
L
lycian45d ago
System.Globalization.NumberFormatInfo class - .NET
Learn more about the System.Globalization.NumberFormatInfo class.
D
dreadfullydistinct45d ago
right, yeah I am fairly sure it would only ever be 2 or 3, and it's data I'm generating in my web backend and sending to be rendered into a UI Given that, there's an argument to make it culture specific, but I think retrieving the user's current culture is not really worth the hassle at this stage Scale is pretty small, this endpoint will probably only be hit a couple times an hour if that 😛 It definitely is not really worth it for this specific use case but I do like to learn more about .NET when these things come up
Want results from more Discord servers?
Add your server
More Posts
✅ .NET MAUI LayoutI am trying to create a password field with the show icon to the right of the password field, when iGetting an error for an undefined variableHello, I'm a CS major working on a project so I'm still pretty new. I'm getting a CS0165 error on liEnemy following after the player (MONOGAME)Im making a simple game using Monogame in visual studio. I have two sprites drawn on the screen (pinIm having an issue checking for collisions when comparing DateTime objects.I have this function that's supposed to check for collisions with bookings. I am using TimeSpans andclamping how fast a input (as a float) can change.Let’s say my Input X float changes in a amount of time from -1 to 1 (-1, -0.5, 0, 0.5, 1) so as an eIValueResolver won't work with AutoMapperHi guys , hope all of you doing well, I'm recently working on a project where I need to convert a spHelp with concurrency blocking issueI have a small app that runs CPU bound on multiple threads (amount of processors) On one PC it workFrontend not workingI dont really keen on frontend but I think have some knowledge about it would be nice, I'm learning JsonSerializerOptionsTo be continuedC# Dictionary questionHi, if i have a dictionary in C# defined like so: `Dictionary<string, List<int>> test;` and I do `Li✅ Avalonia not showing rows in datagridThere are no rows in my datagrid in Avalonia, the headers are visible. I've checked if my list is emInfinite loop```c# /// ------------------------------------------------------------ /// <summary> /// Creates a sHow to connect my c# backend with the frontend?Hello, I created a ASP NET Core Web Api project with the command dotnet new webapi -minimal. In my ✅ Using `Func<ReadOnlySpan<char>,bool>` but not allowed due to Pointer TypeI am building a parser, and performance is of concern. So instead of allocating infinite strings wheconcurrency and atomicity Asp.net core web api and efcorelet's say there's an endpoint called AssingUser() ,this endpoint assigns one donation to this currenBuilding a generic repository for mongodbhello folks I was thinking build a generic repository structure for mongodb. but someday if i want