Hi Biping, (including the Drizzle mailing list for more feedback)
On Thu, May 07, 2009 at 07:36:04PM +0800, Biping MENG wrote: > I've got some questions about the pool of threads scheduler here. > As far as I know, libevent uses Level Trigger epoll on READ/WRITE event on > the Linux platform. Epoll don't perform so excellent in this mode, > especially when watching on too many FDs. So may it be a possible reason > of low performance? I don't think libevent is the performance culprit here. The usage of libevent in the current pool of threads is not optimal, but it's not a significant overhead (at least I think). I think the bigger problem is that libevent is only being used when waiting for a new command (not for reading if the command is big or when writing the command out). This means the threads in the pool may be stuck blocking on socket I/O and/or disk I/O, which is bad when you have a fixed pool size. You may have new commands ready to run but there are no free threads because they are all blocking on something else. Unfortunately this is not easily fixed, since the I/O code is spread throughout the query processing. We would need to make much of it stateful so it could yield the threads when it knows it will be blocking. This will be a big task, but ultimately, will be a big win. :) Stewart has also been looking at using fibers here (usserland threads) where Drizzle would essentially have it's own userland threading library. This would allow a scheduler to switch between "threads" when they are blocking, allowing us to avoid making the query execution code stateful. I'll let him comment more on this. :) > How do we set size? I mean, size of the pool that containing working > threads. Do we try to know the number of cores on the machine through some > API, and set the size accordingly? I thought the most great advantage of > pool of threads scheduling over multi-threads scheduling should be pool of > threads has a definitely control over the number of concurrent working > threads, and thus, could avoid some CPU consumption spent on context > switch. So we have to set the size of pool equal to the core number to > take good advantage of this saving. Do I take it right? Well, this entirely depends on the load. If we are CPU bound and the threads never block for any reason (disk, network, ...) having the same number of threads as we have cores is what we probably the correct answer. As soon as the threads can block for any reason (introduce idle CPU time), we need to start adding more threads into the pool to make sure there is always something to run. This is where some benchmarking would come in handy to see what the optimal balance is between thread count, CPU usage, and the context-switching overhead. Like I said above though, I think the "correct" solution is to never allow these threads to block and work towards an execution engine that can be stateful to yield the threads they are running on when possible. Some blocking factors, like disk I/O, are not always possible to yield on so we may want to look at using an async queue and a pool of threads dedicated to disk I/O. This allows operations that are normally blocking to be non-blocking for threads (allowing them to yield). I realize these may be high-hopes, but we can get there. :) -Eric _______________________________________________ Mailing list: https://launchpad.net/~drizzle-discuss Post to : [email protected] Unsubscribe : https://launchpad.net/~drizzle-discuss More help : https://help.launchpad.net/ListHelp

