{"action":"created","comment":{"url":"https://api.github.com/repos/Azure/DotNetty/pulls/comments/63629974","id":63629974,"diff_hunk":"@@ -0,0 +1,196 @@\n+﻿namespace DotNetty.Transport.Tests.Performance.Sockets\n+{\n+    using System;\n+    using System.Collections.Concurrent;\n+    using System.Collections.Generic;\n+    using System.Net;\n+    using System.Threading;\n+    using System.Threading.Tasks;\n+    using DotNetty.Codecs;\n+    using DotNetty.Transport.Bootstrapping;\n+    using DotNetty.Transport.Channels;\n+    using DotNetty.Transport.Channels.Sockets;\n+    using DotNetty.Transport.Tests.Performance.Utilities;\n+    using NBench;\n+\n+    public class TcpServerSocketChannelHorizontalScaleSpec\n+    {\n+        const string ClientConnectCounterName = \"connected clients\";\n+\n+        const string InboundThroughputCounterName = \"inbound ops\";\n+\n+        const string OutboundThroughputCounterName = \"outbound ops\";\n+\n+        const string ErrorCounterName = \"exceptions caught\";\n+\n+        public const int IterationCount = 1; // these are LONG-running benchmarks. stick with a lower iteration count\n+        static readonly IPEndPoint TEST_ADDRESS = new IPEndPoint(IPAddress.IPv6Loopback, 0);\n+\n+        // Sleep main thread, then start a new client every 30 ms\n+        static readonly TimeSpan SleepInterval = TimeSpan.FromMilliseconds(300);\n+\n+        /// <summary>\n+        ///     If it takes longer than <see cref=\"SaturationThreshold\" /> to establish 10 connections, we're saturated.\n+        ///     End the stress test.\n+        /// </summary>\n+        static readonly TimeSpan SaturationThreshold = TimeSpan.FromSeconds(15);\n+\n+        protected readonly ManualResetEventSlim ResetEvent = new ManualResetEventSlim(false);\n+        ConcurrentBag<IChannel> clientChannels;\n+        Counter clientConnectedCounter;\n+        Counter errorCounter;\n+\n+        Action eventLoop;\n+        Counter inboundThroughputCounter;\n+        Counter outboundThroughputCounter;\n+\n+        IChannel serverChannel;\n+        CancellationTokenSource shutdownBenchmark;\n+\n+        IReadFinishedSignal signal;\n+\n+        protected Bootstrap ClientBootstrap;\n+\n+        protected IEventLoopGroup ClientGroup;\n+        protected ServerBootstrap ServerBoostrap;\n+        protected IEventLoopGroup ServerGroup;\n+        protected IEventLoopGroup WorkerGroup;\n+\n+        protected virtual IChannelHandler GetEncoder() => new LengthFieldPrepender(4, false);\n+\n+        protected virtual IChannelHandler GetDecoder() => new LengthFieldBasedFrameDecoder(int.MaxValue, 0, 4, 0, 4);\n+\n+        static readonly ThreadLocal<Random> ThreadLocalRandom = new ThreadLocal<Random>(() => new Random());\n+\n+        [PerfSetup]\n+        public void SetUp(BenchmarkContext context)\n+        {\n+            this.ClientGroup = new MultithreadEventLoopGroup(Environment.ProcessorCount / 2);\n+            this.ServerGroup = new MultithreadEventLoopGroup(1);\n+            this.WorkerGroup = new MultithreadEventLoopGroup(Environment.ProcessorCount / 2);\n+\n+            this.shutdownBenchmark = new CancellationTokenSource();\n+            this.clientChannels = new ConcurrentBag<IChannel>();\n+\n+            this.inboundThroughputCounter = context.GetCounter(InboundThroughputCounterName);\n+            this.outboundThroughputCounter = context.GetCounter(OutboundThroughputCounterName);\n+            this.clientConnectedCounter = context.GetCounter(ClientConnectCounterName);\n+            this.errorCounter = context.GetCounter(ErrorCounterName);\n+\n+            this.signal = new ManualResetEventSlimReadFinishedSignal(this.ResetEvent);\n+\n+            ServerBootstrap sb = new ServerBootstrap().Group(this.ServerGroup, this.WorkerGroup).Channel<TcpServerSocketChannel>()\n+                .ChildOption(ChannelOption.TcpNodelay, true)\n+                .ChildHandler(new ActionChannelInitializer<TcpSocketChannel>(channel =>\n+                {\n+                    channel.Pipeline.AddLast(this.GetEncoder())\n+                        .AddLast(this.GetDecoder())\n+                        .AddLast(new IntCodec(true))\n+                        .AddLast(new CounterHandlerInbound(this.inboundThroughputCounter))\n+                        .AddLast(new CounterHandlerOutbound(this.outboundThroughputCounter))\n+                        .AddLast(new ErrorCounterHandler(this.errorCounter));\n+                }));","path":"test/DotNetty.Transport.Tests.Performance/Sockets/TcpServerSocketChannelHorizontalScaleStressSpec.cs","position":92,"original_position":92,"commit_id":"fa633b6d43ab028dd06d07fc41d7949c02b8dba0","original_commit_id":"fa633b6d43ab028dd06d07fc41d7949c02b8dba0","user":{"login":"nayato","id":818017,"avatar_url":"https://avatars.githubusercontent.com/u/818017?v=3","gravatar_id":"","url":"https://api.github.com/users/nayato","html_url":"https://github.com/nayato","followers_url":"https://api.github.com/users/nayato/followers","following_url":"https://api.github.com/users/nayato/following{/other_user}","gists_url":"https://api.github.com/users/nayato/gists{/gist_id}","starred_url":"https://api.github.com/users/nayato/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nayato/subscriptions","organizations_url":"https://api.github.com/users/nayato/orgs","repos_url":"https://api.github.com/users/nayato/repos","events_url":"https://api.github.com/users/nayato/events{/privacy}","received_events_url":"https://api.github.com/users/nayato/received_events","type":"User","site_admin":false},"body":"yep, either way would work. New one is more composable of course.","created_at":"2016-05-18T00:51:42Z","updated_at":"2016-05-18T00:51:42Z","html_url":"https://github.com/Azure/DotNetty/pull/113#discussion_r63629974","pull_request_url":"https://api.github.com/repos/Azure/DotNetty/pulls/113","_links":{"self":{"href":"https://api.github.com/repos/Azure/DotNetty/pulls/comments/63629974"},"html":{"href":"https://github.com/Azure/DotNetty/pull/113#discussion_r63629974"},"pull_request":{"href":"https://api.github.com/repos/Azure/DotNetty/pulls/113"}}},"pull_request":{"url":"https://api.github.com/repos/Azure/DotNetty/pulls/113","id":70409285,"html_url":"https://github.com/Azure/DotNetty/pull/113","diff_url":"https://github.com/Azure/DotNetty/pull/113.diff","patch_url":"https://github.com/Azure/DotNetty/pull/113.patch","issue_url":"https://api.github.com/repos/Azure/DotNetty/issues/113","number":113,"state":"open","locked":false,"title":"added DotNetty stress spec","user":{"login":"Aaronontheweb","id":326939,"avatar_url":"https://avatars.githubusercontent.com/u/326939?v=3","gravatar_id":"","url":"https://api.github.com/users/Aaronontheweb","html_url":"https://github.com/Aaronontheweb","followers_url":"https://api.github.com/users/Aaronontheweb/followers","following_url":"https://api.github.com/users/Aaronontheweb/following{/other_user}","gists_url":"https://api.github.com/users/Aaronontheweb/gists{/gist_id}","starred_url":"https://api.github.com/users/Aaronontheweb/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Aaronontheweb/subscriptions","organizations_url":"https://api.github.com/users/Aaronontheweb/orgs","repos_url":"https://api.github.com/users/Aaronontheweb/repos","events_url":"https://api.github.com/users/Aaronontheweb/events{/privacy}","received_events_url":"https://api.github.com/users/Aaronontheweb/received_events","type":"User","site_admin":false},"body":"This spec will continuously add new client connections (firing roughly 255 msg / s each) to the same server until the time to add 10 connections exceeds the pre-defined time threshold, which currently stands at 15 seconds.\r\n\r\nGoal is to determine how many concurrent connections can be added until we've saturated the CPU. Bear in mind this spec is running both the client and the server load on the same machine, so in real life the connection threshold for a single server would be much higher.","created_at":"2016-05-17T18:47:08Z","updated_at":"2016-05-18T00:51:42Z","closed_at":null,"merged_at":null,"merge_commit_sha":"32cd7227f325fc113660657569e7bd85e808fde0","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/Azure/DotNetty/pulls/113/commits","review_comments_url":"https://api.github.com/repos/Azure/DotNetty/pulls/113/comments","review_comment_url":"https://api.github.com/repos/Azure/DotNetty/pulls/comments{/number}","comments_url":"https://api.github.com/repos/Azure/DotNetty/issues/113/comments","statuses_url":"https://api.github.com/repos/Azure/DotNetty/statuses/fa633b6d43ab028dd06d07fc41d7949c02b8dba0","head":{"label":"Aaronontheweb:stress-test","ref":"stress-test","sha":"fa633b6d43ab028dd06d07fc41d7949c02b8dba0","user":{"login":"Aaronontheweb","id":326939,"avatar_url":"https://avatars.githubusercontent.com/u/326939?v=3","gravatar_id":"","url":"https://api.github.com/users/Aaronontheweb","html_url":"https://github.com/Aaronontheweb","followers_url":"https://api.github.com/users/Aaronontheweb/followers","following_url":"https://api.github.com/users/Aaronontheweb/following{/other_user}","gists_url":"https://api.github.com/users/Aaronontheweb/gists{/gist_id}","starred_url":"https://api.github.com/users/Aaronontheweb/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Aaronontheweb/subscriptions","organizations_url":"https://api.github.com/users/Aaronontheweb/orgs","repos_url":"https://api.github.com/users/Aaronontheweb/repos","events_url":"https://api.github.com/users/Aaronontheweb/events{/privacy}","received_events_url":"https://api.github.com/users/Aaronontheweb/received_events","type":"User","site_admin":false},"repo":{"id":39223260,"name":"DotNetty","full_name":"Aaronontheweb/DotNetty","owner":{"login":"Aaronontheweb","id":326939,"avatar_url":"https://avatars.githubusercontent.com/u/326939?v=3","gravatar_id":"","url":"https://api.github.com/users/Aaronontheweb","html_url":"https://github.com/Aaronontheweb","followers_url":"https://api.github.com/users/Aaronontheweb/followers","following_url":"https://api.github.com/users/Aaronontheweb/following{/other_user}","gists_url":"https://api.github.com/users/Aaronontheweb/gists{/gist_id}","starred_url":"https://api.github.com/users/Aaronontheweb/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Aaronontheweb/subscriptions","organizations_url":"https://api.github.com/users/Aaronontheweb/orgs","repos_url":"https://api.github.com/users/Aaronontheweb/repos","events_url":"https://api.github.com/users/Aaronontheweb/events{/privacy}","received_events_url":"https://api.github.com/users/Aaronontheweb/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/Aaronontheweb/DotNetty","description":"","fork":true,"url":"https://api.github.com/repos/Aaronontheweb/DotNetty","forks_url":"https://api.github.com/repos/Aaronontheweb/DotNetty/forks","keys_url":"https://api.github.com/repos/Aaronontheweb/DotNetty/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Aaronontheweb/DotNetty/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Aaronontheweb/DotNetty/teams","hooks_url":"https://api.github.com/repos/Aaronontheweb/DotNetty/hooks","issue_events_url":"https://api.github.com/repos/Aaronontheweb/DotNetty/issues/events{/number}","events_url":"https://api.github.com/repos/Aaronontheweb/DotNetty/events","assignees_url":"https://api.github.com/repos/Aaronontheweb/DotNetty/assignees{/user}","branches_url":"https://api.github.com/repos/Aaronontheweb/DotNetty/branches{/branch}","tags_url":"https://api.github.com/repos/Aaronontheweb/DotNetty/tags","blobs_url":"https://api.github.com/repos/Aaronontheweb/DotNetty/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Aaronontheweb/DotNetty/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Aaronontheweb/DotNetty/git/refs{/sha}","trees_url":"https://api.github.com/repos/Aaronontheweb/DotNetty/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Aaronontheweb/DotNetty/statuses/{sha}","languages_url":"https://api.github.com/repos/Aaronontheweb/DotNetty/languages","stargazers_url":"https://api.github.com/repos/Aaronontheweb/DotNetty/stargazers","contributors_url":"https://api.github.com/repos/Aaronontheweb/DotNetty/contributors","subscribers_url":"https://api.github.com/repos/Aaronontheweb/DotNetty/subscribers","subscription_url":"https://api.github.com/repos/Aaronontheweb/DotNetty/subscription","commits_url":"https://api.github.com/repos/Aaronontheweb/DotNetty/commits{/sha}","git_commits_url":"https://api.github.com/repos/Aaronontheweb/DotNetty/git/commits{/sha}","comments_url":"https://api.github.com/repos/Aaronontheweb/DotNetty/comments{/number}","issue_comment_url":"https://api.github.com/repos/Aaronontheweb/DotNetty/issues/comments{/number}","contents_url":"https://api.github.com/repos/Aaronontheweb/DotNetty/contents/{+path}","compare_url":"https://api.github.com/repos/Aaronontheweb/DotNetty/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Aaronontheweb/DotNetty/merges","archive_url":"https://api.github.com/repos/Aaronontheweb/DotNetty/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Aaronontheweb/DotNetty/downloads","issues_url":"https://api.github.com/repos/Aaronontheweb/DotNetty/issues{/number}","pulls_url":"https://api.github.com/repos/Aaronontheweb/DotNetty/pulls{/number}","milestones_url":"https://api.github.com/repos/Aaronontheweb/DotNetty/milestones{/number}","notifications_url":"https://api.github.com/repos/Aaronontheweb/DotNetty/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Aaronontheweb/DotNetty/labels{/name}","releases_url":"https://api.github.com/repos/Aaronontheweb/DotNetty/releases{/id}","deployments_url":"https://api.github.com/repos/Aaronontheweb/DotNetty/deployments","created_at":"2015-07-16T22:22:22Z","updated_at":"2016-03-11T01:40:59Z","pushed_at":"2016-05-17T18:44:52Z","git_url":"git://github.com/Aaronontheweb/DotNetty.git","ssh_url":"git@github.com:Aaronontheweb/DotNetty.git","clone_url":"https://github.com/Aaronontheweb/DotNetty.git","svn_url":"https://github.com/Aaronontheweb/DotNetty","homepage":null,"size":776,"stargazers_count":1,"watchers_count":1,"language":"C#","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":1,"default_branch":"master"}},"base":{"label":"Azure:dev","ref":"dev","sha":"36ba08b5e934857e5f64004794c586cb76159836","user":{"login":"Azure","id":6844498,"avatar_url":"https://avatars.githubusercontent.com/u/6844498?v=3","gravatar_id":"","url":"https://api.github.com/users/Azure","html_url":"https://github.com/Azure","followers_url":"https://api.github.com/users/Azure/followers","following_url":"https://api.github.com/users/Azure/following{/other_user}","gists_url":"https://api.github.com/users/Azure/gists{/gist_id}","starred_url":"https://api.github.com/users/Azure/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Azure/subscriptions","organizations_url":"https://api.github.com/users/Azure/orgs","repos_url":"https://api.github.com/users/Azure/repos","events_url":"https://api.github.com/users/Azure/events{/privacy}","received_events_url":"https://api.github.com/users/Azure/received_events","type":"Organization","site_admin":false},"repo":{"id":35290377,"name":"DotNetty","full_name":"Azure/DotNetty","owner":{"login":"Azure","id":6844498,"avatar_url":"https://avatars.githubusercontent.com/u/6844498?v=3","gravatar_id":"","url":"https://api.github.com/users/Azure","html_url":"https://github.com/Azure","followers_url":"https://api.github.com/users/Azure/followers","following_url":"https://api.github.com/users/Azure/following{/other_user}","gists_url":"https://api.github.com/users/Azure/gists{/gist_id}","starred_url":"https://api.github.com/users/Azure/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Azure/subscriptions","organizations_url":"https://api.github.com/users/Azure/orgs","repos_url":"https://api.github.com/users/Azure/repos","events_url":"https://api.github.com/users/Azure/events{/privacy}","received_events_url":"https://api.github.com/users/Azure/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Azure/DotNetty","description":"DotNetty project – a port of netty, event-driven asynchronous network application framework","fork":false,"url":"https://api.github.com/repos/Azure/DotNetty","forks_url":"https://api.github.com/repos/Azure/DotNetty/forks","keys_url":"https://api.github.com/repos/Azure/DotNetty/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Azure/DotNetty/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Azure/DotNetty/teams","hooks_url":"https://api.github.com/repos/Azure/DotNetty/hooks","issue_events_url":"https://api.github.com/repos/Azure/DotNetty/issues/events{/number}","events_url":"https://api.github.com/repos/Azure/DotNetty/events","assignees_url":"https://api.github.com/repos/Azure/DotNetty/assignees{/user}","branches_url":"https://api.github.com/repos/Azure/DotNetty/branches{/branch}","tags_url":"https://api.github.com/repos/Azure/DotNetty/tags","blobs_url":"https://api.github.com/repos/Azure/DotNetty/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Azure/DotNetty/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Azure/DotNetty/git/refs{/sha}","trees_url":"https://api.github.com/repos/Azure/DotNetty/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Azure/DotNetty/statuses/{sha}","languages_url":"https://api.github.com/repos/Azure/DotNetty/languages","stargazers_url":"https://api.github.com/repos/Azure/DotNetty/stargazers","contributors_url":"https://api.github.com/repos/Azure/DotNetty/contributors","subscribers_url":"https://api.github.com/repos/Azure/DotNetty/subscribers","subscription_url":"https://api.github.com/repos/Azure/DotNetty/subscription","commits_url":"https://api.github.com/repos/Azure/DotNetty/commits{/sha}","git_commits_url":"https://api.github.com/repos/Azure/DotNetty/git/commits{/sha}","comments_url":"https://api.github.com/repos/Azure/DotNetty/comments{/number}","issue_comment_url":"https://api.github.com/repos/Azure/DotNetty/issues/comments{/number}","contents_url":"https://api.github.com/repos/Azure/DotNetty/contents/{+path}","compare_url":"https://api.github.com/repos/Azure/DotNetty/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Azure/DotNetty/merges","archive_url":"https://api.github.com/repos/Azure/DotNetty/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Azure/DotNetty/downloads","issues_url":"https://api.github.com/repos/Azure/DotNetty/issues{/number}","pulls_url":"https://api.github.com/repos/Azure/DotNetty/pulls{/number}","milestones_url":"https://api.github.com/repos/Azure/DotNetty/milestones{/number}","notifications_url":"https://api.github.com/repos/Azure/DotNetty/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Azure/DotNetty/labels{/name}","releases_url":"https://api.github.com/repos/Azure/DotNetty/releases{/id}","deployments_url":"https://api.github.com/repos/Azure/DotNetty/deployments","created_at":"2015-05-08T16:41:53Z","updated_at":"2016-05-17T08:30:30Z","pushed_at":"2016-05-18T00:50:42Z","git_url":"git://github.com/Azure/DotNetty.git","ssh_url":"git@github.com:Azure/DotNetty.git","clone_url":"https://github.com/Azure/DotNetty.git","svn_url":"https://github.com/Azure/DotNetty","homepage":"","size":950,"stargazers_count":317,"watchers_count":317,"language":"C#","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":97,"mirror_url":null,"open_issues_count":18,"forks":97,"open_issues":18,"watchers":317,"default_branch":"dev"}},"_links":{"self":{"href":"https://api.github.com/repos/Azure/DotNetty/pulls/113"},"html":{"href":"https://github.com/Azure/DotNetty/pull/113"},"issue":{"href":"https://api.github.com/repos/Azure/DotNetty/issues/113"},"comments":{"href":"https://api.github.com/repos/Azure/DotNetty/issues/113/comments"},"review_comments":{"href":"https://api.github.com/repos/Azure/DotNetty/pulls/113/comments"},"review_comment":{"href":"https://api.github.com/repos/Azure/DotNetty/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/Azure/DotNetty/pulls/113/commits"},"statuses":{"href":"https://api.github.com/repos/Azure/DotNetty/statuses/fa633b6d43ab028dd06d07fc41d7949c02b8dba0"}}}}