﻿<?xml version="1.0" encoding="utf-8"?><rss version="2.0"><channel><title>Ayende @ Rahien</title><link>http://ayende.com</link><description>Ayende @ Rahien</description><copyright>Copyright (C) Ayende Rahien  2004 - 2021 (c) 2026</copyright><ttl>60</ttl><item><title>Michael Valenty commented on Unbounded concurrency</title><description>I was under the impression that the TPL was for taking advantage of multiple cores for *processor-intense* operations. The processor is not your limiting factor here, it's the inherent latency in the PostTo operation which requires thread management. I would thing you'd be better off with something like ThreadPool to do that.
</description><link>http://ayende.com/4476/unbounded-concurrency#comment20</link><guid>http://ayende.com/4476/unbounded-concurrency#comment20</guid><pubDate>Sat, 01 May 2010 16:38:47 GMT</pubDate></item><item><title>Dan Finucane commented on Unbounded concurrency</title><description>The thing is your client is working as hard as it can but your server may not be.  Even if you remove that limit you would want to set the MaxDegreeOfParallelism to approximate the number of cores on your system.  Better yet use ASYNC IO instead of Parallel.ForEach avoid all the blocking and use fewer threads.    I use Jeffrey Richter's AsyncEnumerator for this and it's great.
</description><link>http://ayende.com/4476/unbounded-concurrency#comment19</link><guid>http://ayende.com/4476/unbounded-concurrency#comment19</guid><pubDate>Thu, 29 Apr 2010 17:28:40 GMT</pubDate></item><item><title>Ayende Rahien commented on Unbounded concurrency</title><description>Dan,
  
I removed the 2 connection limit, as mentioned in the post
</description><link>http://ayende.com/4476/unbounded-concurrency#comment18</link><guid>http://ayende.com/4476/unbounded-concurrency#comment18</guid><pubDate>Thu, 29 Apr 2010 17:20:09 GMT</pubDate></item><item><title>Dan Finucane commented on Unbounded concurrency</title><description>If you want to see how fast RavenDB can take documents then this test won't do that well.  You want your client to do at most 2 posts concurrently perhaps using MaxDegreeOfParallelism as suggested by James.  2 is the default max number of connections to one remote host that WININET will allow.  When you allow more than the max WININET limit all the threads above 2 will block as soon as they try to connect.
  
  
In order to get a real stress test of RavenDB you will need to increase the WININET connection limit to match the number of cores in your system or you will need multiple client machines all doing 2 at a time.  I think I would go for the multiple machine approach and use 4 or 5 all running two threads concurrently posting documents.
</description><link>http://ayende.com/4476/unbounded-concurrency#comment17</link><guid>http://ayende.com/4476/unbounded-concurrency#comment17</guid><pubDate>Thu, 29 Apr 2010 17:14:51 GMT</pubDate></item><item><title>fschwiet commented on Unbounded concurrency</title><description>@James, what value did you use for MaxDegreeOfParallelism?
</description><link>http://ayende.com/4476/unbounded-concurrency#comment16</link><guid>http://ayende.com/4476/unbounded-concurrency#comment16</guid><pubDate>Thu, 29 Apr 2010 16:43:54 GMT</pubDate></item><item><title>James Freiwirth commented on Unbounded concurrency</title><description>I ran into a very similar issue the other day despite setting MaxDegreeOfParallelism to a reasonable number. I wonder if there is something else at play here?
</description><link>http://ayende.com/4476/unbounded-concurrency#comment15</link><guid>http://ayende.com/4476/unbounded-concurrency#comment15</guid><pubDate>Thu, 29 Apr 2010 16:38:59 GMT</pubDate></item><item><title>Lee Campbell commented on Unbounded concurrency</title><description>It seems to me that the PostTo operation on the client is IO bound* and not CPU bound. Therefore I think you may be better using the APM model instead of allocating threads to each task. From what I understand the APM model will leverage the Completion Port technology and therefore not steal so many threads....this leaves the threads available for the server (localhost) to the actually process the requests.
  
  
*I imagine the client code would spend most of its CPU time blocked while reading from disk and then blocked again while performing the network IO/waiting for a response.
</description><link>http://ayende.com/4476/unbounded-concurrency#comment14</link><guid>http://ayende.com/4476/unbounded-concurrency#comment14</guid><pubDate>Thu, 29 Apr 2010 16:04:30 GMT</pubDate></item><item><title>Copenhas commented on Unbounded concurrency</title><description>Rahien, thanks for the info.
</description><link>http://ayende.com/4476/unbounded-concurrency#comment13</link><guid>http://ayende.com/4476/unbounded-concurrency#comment13</guid><pubDate>Thu, 29 Apr 2010 15:42:38 GMT</pubDate></item><item><title>Ayende Rahien commented on Unbounded concurrency</title><description>Copenhas,
  
Index updates in Couch are blocking, only one thread can do it at a single time.
  
  
Couch concurrency really shines for reads, for writes, it is limited to a single thread for documents and one thread for each index (on first read)
</description><link>http://ayende.com/4476/unbounded-concurrency#comment12</link><guid>http://ayende.com/4476/unbounded-concurrency#comment12</guid><pubDate>Thu, 29 Apr 2010 15:27:19 GMT</pubDate></item><item><title>Ayende Rahien commented on Unbounded concurrency</title><description>Demis,
  
The 1 request handling works nicely if you don't do IO.
  
As you noted, if you do need it, you have a hard limit on what you can do. Even if you use async IO, it is pretty easy to get into situations where you can handle requests fast enough but you blow out the async IO queues.
</description><link>http://ayende.com/4476/unbounded-concurrency#comment11</link><guid>http://ayende.com/4476/unbounded-concurrency#comment11</guid><pubDate>Thu, 29 Apr 2010 15:26:02 GMT</pubDate></item><item><title>Copenhas commented on Unbounded concurrency</title><description>Yeah that would make sense that CouchDB has a single write thread. I'll have to take a look to see how CouchDB really takes advantage of Erlang. I suppose when updating indexes or on reads. Hmm..but is that a write thread in Erlang's sense or does CouchDB actually create and manage an OS level thread for writing... meh, this is getting off the point of the post.
</description><link>http://ayende.com/4476/unbounded-concurrency#comment10</link><guid>http://ayende.com/4476/unbounded-concurrency#comment10</guid><pubDate>Thu, 29 Apr 2010 15:12:48 GMT</pubDate></item><item><title>Demis Bellot commented on Unbounded concurrency</title><description>CouchDB share the same number of threads that other high performance servers like Redis and Nginx has: 1. In this way, the way they achieve concurrency is just by being really really fast. 
  
  
For maximum perf and scalability this is the correct number to have, although with the advent of multi-core computing the meaning has now changed to:
  
  
"The correct number of threads is, of course, equal to the number of cores on the box" -- The Moth
  
[www.danielmoth.com/.../...arallel-Programming.aspx](http://www.danielmoth.com/Blog/Do-NOT-Explicitly-Use-Threads-For-Parallel-Programming.aspx)  
  
Achieving this in say Redis is easy just run a new instance on a different port.
  
  
Although as @Anders Lybecker implies this just lets you achieve CPU efficiency, this does not solve the problem if the actual request itself is expensive. Maybe the request needs to write a lot of data to disk in which case IO now becomes your bottleneck and your new hard limit will be reached. Which is why I would suggest either partitioning / load balancing or to defer execution.
</description><link>http://ayende.com/4476/unbounded-concurrency#comment9</link><guid>http://ayende.com/4476/unbounded-concurrency#comment9</guid><pubDate>Thu, 29 Apr 2010 14:49:37 GMT</pubDate></item><item><title>Paul Betts commented on Unbounded concurrency</title><description>It sounds like you should be using the I/O Thread Pool threading - check out 
[blogs.msdn.com/.../9990424.aspx](http://blogs.msdn.com/pfxteam/archive/2010/04/09/9990424.aspx) for a drop-in scheduler that will work with PFX.
</description><link>http://ayende.com/4476/unbounded-concurrency#comment8</link><guid>http://ayende.com/4476/unbounded-concurrency#comment8</guid><pubDate>Thu, 29 Apr 2010 14:46:44 GMT</pubDate></item><item><title>Ayende Rahien commented on Unbounded concurrency</title><description>Copenhas,
  
Couch has exactly one write thread.
  
The issue isn't with thread management, the issue is with any locks that you have to deal with.
</description><link>http://ayende.com/4476/unbounded-concurrency#comment7</link><guid>http://ayende.com/4476/unbounded-concurrency#comment7</guid><pubDate>Thu, 29 Apr 2010 14:08:51 GMT</pubDate></item><item><title>Copenhas commented on Unbounded concurrency</title><description>I do wonder what the upper limit is for CouchDB with Erlang. Due to Erlang's concurrency model it can handle thousands of it's internal processes. Of course behind the scenes it is actually managing the queues, scheduling, and OS threads that make everything run. 
  
  
I remembered reading about some Erlang webserver that didn't die until 80,000 concurrent connections while Apache died around 4,000. Of course questions of that webserver's sophistication and performance at those levels certainly comes up, but I believe it still demonstrates the abilities of Erlang.
  
  
Regardless I'm very excited about RavenDB and yes each request has a fair amount of overhead to it. It sounds like the problem is really just needing to find the maximum number of threads that can be handled concurrently. Even though Erlang is running thousands of "processes" it still limits the number of concurrent OS threads it's using. I would assume this is based on system specs when the runtime starts up.
</description><link>http://ayende.com/4476/unbounded-concurrency#comment6</link><guid>http://ayende.com/4476/unbounded-concurrency#comment6</guid><pubDate>Thu, 29 Apr 2010 13:46:31 GMT</pubDate></item><item><title>Anders Lybecker commented on Unbounded concurrency</title><description>You optimize one place to find the new bottleneck!
  
  
The Task Parallel Library tries to keep your CPU busy, at the expense of the overall performance.
  
</description><link>http://ayende.com/4476/unbounded-concurrency#comment5</link><guid>http://ayende.com/4476/unbounded-concurrency#comment5</guid><pubDate>Thu, 29 Apr 2010 12:13:26 GMT</pubDate></item><item><title>Daniel commented on Unbounded concurrency</title><description>No need for a custom partitioner.
  
Just set ParallelOption.MaxDegreeOfParallelism to some reasonable value.
  
  
Parallel.ForEach(Directory.GetFiles("Docs","*.json"), new ParallelOptions { MaxDegreeOfParallelism = 10 }, file =&gt; ...);
</description><link>http://ayende.com/4476/unbounded-concurrency#comment4</link><guid>http://ayende.com/4476/unbounded-concurrency#comment4</guid><pubDate>Thu, 29 Apr 2010 11:54:46 GMT</pubDate></item><item><title>Henning commented on Unbounded concurrency</title><description>Hi,
  
  
as far as I unterstand Parallel.For (or ForEach in this case), each single iteration could be executed in parallel to each other iteration. That's why you could end up with this huge chunk of blocking threads.
  
  
Maybe using a Partitioner could help. In that case you would not support executing every iteration in parallel, but only batches of for e.g. 100.
  
  
I believe .Net 4.0 has some support for creating partions in Parallel.ForEach ... look at 
[msdn.microsoft.com/en-us/library/dd560853.aspx](http://msdn.microsoft.com/en-us/library/dd560853.aspx)</description><link>http://ayende.com/4476/unbounded-concurrency#comment3</link><guid>http://ayende.com/4476/unbounded-concurrency#comment3</guid><pubDate>Thu, 29 Apr 2010 11:19:21 GMT</pubDate></item><item><title>Demis Bellot commented on Unbounded concurrency</title><description>@junior programmer
  
  
This is not a problem that a node.js or an erlang solution is going to solve. The problem here is that the request itself is an expensive operation and as ayende has suggested there *will always be* a celling on the number of requests it can process at the same time. ASP.NET already has a 'request queue' behind the scenes which improves the situation but this has a limit as well and there is so many requests you can queue before it will to start throwing Timeout exceptions.
  
  
The easiest solution to develop is to throttle the requests on the client and perform them in batches. However I believe the most ideal solution in the long term is to convert the requests into async operations (if not already done so) which will remove the time-coupling on the client. This will allow you to store the requests into a persistent message quene which will allow you to process the request *offline* and at a load that the server can handle efficiently.
</description><link>http://ayende.com/4476/unbounded-concurrency#comment2</link><guid>http://ayende.com/4476/unbounded-concurrency#comment2</guid><pubDate>Thu, 29 Apr 2010 10:39:51 GMT</pubDate></item><item><title>junior programmer commented on Unbounded concurrency</title><description>perhaps erlang or node.js is more suited than the c# threading model for massive concurrency
</description><link>http://ayende.com/4476/unbounded-concurrency#comment1</link><guid>http://ayende.com/4476/unbounded-concurrency#comment1</guid><pubDate>Thu, 29 Apr 2010 10:11:04 GMT</pubDate></item></channel></rss>