|
|
DescriptionAdd support for multimedia timers to TaskQueue on Windows.
Multimedia timers are higher precision than WM_TIMER, but they're also
a limited resource and more costly. So this implementation is a best
effort implementation that falls back on WM_TIMER when multimedia
timers aren't available.
A possible future change could be to make high precision timers in a
TaskQueue, optional. The reason for doing so would be for TaskQueues
that don't need high precision timers, won't eat up timers from TQ
instances that really need it.
BUG=webrtc:7151
Review-Url: https://codereview.webrtc.org/2691973002
Cr-Commit-Position: refs/heads/master@{#16661}
Committed: https://chromium.googlesource.com/external/webrtc/+/f9d91548084c39fae6c355fd03202fb8f66eb5a1
Patch Set 1 #
Total comments: 4
Patch Set 2 : Update comment #
Total comments: 27
Patch Set 3 : Address comments #Patch Set 4 : Add documentation, WAIT_OBJECT_0 and remove LOG(WARNING) #
Messages
Total messages: 25 (10 generated)
tommi@webrtc.org changed reviewers: + solenberg@webrtc.org
Please take a look Fredrik. I'll associate a bug with the issue as soon as I can find it :) (or file one if I can't)
The CQ bit was checked by tommi@webrtc.org to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.webrtc.org/...
The CQ bit was unchecked by commit-bot@chromium.org
Dry run: Try jobs failed on following builders: presubmit on master.tryserver.webrtc (JOB_FAILED, http://build.chromium.org/p/tryserver.webrtc/builders/presubmit/builds/13404)
Description was changed from ========== Add support for multimedia timers to TaskQueue on Windows. Multimedia timers are higher precision than WM_TIMER, but they're also a limited resource and more costly. So this implementation is a best effort implementation that falls back on WM_TIMER when multimedia timers aren't available. A possible future change could be to make high precision timers in a TaskQueue, optional. The reason for doing so would be for TaskQueues that don't need high precision timers, won't eat up timers from TQ instances that really need it. BUG= ========== to ========== Add support for multimedia timers to TaskQueue on Windows. Multimedia timers are higher precision than WM_TIMER, but they're also a limited resource and more costly. So this implementation is a best effort implementation that falls back on WM_TIMER when multimedia timers aren't available. A possible future change could be to make high precision timers in a TaskQueue, optional. The reason for doing so would be for TaskQueues that don't need high precision timers, won't eat up timers from TQ instances that really need it. BUG=webrtc:7151 ==========
On 2017/02/13 14:53:55, tommi (webrtc) wrote: > Please take a look Fredrik. I'll associate a bug with the issue as soon as I > can find it :) (or file one if I can't) ping - just making sure you saw this.
Chances are you've already looked into this, but it's been a while since I dealt directly with the Windows APIs so I'm rusty and have some catching up to do. It looks like the recommended way for high perf timing is timer queues. However, some (e.g. http://www.virtualdub.org/blog/pivot/entry.php?id=272) claim the accuracy isn't good enough. So the right choice depends on what we intend to use delayed tasks for - highly accurate realtime scheduling, or (as it looks in the code base) for time outs and less critical processes. Tell me a bit about the tradeoff you've made! https://codereview.webrtc.org/2691973002/diff/1/webrtc/base/task_queue_win.cc File webrtc/base/task_queue_win.cc (right): https://codereview.webrtc.org/2691973002/diff/1/webrtc/base/task_queue_win.cc... webrtc/base/task_queue_win.cc:61: // limit of concurrently active multimedia timers, is much lower, or 16. Is the limit per process or across the system? https://codereview.webrtc.org/2691973002/diff/1/webrtc/base/task_queue_win.cc... webrtc/base/task_queue_win.cc:113: timeSetEvent(delay_ms, 0, reinterpret_cast<LPTIMECALLBACK>(event_), 0, MSDN says timeSetEvent() is obsolete (since XP/Server 2003) and that TimerQueues should be used instead: https://msdn.microsoft.com/en-us/library/dd757634(v=vs.85).aspx and https://msdn.microsoft.com/en-us/library/ms686796(v=vs.85).aspx
Update comment
https://codereview.webrtc.org/2691973002/diff/1/webrtc/base/task_queue_win.cc File webrtc/base/task_queue_win.cc (right): https://codereview.webrtc.org/2691973002/diff/1/webrtc/base/task_queue_win.cc... webrtc/base/task_queue_win.cc:61: // limit of concurrently active multimedia timers, is much lower, or 16. On 2017/02/14 10:29:19, the sun wrote: > Is the limit per process or across the system? per process, comment updated. https://codereview.webrtc.org/2691973002/diff/1/webrtc/base/task_queue_win.cc... webrtc/base/task_queue_win.cc:113: timeSetEvent(delay_ms, 0, reinterpret_cast<LPTIMECALLBACK>(event_), 0, On 2017/02/14 10:29:19, the sun wrote: > MSDN says timeSetEvent() is obsolete (since XP/Server 2003) and that TimerQueues > should be used instead: > https://msdn.microsoft.com/en-us/library/dd757634(v=vs.85).aspx > > and > https://msdn.microsoft.com/en-us/library/ms686796(v=vs.85).aspx Yes. I looked into the various options and measurements. As for example in the source you linked to, the accuracy of the alternatives, is not as good as this approach. So I opted for picking the approach that we currently use in WebRTC. My thinking was to pick the approach that would be least likely to cause regressions as we migrate over to using TaskQueue. Moving forward, I think it's entirely reasonable that we rethink this and evaluate the alternatives again. There might be some ways to get the same accuracy as timeSetEvent offers by using other APIs, since typically when Microsoft deprecates an API, it builds the old one on top of the new one (e.g. on newer versions of Windows that support CoreAudio, the Wave API was re-implemented on top of CoreAudio for sake of compatibility). Figuring that out and digging deeper into performance and understanding what accuracy we actually need, will require some time spent on investigating.
Generally LG, but do we really need it? PostThreadMessage will introduce an indeterminate delay anyway, so there is a lower bound on the timing interval we can get with high precision. There's also a limit to the number of high precision tasks in flight, after which we'll fall back on WM_TIMER. It seems to me we risk shooting ourselves in the foot with these limitations. Either we should just accept that posted delayed tasks have bad precision (ok for things like timeouts, etc), or we find another way. E.g. avoid PostThreadMessage and our own queue, reusing one or to MM timers to wake up at the time of the first scheduled task in the queue. I'm not saying it is easy. https://codereview.webrtc.org/2691973002/diff/20001/webrtc/base/task_queue_wi... File webrtc/base/task_queue_win.cc (right): https://codereview.webrtc.org/2691973002/diff/20001/webrtc/base/task_queue_wi... webrtc/base/task_queue_win.cc:36: InitOnceExecuteOnce(&init_once, InitializeTls, nullptr, nullptr); nit: Would be nice to use global scope for all windows functions. https://codereview.webrtc.org/2691973002/diff/20001/webrtc/base/task_queue_wi... webrtc/base/task_queue_win.cc:64: // kMaxTimers larger than 16 though since it is possible that 'complete' or nit: Odd start of sentence https://codereview.webrtc.org/2691973002/diff/20001/webrtc/base/task_queue_wi... webrtc/base/task_queue_win.cc:97: void Close() { make private https://codereview.webrtc.org/2691973002/diff/20001/webrtc/base/task_queue_wi... webrtc/base/task_queue_win.cc:107: RTC_DCHECK(timer_id_ == 0); nit: _EQ, _NE is what's preferred (though personally I think this is more readable). https://codereview.webrtc.org/2691973002/diff/20001/webrtc/base/task_queue_wi... webrtc/base/task_queue_win.cc:243: QS_ALLEVENTS, MWMO_ALERTABLE); Ah, so we need MWMO_ALTERTABLE for the stop event in PlatformThread. That may be worth a comment. https://codereview.webrtc.org/2691973002/diff/20001/webrtc/base/task_queue_wi... webrtc/base/task_queue_win.cc:245: if (result == count) { I'd rather spell out WAIT_OBJECT_0 when checking the result. https://codereview.webrtc.org/2691973002/diff/20001/webrtc/base/task_queue_wi... webrtc/base/task_queue_win.cc:248: } else if (result < count) { and here https://codereview.webrtc.org/2691973002/diff/20001/webrtc/base/task_queue_wi... webrtc/base/task_queue_win.cc:259: if (mm_timers.size() > 8) { Add a constant for the "8" inside MultimediaTimer:: https://codereview.webrtc.org/2691973002/diff/20001/webrtc/base/task_queue_wi... webrtc/base/task_queue_win.cc:311: timers->emplace_back(); What's the overhead of recreating timers (CreateEvent/CloseHandle, specifically). Is it easier to just have a pool of them than to figure out potential lag in queueing timers? https://codereview.webrtc.org/2691973002/diff/20001/webrtc/base/task_queue_wi... webrtc/base/task_queue_win.cc:326: if (!timer_queued) { Do we need logging when this happens? If I'm doing things that require high precision, and I can't actually trust the task queue to provide it, I need to at least know when it is taking me for a ride.
https://codereview.webrtc.org/2691973002/diff/20001/webrtc/base/task_queue_wi... File webrtc/base/task_queue_win.cc (right): https://codereview.webrtc.org/2691973002/diff/20001/webrtc/base/task_queue_wi... webrtc/base/task_queue_win.cc:36: InitOnceExecuteOnce(&init_once, InitializeTls, nullptr, nullptr); On 2017/02/16 12:07:25, the sun wrote: > nit: Would be nice to use global scope for all windows functions. I was debating that since that's what I'm actually used to. I checked some of the other code and based on that, removed the ::, however, since that would also help you read the code, I changed the whole file. https://codereview.webrtc.org/2691973002/diff/20001/webrtc/base/task_queue_wi... webrtc/base/task_queue_win.cc:64: // kMaxTimers larger than 16 though since it is possible that 'complete' or On 2017/02/16 12:07:25, the sun wrote: > nit: Odd start of sentence ah, there was a missing 'is'. fixed. https://codereview.webrtc.org/2691973002/diff/20001/webrtc/base/task_queue_wi... webrtc/base/task_queue_win.cc:97: void Close() { On 2017/02/16 12:07:25, the sun wrote: > make private Done. https://codereview.webrtc.org/2691973002/diff/20001/webrtc/base/task_queue_wi... webrtc/base/task_queue_win.cc:107: RTC_DCHECK(timer_id_ == 0); On 2017/02/16 12:07:25, the sun wrote: > nit: _EQ, _NE is what's preferred (though personally I think this is more > readable). Done. I couldn't do it in a couple of cases since the template code behind RTC_DCHECK_NE goes berserk if trying to compare things like event_ to nullptr or stl iterators. https://codereview.webrtc.org/2691973002/diff/20001/webrtc/base/task_queue_wi... webrtc/base/task_queue_win.cc:243: QS_ALLEVENTS, MWMO_ALERTABLE); On 2017/02/16 12:07:25, the sun wrote: > Ah, so we need MWMO_ALTERTABLE for the stop event in PlatformThread. That may be > worth a comment. Done. It's also needed for InitializeQueueThread and might also come in handy if we decide to go for a different timer approach in the future, such as waitable timers. https://codereview.webrtc.org/2691973002/diff/20001/webrtc/base/task_queue_wi... webrtc/base/task_queue_win.cc:245: if (result == count) { On 2017/02/16 12:07:25, the sun wrote: > I'd rather spell out WAIT_OBJECT_0 when checking the result. |count| will only be equal to WAIT_OBJECT_0 if count is 0. However, if there are timers that we wait on, |count| will be higher than WAIT_OBJECT_0. I'll add a comment. https://codereview.webrtc.org/2691973002/diff/20001/webrtc/base/task_queue_wi... webrtc/base/task_queue_win.cc:248: } else if (result < count) { On 2017/02/16 12:07:25, the sun wrote: > and here Same here. The purpose of this check is to make sure that we didn't get an error. If |result| is between 0 and |count| (it can't be negative), we know a timer has been fired. If it's equal or higher than |count|, then an error has occurred (error values are positive integers too, e.g. WAIT_IO_COMPLETION is 0xC0). I added info to the above comment for this too. https://codereview.webrtc.org/2691973002/diff/20001/webrtc/base/task_queue_wi... webrtc/base/task_queue_win.cc:259: if (mm_timers.size() > 8) { On 2017/02/16 12:07:25, the sun wrote: > Add a constant for the "8" inside MultimediaTimer:: Done. https://codereview.webrtc.org/2691973002/diff/20001/webrtc/base/task_queue_wi... webrtc/base/task_queue_win.cc:311: timers->emplace_back(); On 2017/02/16 12:07:25, the sun wrote: > What's the overhead of recreating timers (CreateEvent/CloseHandle, > specifically). Is it easier to just have a pool of them than to figure out > potential lag in queueing timers? CreateEvent creates a kernel object, so the cost can be noticeable (a few ms) when the machine is busy. They're also a limited resource, so while we do have a pool here (unused ones are garbage collected when we have over 8 allocated), it's not a big pool (for some definition of big). https://codereview.webrtc.org/2691973002/diff/20001/webrtc/base/task_queue_wi... webrtc/base/task_queue_win.cc:326: if (!timer_queued) { On 2017/02/16 12:07:25, the sun wrote: > Do we need logging when this happens? If I'm doing things that require high > precision, and I can't actually trust the task queue to provide it, I need to at > least know when it is taking me for a ride. That sounds useful so I've added warning log. However... The LOG IO is so expensive that it caused the Wait(100) test in PostMultipleDelayed, to start failing on my machine :-/ (powerful desktop) The total time of running that test went from 11ms to 428ms! I wonder if I should not add that log statement for now :-/
Address comments
On 2017/02/16 12:07:25, the sun wrote: > Generally LG, but do we really need it? > > PostThreadMessage will introduce an indeterminate delay anyway, so there is a > lower bound on the timing interval we can get with high precision. There's also > a limit to the number of high precision tasks in flight, after which we'll fall > back on WM_TIMER. > > It seems to me we risk shooting ourselves in the foot with these limitations. > Either we should just accept that posted delayed tasks have bad precision (ok > for things like timeouts, etc), or we find another way. E.g. avoid > PostThreadMessage and our own queue, reusing one or to MM timers to wake up at > the time of the first scheduled task in the queue. I'm not saying it is easy. > I think we need it. SetTimer can be so unreliable, sometimes firing before it should (off by a few ms) and sometimes significantly later, as much as 15ms. Since we use these timers to schedule things that need to happen within periods such as between rendering two video frames, @60fps, that's 15ms. So I think we need 1ms granularity. It's possible that waitable timers or timer queues are good enough and I want to look into that. They might not suffer from the same limitations of timeSetEvent. However, timeSetEvent is what we're already using, so I think this is a reasonable start, same limits and precision that we're already using. Having said that, yes I share the footgun concerns. Wrt to PostThreadMessage, that has actually not been a problem in my measurements, but as part of how this implementation can be improved upon, is to create the timer objects on the calling thread at the time of call and then transfer ownership of the timer via PostThreadMessage. There are a few options, but as you say, things can get complex (but still something we can do).
That's a reasonable tradeoff. LGTM % document timing expectations in task_queue.h https://codereview.webrtc.org/2691973002/diff/20001/webrtc/base/task_queue_wi... File webrtc/base/task_queue_win.cc (right): https://codereview.webrtc.org/2691973002/diff/20001/webrtc/base/task_queue_wi... webrtc/base/task_queue_win.cc:245: if (result == count) { On 2017/02/16 17:38:47, tommi (webrtc) wrote: > On 2017/02/16 12:07:25, the sun wrote: > > I'd rather spell out WAIT_OBJECT_0 when checking the result. > > |count| will only be equal to WAIT_OBJECT_0 if count is 0. However, if there are > timers that we wait on, |count| will be higher than WAIT_OBJECT_0. I'll add a > comment. I was thinking about being overly clear to the casual reader, with something like: if (result == (WAIT_OBJECT_0 + count)) { and below } else if (result < (WAIT_OBJECT_0 + count)) { since not everyone reading the docs for MsgWaitForMultipleObjectsEx() will immediately know that WAIT_OBJECT_0 == 0 (although they will for sure suspect it). (The comment is great, but just adding this extra icing makes the code self-documented IMO. It's pretty obvious to the reader something special is going on and so consulting API docs would be the next step...) https://codereview.webrtc.org/2691973002/diff/20001/webrtc/base/task_queue_wi... webrtc/base/task_queue_win.cc:311: timers->emplace_back(); On 2017/02/16 17:38:47, tommi (webrtc) wrote: > On 2017/02/16 12:07:25, the sun wrote: > > What's the overhead of recreating timers (CreateEvent/CloseHandle, > > specifically). Is it easier to just have a pool of them than to figure out > > potential lag in queueing timers? > > CreateEvent creates a kernel object, so the cost can be noticeable (a few ms) > when the machine is busy. They're also a limited resource, so while we do have > a pool here (unused ones are garbage collected when we have over 8 allocated), > it's not a big pool (for some definition of big). Out of curiosity, what's the limit? The only limit I can quickly find, is 16M (2^24) HANDLEs (I trust Russinovich on this stuff). Are there other limits per kernel object? Not sure what other costs are associated with events. https://codereview.webrtc.org/2691973002/diff/20001/webrtc/base/task_queue_wi... webrtc/base/task_queue_win.cc:326: if (!timer_queued) { On 2017/02/16 17:38:47, tommi (webrtc) wrote: > On 2017/02/16 12:07:25, the sun wrote: > > Do we need logging when this happens? If I'm doing things that require high > > precision, and I can't actually trust the task queue to provide it, I need to > at > > least know when it is taking me for a ride. > > That sounds useful so I've added warning log. However... > > The LOG IO is so expensive that it caused the Wait(100) test in > PostMultipleDelayed, to start failing on my machine :-/ (powerful desktop) > > The total time of running that test went from 11ms to 428ms! > > I wonder if I should not add that log statement for now :-/ Sounds like the best option. :/ Can you add appropriate commentary in task_queue.h on what to expect from timing?
Add documentation, WAIT_OBJECT_0 and remove LOG(WARNING)
https://codereview.webrtc.org/2691973002/diff/20001/webrtc/base/task_queue_wi... File webrtc/base/task_queue_win.cc (right): https://codereview.webrtc.org/2691973002/diff/20001/webrtc/base/task_queue_wi... webrtc/base/task_queue_win.cc:245: if (result == count) { On 2017/02/16 20:18:47, the sun wrote: > On 2017/02/16 17:38:47, tommi (webrtc) wrote: > > On 2017/02/16 12:07:25, the sun wrote: > > > I'd rather spell out WAIT_OBJECT_0 when checking the result. > > > > |count| will only be equal to WAIT_OBJECT_0 if count is 0. However, if there > are > > timers that we wait on, |count| will be higher than WAIT_OBJECT_0. I'll add a > > comment. > > I was thinking about being overly clear to the casual reader, with something > like: > > if (result == (WAIT_OBJECT_0 + count)) { > > and below > > } else if (result < (WAIT_OBJECT_0 + count)) { > > since not everyone reading the docs for MsgWaitForMultipleObjectsEx() will > immediately know that WAIT_OBJECT_0 == 0 (although they will for sure suspect > it). > > (The comment is great, but just adding this extra icing makes the code > self-documented IMO. It's pretty obvious to the reader something special is > going on and so consulting API docs would be the next step...) Ah, yes, that makes sense. https://codereview.webrtc.org/2691973002/diff/20001/webrtc/base/task_queue_wi... webrtc/base/task_queue_win.cc:311: timers->emplace_back(); On 2017/02/16 20:18:47, the sun wrote: > On 2017/02/16 17:38:47, tommi (webrtc) wrote: > > On 2017/02/16 12:07:25, the sun wrote: > > > What's the overhead of recreating timers (CreateEvent/CloseHandle, > > > specifically). Is it easier to just have a pool of them than to figure out > > > potential lag in queueing timers? > > > > CreateEvent creates a kernel object, so the cost can be noticeable (a few ms) > > when the machine is busy. They're also a limited resource, so while we do > have > > a pool here (unused ones are garbage collected when we have over 8 allocated), > > it's not a big pool (for some definition of big). > > Out of curiosity, what's the limit? The only limit I can quickly find, is 16M > (2^24) HANDLEs (I trust Russinovich on this stuff). Are there other limits per > kernel object? Not sure what other costs are associated with events. That's probably correct, given the source :) I don't know the exact cost associated, but some things that come to mind that are different from a regular in-process event-like object, would be bookkeeping overhead since events are cross-process-capable synchronization objects (events can be named and shared with other processes, duplicated etc), associated security descriptor, even a stack trace and various other info as you probably saw when looking at Mark's data (was it the 'testlimit article' you read?). https://codereview.webrtc.org/2691973002/diff/20001/webrtc/base/task_queue_wi... webrtc/base/task_queue_win.cc:326: if (!timer_queued) { On 2017/02/16 20:18:47, the sun wrote: > On 2017/02/16 17:38:47, tommi (webrtc) wrote: > > On 2017/02/16 12:07:25, the sun wrote: > > > Do we need logging when this happens? If I'm doing things that require high > > > precision, and I can't actually trust the task queue to provide it, I need > to > > at > > > least know when it is taking me for a ride. > > > > That sounds useful so I've added warning log. However... > > > > The LOG IO is so expensive that it caused the Wait(100) test in > > PostMultipleDelayed, to start failing on my machine :-/ (powerful desktop) > > > > The total time of running that test went from 11ms to 428ms! > > > > I wonder if I should not add that log statement for now :-/ > > Sounds like the best option. :/ Can you add appropriate commentary in > task_queue.h on what to expect from timing? Done.
The CQ bit was checked by tommi@webrtc.org
The patchset sent to the CQ was uploaded after l-g-t-m from solenberg@webrtc.org Link to the patchset: https://codereview.webrtc.org/2691973002/#ps60001 (title: "Add documentation, WAIT_OBJECT_0 and remove LOG(WARNING)")
CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.webrtc.org/...
CQ is committing da patch. Bot data: {"patchset_id": 60001, "attempt_start_ts": 1487324643801390, "parent_rev": "fc5d22c86f63730e3da5431b1810e355484671c3", "commit_rev": "f9d91548084c39fae6c355fd03202fb8f66eb5a1"}
Message was sent while issue was closed.
Description was changed from ========== Add support for multimedia timers to TaskQueue on Windows. Multimedia timers are higher precision than WM_TIMER, but they're also a limited resource and more costly. So this implementation is a best effort implementation that falls back on WM_TIMER when multimedia timers aren't available. A possible future change could be to make high precision timers in a TaskQueue, optional. The reason for doing so would be for TaskQueues that don't need high precision timers, won't eat up timers from TQ instances that really need it. BUG=webrtc:7151 ========== to ========== Add support for multimedia timers to TaskQueue on Windows. Multimedia timers are higher precision than WM_TIMER, but they're also a limited resource and more costly. So this implementation is a best effort implementation that falls back on WM_TIMER when multimedia timers aren't available. A possible future change could be to make high precision timers in a TaskQueue, optional. The reason for doing so would be for TaskQueues that don't need high precision timers, won't eat up timers from TQ instances that really need it. BUG=webrtc:7151 Review-Url: https://codereview.webrtc.org/2691973002 Cr-Commit-Position: refs/heads/master@{#16661} Committed: https://chromium.googlesource.com/external/webrtc/+/f9d91548084c39fae6c355fd0... ==========
Message was sent while issue was closed.
Committed patchset #4 (id:60001) as https://chromium.googlesource.com/external/webrtc/+/f9d91548084c39fae6c355fd0...
Message was sent while issue was closed.
https://codereview.webrtc.org/2691973002/diff/20001/webrtc/base/task_queue_wi... File webrtc/base/task_queue_win.cc (right): https://codereview.webrtc.org/2691973002/diff/20001/webrtc/base/task_queue_wi... webrtc/base/task_queue_win.cc:311: timers->emplace_back(); On 2017/02/17 09:43:57, tommi (webrtc) wrote: > On 2017/02/16 20:18:47, the sun wrote: > > On 2017/02/16 17:38:47, tommi (webrtc) wrote: > > > On 2017/02/16 12:07:25, the sun wrote: > > > > What's the overhead of recreating timers (CreateEvent/CloseHandle, > > > > specifically). Is it easier to just have a pool of them than to figure out > > > > potential lag in queueing timers? > > > > > > CreateEvent creates a kernel object, so the cost can be noticeable (a few > ms) > > > when the machine is busy. They're also a limited resource, so while we do > > have > > > a pool here (unused ones are garbage collected when we have over 8 > allocated), > > > it's not a big pool (for some definition of big). > > > > Out of curiosity, what's the limit? The only limit I can quickly find, is 16M > > (2^24) HANDLEs (I trust Russinovich on this stuff). Are there other limits per > > kernel object? Not sure what other costs are associated with events. > > That's probably correct, given the source :) I don't know the exact cost > associated, but some things that come to mind that are different from a regular > in-process event-like object, would be bookkeeping overhead since events are > cross-process-capable synchronization objects (events can be named and shared > with other processes, duplicated etc), associated security descriptor, even a > stack trace and various other info as you probably saw when looking at Mark's > data (was it the 'testlimit article' you read?). Yeah that was it. |