{"action":"created","issue":{"url":"https://api.github.com/repos/dotnet/corefx/issues/3992","labels_url":"https://api.github.com/repos/dotnet/corefx/issues/3992/labels{/name}","comments_url":"https://api.github.com/repos/dotnet/corefx/issues/3992/comments","events_url":"https://api.github.com/repos/dotnet/corefx/issues/3992/events","html_url":"https://github.com/dotnet/corefx/pull/3992","id":112425424,"number":3992,"title":"Avoid StringBuilder interop perf","user":{"login":"JeremyKuhne","id":8184940,"avatar_url":"https://avatars.githubusercontent.com/u/8184940?v=3","gravatar_id":"","url":"https://api.github.com/users/JeremyKuhne","html_url":"https://github.com/JeremyKuhne","followers_url":"https://api.github.com/users/JeremyKuhne/followers","following_url":"https://api.github.com/users/JeremyKuhne/following{/other_user}","gists_url":"https://api.github.com/users/JeremyKuhne/gists{/gist_id}","starred_url":"https://api.github.com/users/JeremyKuhne/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/JeremyKuhne/subscriptions","organizations_url":"https://api.github.com/users/JeremyKuhne/orgs","repos_url":"https://api.github.com/users/JeremyKuhne/repos","events_url":"https://api.github.com/users/JeremyKuhne/events{/privacy}","received_events_url":"https://api.github.com/users/JeremyKuhne/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/dotnet/corefx/labels/2%20-%20In%20Progress","name":"2 - In Progress","color":"CCCCCC"},{"url":"https://api.github.com/repos/dotnet/corefx/labels/cla-already-signed","name":"cla-already-signed","color":"009800"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":18,"created_at":"2015-10-20T18:02:34Z","updated_at":"2015-10-23T18:04:29Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/dotnet/corefx/pulls/3992","html_url":"https://github.com/dotnet/corefx/pull/3992","diff_url":"https://github.com/dotnet/corefx/pull/3992.diff","patch_url":"https://github.com/dotnet/corefx/pull/3992.patch"},"body":"Creates an internal buffer specifically for interop purposes (NativeBuffer/StringBuffer).\r\nCaching is implicit, disposing will return the buffer to the cache immediately.\r\nBuffers resize implicitly and utilize new (non depreciated) heap APIs (which handle content\r\ncopying if needed). Buffers do not zero memory for added perf.\r\nStringBuffer can copy directly with strings and other StringBuffers.\r\n\r\nSome StringBuilder perf/functionality issues for interop:\r\n- Does not pin, but could if unchunked (creating 4x allocations for out strings with P/Invoke)\r\n- Does not allow fast copying between StringBuilders\r\n- Does not allow indexing in to skip characters with P/Invoke (char* + offset)\r\n- Cannot compare substrings without allocating or walking char indexing\r\n- Difficult to split null separated string arrays (common in Win32)\r\n- Capacity is actually +1 (doesn't include the null), most Win32 APIs want count + null\r\n\r\nStart moving String/StringBuilder/StringBuffer path internal helper methods to use core\r\nchar* helper for longer methods. Keep StringBuffer overloads in a separate file to\r\nallow inclusion just with interoping projects."},"comment":{"url":"https://api.github.com/repos/dotnet/corefx/issues/comments/150649439","html_url":"https://github.com/dotnet/corefx/pull/3992#issuecomment-150649439","issue_url":"https://api.github.com/repos/dotnet/corefx/issues/3992","id":150649439,"user":{"login":"JeremyKuhne","id":8184940,"avatar_url":"https://avatars.githubusercontent.com/u/8184940?v=3","gravatar_id":"","url":"https://api.github.com/users/JeremyKuhne","html_url":"https://github.com/JeremyKuhne","followers_url":"https://api.github.com/users/JeremyKuhne/followers","following_url":"https://api.github.com/users/JeremyKuhne/following{/other_user}","gists_url":"https://api.github.com/users/JeremyKuhne/gists{/gist_id}","starred_url":"https://api.github.com/users/JeremyKuhne/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/JeremyKuhne/subscriptions","organizations_url":"https://api.github.com/users/JeremyKuhne/orgs","repos_url":"https://api.github.com/users/JeremyKuhne/repos","events_url":"https://api.github.com/users/JeremyKuhne/events{/privacy}","received_events_url":"https://api.github.com/users/JeremyKuhne/received_events","type":"User","site_admin":false},"created_at":"2015-10-23T18:04:29Z","updated_at":"2015-10-23T18:04:29Z","body":"@stephentoub Would it make sense to create a LowLevelConcurrentStack/Queue to get a lock free collection for the cache at this level?"}}