{"action":"created","issue":{"url":"https://api.github.com/repos/dotnet/coreclr/issues/6532","repository_url":"https://api.github.com/repos/dotnet/coreclr","labels_url":"https://api.github.com/repos/dotnet/coreclr/issues/6532/labels{/name}","comments_url":"https://api.github.com/repos/dotnet/coreclr/issues/6532/comments","events_url":"https://api.github.com/repos/dotnet/coreclr/issues/6532/events","html_url":"https://github.com/dotnet/coreclr/issues/6532","id":168405140,"number":6532,"title":"Caching the result of Char.ToString","user":{"login":"jamesqo","id":9159214,"avatar_url":"https://avatars.githubusercontent.com/u/9159214?v=3","gravatar_id":"","url":"https://api.github.com/users/jamesqo","html_url":"https://github.com/jamesqo","followers_url":"https://api.github.com/users/jamesqo/followers","following_url":"https://api.github.com/users/jamesqo/following{/other_user}","gists_url":"https://api.github.com/users/jamesqo/gists{/gist_id}","starred_url":"https://api.github.com/users/jamesqo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jamesqo/subscriptions","organizations_url":"https://api.github.com/users/jamesqo/orgs","repos_url":"https://api.github.com/users/jamesqo/repos","events_url":"https://api.github.com/users/jamesqo/events{/privacy}","received_events_url":"https://api.github.com/users/jamesqo/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":2,"created_at":"2016-07-29T20:14:26Z","updated_at":"2016-07-29T21:26:58Z","closed_at":null,"body":"Since `Char.ToString` is called so often when concatenating variable chars to strings, e.g.\r\n\r\n```cs\r\n\"The letter \" + letter + \" is the \" + i \"th letter in the alphabet.\"\r\n// or String.Format\r\n$\"The letter {letter} is the {i}th letter in the alphabet.\"\r\n```\r\n\r\nand people typically aren't aware that it involves boxing + a string allocation, we may want to consider caching the `ToString` part for ASCII characters. It could look something like this:\r\n\r\n```cs\r\nprivate static readonly string[] s_asciiStrings =\r\n{\r\n    \"\\u0000\",\r\n    \"\\u0001\",\r\n    \"\\u0002\",\r\n    \"\\u0003\",\r\n    \"\\u0004\",\r\n    ...\r\n};\r\n\r\npublic string ToString()\r\n{\r\n    return m_value <= '\\u007f' ? s_asciiStrings[m_value] : new string(m_value, 1);\r\n}\r\n```\r\n\r\nI haven't submitted a PR for this yet since I haven't tested the performance impact (it would probably kill inlining for the method since now it needs to include a branch + array index range check), and the overhead of the array + cached strings would be quite substantial (I think ~32-40 bytes for each string assuming 64-bit, and the array itself would take up about 8 * 128 bytes).\r\n\r\ncc @omariom @GSPP"},"comment":{"url":"https://api.github.com/repos/dotnet/coreclr/issues/comments/236297948","html_url":"https://github.com/dotnet/coreclr/issues/6532#issuecomment-236297948","issue_url":"https://api.github.com/repos/dotnet/coreclr/issues/6532","id":236297948,"user":{"login":"GSPP","id":12032350,"avatar_url":"https://avatars.githubusercontent.com/u/12032350?v=3","gravatar_id":"","url":"https://api.github.com/users/GSPP","html_url":"https://github.com/GSPP","followers_url":"https://api.github.com/users/GSPP/followers","following_url":"https://api.github.com/users/GSPP/following{/other_user}","gists_url":"https://api.github.com/users/GSPP/gists{/gist_id}","starred_url":"https://api.github.com/users/GSPP/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/GSPP/subscriptions","organizations_url":"https://api.github.com/users/GSPP/orgs","repos_url":"https://api.github.com/users/GSPP/repos","events_url":"https://api.github.com/users/GSPP/events{/privacy}","received_events_url":"https://api.github.com/users/GSPP/received_events","type":"User","site_admin":false},"created_at":"2016-07-29T21:26:58Z","updated_at":"2016-07-29T21:26:58Z","body":"I can already see the Stack Overflow questions coming: \"Why is `ReferenceEquals('A'.ToString(), 'A'.ToString()) == true` but `ReferenceEquals('Ü'.ToString(), 'Ü'.ToString()) == false`???\"\r\n\r\n;-)\r\n\r\nI think inlining is not really important here because the cost of executing this is so much higher than the call cost. Inlining does not simplify anything away here. It's just the call that's avoided. So that's not a significant loss.\r\n\r\nJava has something similar with boxing. Certain numbers box to well-known references I think. I believe the Java people sometimes have bugs and irritations caused by that.\r\n\r\nIf this is implemented I'd lazily initialize the array slots and I'd start the array at something more realistic like `' '`.\r\n\r\nI also think that this is more useful for integers. Culture could play a role there. [Not sure how culture could possibly affect the result.](http://stackoverflow.com/questions/8492449/is-int32-tostring-culture-specific)\r\n\r\n`Boolean.ToString()` already does something like this.\r\n\r\nAnother concern is that this could be implemented as a library method. It does not have to be in the BCL (but it could).\r\n\r\nThis would not only benefit in terms of reduced CPU cost but also in terms of reduced working set size. Some applications keep a lot of data in memory. This optimization could cause a lot of structure sharing."}}
{"actor":{"display_login":"GSPP"}}