-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
Consider expanding number formatting cache to larger values #76888
Comments
Tagging subscribers to this area: @dotnet/area-system-runtime Issue DetailsSeveral releases ago, we added to number formatting a cache of strings for the values 0 through 9:
Since with the default format non-negative values aren't impacted by culture, this cache is used for all numerical types for all single digit values as part of value.ToString() . We should consider expanding the cache to larger values, e.g. up to 300 to account for other frequently used values on success paths, like HTTP success status codes.
The upside to this is significantly less allocation as well as better throughput for formatting such values. The primary downside is increased memory costs for a larger table, e.g. caching all values 0 through 299 would add ~12K in allocated objects (caching all through 1000 would add ~39K). If the full cost is deemed prohibitive, it could be made lazy, such that at the expense of an additional null check on each access, we could populate only the strings actually used. We could also clear the table under certain conditions if it was deemed an issue. And we could choose to not include the table in corelib builds where we expect memory to be at a premium. cc: @marklio
|
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
I think it would end up looking something like this: [HideColumns("Job", "Error", "StdDev", "RatioSD")]
[MemoryDiagnoser(displayGenColumns: false)]
public class Bytes
{
[Params(123)]
public byte Value { get; set; }
[Benchmark]
public string ValueToString() => Value.ToString();
}
[HideColumns("Job", "Error", "StdDev", "RatioSD")]
[MemoryDiagnoser(displayGenColumns: false)]
public class Integers
{
[Params(1, 12, 123, 1234, 12345)]
public int Value { get; set; }
[Benchmark]
public string ValueToString() => Value.ToString();
}
|
@EgorBo shared with me the dump he was looking at, and I did some querying of it using clrmd. It has 8.7M strings, of which 177K are parseable with If I increase the threshold from 300 to 1000, that ~25% goes up to ~40%. |
Can the size of the cache be determined at startup based on some environmental state? Clearly, the cache memory is a trivial cost for a service application so in that environment it is warranted to make it large. But for constrained environments, the extra memory may be problematic. |
Several releases ago, we added to number formatting a cache of strings for the values 0 through 9:
runtime/src/libraries/System.Private.CoreLib/src/System/Number.Formatting.cs
Line 269 in 20d4e30
Since with the default format non-negative values aren't impacted by culture, this cache is used for all numerical types for all single digit values as part of
value.ToString()
. We should consider expanding the cache to larger values, e.g. up to 300 to account for other frequently used values on success paths, like HTTP success status codes.The upside to this is significantly less allocation as well as better throughput for formatting such values. The primary downside is increased memory costs for a larger table, e.g. caching all values 0 through 299 would add ~12K in allocated objects (caching all through 1000 would add ~39K). If the full cost is deemed prohibitive, it could be made lazy, such that at the expense of an additional null check on each access, we could populate only the strings actually used. We could also clear the table under certain conditions if it was deemed an issue. And we could choose to not include the table in corelib builds where we expect memory to be at a premium.
cc: @marklio
The text was updated successfully, but these errors were encountered: