{"action":"created","issue":{"url":"https://api.github.com/repos/dotnet/coreclr/issues/137","labels_url":"https://api.github.com/repos/dotnet/coreclr/issues/137/labels{/name}","comments_url":"https://api.github.com/repos/dotnet/coreclr/issues/137/comments","events_url":"https://api.github.com/repos/dotnet/coreclr/issues/137/events","html_url":"https://github.com/dotnet/coreclr/pull/137","id":56921086,"number":137,"title":"SemaphoreSlim performance improvement","user":{"login":"ikopylov","id":10262823,"avatar_url":"https://avatars.githubusercontent.com/u/10262823?v=3","gravatar_id":"","url":"https://api.github.com/users/ikopylov","html_url":"https://github.com/ikopylov","followers_url":"https://api.github.com/users/ikopylov/followers","following_url":"https://api.github.com/users/ikopylov/following{/other_user}","gists_url":"https://api.github.com/users/ikopylov/gists{/gist_id}","starred_url":"https://api.github.com/users/ikopylov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ikopylov/subscriptions","organizations_url":"https://api.github.com/users/ikopylov/orgs","repos_url":"https://api.github.com/users/ikopylov/repos","events_url":"https://api.github.com/users/ikopylov/events{/privacy}","received_events_url":"https://api.github.com/users/ikopylov/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":{"login":"brianrob","id":6210322,"avatar_url":"https://avatars.githubusercontent.com/u/6210322?v=3","gravatar_id":"","url":"https://api.github.com/users/brianrob","html_url":"https://github.com/brianrob","followers_url":"https://api.github.com/users/brianrob/followers","following_url":"https://api.github.com/users/brianrob/following{/other_user}","gists_url":"https://api.github.com/users/brianrob/gists{/gist_id}","starred_url":"https://api.github.com/users/brianrob/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/brianrob/subscriptions","organizations_url":"https://api.github.com/users/brianrob/orgs","repos_url":"https://api.github.com/users/brianrob/repos","events_url":"https://api.github.com/users/brianrob/events{/privacy}","received_events_url":"https://api.github.com/users/brianrob/received_events","type":"User","site_admin":false},"milestone":null,"comments":8,"created_at":"2015-02-07T18:44:01Z","updated_at":"2015-02-12T22:17:15Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/dotnet/coreclr/pulls/137","html_url":"https://github.com/dotnet/coreclr/pull/137","diff_url":"https://github.com/dotnet/coreclr/pull/137.diff","patch_url":"https://github.com/dotnet/coreclr/pull/137.patch"},"body":"This tweak improves performance for the case when the number of working threads more than the number of CPU cores.\r\n\r\nThe original code uses SpinWait before calling Monitor.Enter(), but the spinning condition is not perfect. To reduce the number of unnecessary waiting on the Monitor it would be good to wait while other threads finished their work inside critical section. The idea of this tweak is to arrange threads on SpinWait so that they do not enter critical section concurrently.\r\n\r\n\r\nMeasurement taken on i7-4770k (8 cores: 4 physical + 4HT).\r\n\r\nSemaphoreSlim tests (source code of the test can be found [here](https://gist.github.com/ikopylov/3ba679adaaeb416d19a4#file-semaphoreslimperftest-cs)).\r\nOld:\r\n```\r\n<# of threads calling Release>, <# of threads calling Wait>: <Average execution time>\r\n1, 1:   1585ms\r\n8, 8:   2367ms\r\n1, 8:   3727ms\r\n1, 16: 97430ms\r\n8, 1:   1522ms\r\n16, 1:  1515ms\r\n```\r\n\r\nNew:\r\n```\r\n1, 1:   1488ms\r\n8, 8:   2402ms\r\n1, 8:   3556ms\r\n1, 16:  6649ms\r\n8, 1:   1546ms\r\n16, 1:  1489ms\r\n```\r\n\r\nFor the '**1, 16**' case the boost is obvious. For other cases the difference is comparable to the measurement error.\r\n\r\n\r\n\r\nBlockingCollection uses SemaphoreSlim under cover so I decided to test it too (source code of the test can be found [here](https://gist.github.com/ikopylov/3ba679adaaeb416d19a4#file-blockingcollectionperftest-cs)).\r\nOld:\r\n```\r\n<# of threads adding elements>, <# of threads taking elements>: <Average execution time>\r\n1, 1:    2106ms\r\n4, 4:    2111ms\r\n8, 8:    2683ms\r\n16, 1:  24670ms\r\n1, 16:  22661ms\r\n16, 16:  3147ms\r\n```\r\n\r\nNew:\r\n```\r\n1, 1:    2126ms\r\n4, 4:    1888ms\r\n8, 8:    2176ms\r\n16, 1:   2997ms\r\n1, 16:   3577ms\r\n16, 16:  2138ms\r\n```\r\n\r\nAgain you can see the measurable boost when the number of threads more than the number of cores.\r\n"},"comment":{"url":"https://api.github.com/repos/dotnet/coreclr/issues/comments/74165284","html_url":"https://github.com/dotnet/coreclr/pull/137#issuecomment-74165284","issue_url":"https://api.github.com/repos/dotnet/coreclr/issues/137","id":74165284,"user":{"login":"vancem","id":8459414,"avatar_url":"https://avatars.githubusercontent.com/u/8459414?v=3","gravatar_id":"","url":"https://api.github.com/users/vancem","html_url":"https://github.com/vancem","followers_url":"https://api.github.com/users/vancem/followers","following_url":"https://api.github.com/users/vancem/following{/other_user}","gists_url":"https://api.github.com/users/vancem/gists{/gist_id}","starred_url":"https://api.github.com/users/vancem/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vancem/subscriptions","organizations_url":"https://api.github.com/users/vancem/orgs","repos_url":"https://api.github.com/users/vancem/repos","events_url":"https://api.github.com/users/vancem/events{/privacy}","received_events_url":"https://api.github.com/users/vancem/received_events","type":"User","site_admin":false},"created_at":"2015-02-12T22:17:15Z","updated_at":"2015-02-12T22:17:15Z","body":"The change looks simple which is great.    My concern is that we need an analysis that tells us that we won't have deadlock bugs because we did not release enough threads.   \r\n\r\nCan you also describe the scenario that motivated the change (that is what is your scenario that has few Releasers but many waiters?    "}}