<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Sue Loh's blog : CE Performance Tools</title><link>http://blogs.msdn.com/sloh/archive/tags/CE+Performance+Tools/default.aspx</link><description>Tags: CE Performance Tools</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Lock Convoys and How to Recognize Them</title><link>http://blogs.msdn.com/sloh/archive/2005/05/27/lock-convoys-and-how-to-recognize-them.aspx</link><pubDate>Fri, 27 May 2005 18:39:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:422605</guid><dc:creator>sloh</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/sloh/comments/422605.aspx</comments><wfw:commentRss>http://blogs.msdn.com/sloh/commentrss.aspx?PostID=422605</wfw:commentRss><description>&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;The problem:&lt;/B&gt; When using a particular application on one specific device, users noticed very bad UI response for a period of a few seconds.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;After those seconds, UI responsiveness went back to normal.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;The investigation:&lt;/B&gt; I used ActiveSync to drop celog.dll and oscapture.exe onto a standalone device.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I could have hooked the device up to Platform Builder and run Remote Kernel Tracker over KITL, but in this case the device I had was configured to run without KITL.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I just didn’t bother reconfiguring it.&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;/o:p&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;I made a .lnk file to start oscapture, and a second .lnk file to trigger it (run a second instance of oscapture with the “-c” parameter).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I dropped these onto the Start menu of the device.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I ran oscapture, and played around with the errant application until the UI slowdown occurred.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;As quickly as I could (due to the UI slowdown it took a few seconds) I brought up the start menu and clicked the link to trigger oscapture.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;OScapture saved its data to a file.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I then hooked up ActiveSync again, and copied the log file off the device.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Actually now that I think of it, I probably could have just connected Remote Kernel Tracker to the device over ActiveSync, but you know I’m not that smart.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Here is what I saw when opening up the file in Remote Kernel Tracker:&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;EM&gt;(scroll down if you can't see anything)&lt;/EM&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;EM&gt;&lt;/EM&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;IMG src="http://cenet.members.winisp.net/sloh_files/kt_convoy.png" mce_src="http://cenet.members.winisp.net/sloh_files/kt_convoy.png"&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;The main thread of pimg.exe is taking all the CPU time, and a few other threads (notably a couple in telshell.exe, which is responsible for the Smartphone UI) took little blips of time here and there, contending over a critical section.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I know they are contending because CeLog only logs critical section entry and exit events when there is contention.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Critical sections are acquired and released far too often to log uncontended operations. You don’t see any critical section exit events in this screen shot, but they’re there; they happen so close to the entry events that the “exit” icons are hidden underneath the “entry” icons.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If I had zoomed in some more, you’d see them resolve into distinct events.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;All of these threads are at the same priority, 251 (THREAD_PRIORITY_NORMAL).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I know the thread priorities because I hovered over the thread lines and saw the priorities in the resulting tooltips. &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;But despite the equal priorities in this case, only one thread, that from pimg.exe, is getting very much CPU time.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It is running to the completion of its quantum.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I know that because I set the “time marker 1 &amp;amp; 2” in the time scale bar – you can see them in the screen shot.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In the bottom right of the Remote Kernel Tracker window, where it says “Marker Time Delta,” is the time between the two markers.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That time is about 100ms, the default thread quantum in Windows CE.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Each time the pimg.exe thread runs for about the same length of time, about 100ms.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;I immediately recognized this as a lock convoy problem.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Let me describe what that means.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;A lock convoy is a situation which occurs when two or more threads at the same priority frequently (several times per quantum) acquire a synchronization object, even if they only hold that object for a very short amount of time.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It happens most often with critical sections, but can occur with mutexes, etc as well.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For a while the threads may go along happily without contending over the object.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But eventually some thread’s quantum will expire while it holds the object, and then the problem begins.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The expired thread (let’s call it Thread A) stops running, and the next thread at that priority level begins.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Soon that thread (let’s call it Thread B) gets to a point where it needs to acquire the object.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It blocks on the object.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The kernel chooses the next thread in the priority-queue.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If there are more threads at that priority which end up trying to acquire the object, they block on the object too.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This continues until the kernel returns to Thread A which owns the object.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That thread begins running again, and soon releases the object.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Here are the two important points.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;First, once Thread A releases the object, the kernel chooses a thread that’s blocked waiting for the object (probably Thread B), makes that thread the next owner of the object, and marks it as “runnable.”&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Second, Thread A hasn’t expired its quantum yet, so it continues running rather than switching to Thread B.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Since the threads in this scenario acquire the synchronization object frequently, Thread A soon comes back to a point where it needs to acquire the object again.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This time, however, Thread B owns it.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So Thread A blocks on the object, and the kernel again chooses the next thread in the priority-queue to run.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It eventually gets to Thread B, who does its work while owning the object, then releases the object.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The next thread blocked on the object receives ownership, and this cycle continues endlessly until eventually the threads stop acquiring so often.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;The real performance killer about a lock convoy situation is that every time the threads involved need to acquire the synchronization object, they block and take at least a couple of context switches.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Since the premise of this situation is that the threads acquire the object frequently (several times a quantum), they are running for much less than a quantum between each context switch.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The less time they run between acquires, the more context switches involved – and remember that this is all regardless of how long or short of a time they spend owning the object.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;The other performance killer in a lock convoy situation is that it dramatically increases the percentage of CPU time non-contending threads at the same priority level get to run.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If all threads at that priority level are contending over the object, what you see is very frequent context switching between them all.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If one or more threads at that level are running continuously without blocking on any objects, those threads get to run for a full quantum each time the contending threads loop on the object.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That is what you see in the screen shot above; the pimg.exe thread is not involved in the lock convoy, but since it’s at the same priority level as all the threads in the convoy, it gets all the CPU time.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In this case, the UI threads only ran very tiny periods once each quantum of the pimg.exe thread execution, so the UI was very slow to respond to user input.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Eventually the pimg.exe thread completed its work, the UI threads completed their convoy, and the UI response time went back to its snappy old self.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;The solution:&lt;/B&gt; Lock convoys are not always easy to solve.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In this case, I don’t know the solution for sure, but I believe they either lowered the priority of the pimg.exe main thread or made it do its work at another time.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;While that doesn’t actually get rid of the lock convoy, it speeds it up to the point where it is unnoticeable to the user.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Another work-around might have been to make the pimg.exe thread yield frequently, by calling Sleep(0), to allow the other threads to do their work more frequently than once per quantum.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Note, however, that this isn’t a very ideal work-around, because it’d lead to very frequent thread switching.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Context-switching very often is a problem in itself; you spend all your time making the kernel reschedule threads instead of letting those threads run.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;A different work-around is to reduce contention over the object by allowing it to be shared more often.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For example, suppose the object is a critical section protecting some data.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;You don’t want threads to read the data while it’s being written, or write concurrently, etc.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If reads are relatively frequent while writes are relatively rare, then a way to reduce contention over the lock is to convert it to a reader / writer lock.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If writes are frequent, the improvement of using a reader/writer lock is minimal, but otherwise such a change can allow threads to read at the same time without serializing over a lock.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Sometimes you can work around the problem by acquiring the lock at some other time.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For example, I note that there’s a thread in filesys.exe involved in the convoy.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So I suspect the critical section that was undergoing contention was inside filesys.exe.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;(While critical sections cannot be shared between processes, the non-filesys.exe threads may have used its critical section during calls into filesys.exe APIs.)&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Maybe the UI threads were reading from files to draw icons, or reading from the registry, or writing to a log file.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In the read case, perhaps the UI could have kept the objects in a cache so as to avoid entering the file system.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In the write case, perhaps it could queue up file system writes to execute at a later time.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Either solution amounts to caching data and performing operations asynchronously, instead of during time-critical UI processing.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;While lock convoys are also possible in Windows XP, they’re a little less problematic because of the priority boosting and aging that the Windows XP scheduler does.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If a thread blocks on an object, then when it becomes un-blocked the XP scheduler temporarily boosts its priority a little.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When a thread runs to the completion of its quantum, the XP scheduler ages its priority a little.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In this manner, threads that block often end up at higher priority than threads that run continuously without blocking.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Then the lock convoy isn’t eliminated, but there is less chance of another unrelated thread skunking up the works by running a full quantum each thread switch.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;A better solution, if you can change all the code that acquires the contentious lock, is to use TryEnterCriticalSection to acquire the lock only when it’s uncontended.&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;/o:p&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;retries = 0;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;while(!TryEnterCriticalSection(&amp;amp;CritSec)) {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;if( retries++ &amp;lt; SpinLimit ){&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;Sleep(0);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;continue;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;EnterCriticalSection(&amp;amp;CritSec);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;break;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;}&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;This code will use TryEnterCriticalSection a number of times, yielding the processor on each failure until it reaches the SpinLimit and then uses regular EnterCriticalSection.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The SpinLimit is necessary in case the critical section is owned by a lower-priority thread which would not run and release the critical section while the current thread is looping.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In that case the EnterCriticalSection call is required to make the kernel invert the priority of the owning thread briefly, so that the higher-priority thread can acquire the critical section.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;You may expect this code, which basically polls for the critical section, to hurt performance.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But believe it or not, it can greatly improve it.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The difference between this loop and a regular EnterCriticalSection call is that threads do not enter the queue to acquire the critical section if some other thread owns it.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So in the example above, when Thread A releases the critical section, Thread B does not immediately become the owner.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Thread A is free to continue running and even acquire and release the critical section a few more times before Thread B comes back and tries to acquire it again.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Even with a SpinLimit of 2 (= 1 Sleep() call) two threads can recover from critical section contention without creating a convoy.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Alas, this solution is unavailable if you cannot change the code which acquires the critical section.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;To those of you who might ask whether we intend to make changes to Windows CE to eliminate lock convoys, I’m not at liberty to discuss what we may or may not do in future products.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I can only say the standard non-informative spiel: Microsoft is committed to improving the quality of its products and considers all improvements in the context of other improvements we wish to make, to provide our customers the biggest benefits possible in the time available blah blah blah.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;(By the way that spiel, while hokey, really is true.)&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;In the meantime I hope I’ve provided you with some information you can use to identify and escape this problem if you encounter it.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;STRONG&gt;&lt;EM&gt;UPDATE 26 June 06:&lt;/EM&gt;&lt;/STRONG&gt;&amp;nbsp; Discussion of whether the TryEnter/Sleep solution hurts perf.&amp;nbsp; I don’t really think the Sleep() will hurt perf at all.&amp;nbsp; Here is what would happen:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;
&lt;DIV class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Thread 1 quantum expires while holding the CS (which is what starts a convoy)&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Thread 2 does TryEnter, fails, and sleeps&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Thread 1 runs again, acquires and releases the CS a bunch of times, and quantum expires while not holding the CS&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Thread 2 runs again, does TryEnter again, succeeds.&amp;nbsp; Now it can acquire and release the CS a bunch of times.&lt;/DIV&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;So the sleep causes a thread switch, but it’s a thread switch you’d have taken anyway if you were using regular EnterCriticalSection.&amp;nbsp; And now that I think more about this, I think your change to hold the CS for a longer period would negatively impact the perf of the TryEnter solution, because it’d increase the chances of expiring your quantum while holding the CS.&amp;nbsp; Though the impact would still not be bad because in general the threads would run to quantum completion.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=422605" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/sloh/archive/tags/CE+Performance+Tools/default.aspx">CE Performance Tools</category></item><item><title>Windows CE eHow-tos and Tutorials!  WOW!!</title><link>http://blogs.msdn.com/sloh/archive/2005/05/25/421840.aspx</link><pubDate>Wed, 25 May 2005 21:49:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:421840</guid><dc:creator>sloh</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/sloh/comments/421840.aspx</comments><wfw:commentRss>http://blogs.msdn.com/sloh/commentrss.aspx?PostID=421840</wfw:commentRss><description>&lt;P&gt;I saw a blip of this at MEDC, and just checked it out myself.&amp;nbsp; How cool!&amp;nbsp; It's like a DevCon for all to share!&lt;/P&gt;
&lt;P&gt;&lt;A href="http://msdn.microsoft.com/embedded/getstart/basics/tutorialsce/default.aspx"&gt;http://msdn.microsoft.com/embedded/getstart/basics/tutorialsce/default.aspx&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;Most of it is pretty basic stuff,&amp;nbsp;but if you're new to Windows CE, you should check&amp;nbsp;some of these&amp;nbsp;out!&amp;nbsp; (If you are new to performance tools like Remote Kernel Tracker which I've been posting about, take a look at the&amp;nbsp;&lt;A&gt;Microsoft Windows CE 5.0 Advanced Lab&lt;/A&gt;&amp;nbsp;that's on that site.)&lt;/P&gt;
&lt;P&gt;Sue&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=421840" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/sloh/archive/tags/CE+Performance+Tools/default.aspx">CE Performance Tools</category><category domain="http://blogs.msdn.com/sloh/archive/tags/Debugging_2C00_+Kernel+_2600_+misc.+File+System+issues/default.aspx">Debugging, Kernel &amp; misc. File System issues</category></item><item><title>Recognizing Excessive Thread Switching</title><link>http://blogs.msdn.com/sloh/archive/2005/05/23/421057.aspx</link><pubDate>Mon, 23 May 2005 17:16:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:421057</guid><dc:creator>sloh</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/sloh/comments/421057.aspx</comments><wfw:commentRss>http://blogs.msdn.com/sloh/commentrss.aspx?PostID=421057</wfw:commentRss><description>&lt;P class=Text&gt;&lt;FONT face=Verdana size=2&gt;Sometimes the source of a performance problem is not that code is too slow, but that threads switch too frequently. When the system switches between threads, the system consumes extra cycles in scheduling activities such as selecting the next thread to run, or switching to the new thread, rather than spending the time executing application code. In general, the less time threads run before switching out, the more total time the system spends scheduling new threads to run.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=Text&gt;&lt;FONT face=Verdana size=2&gt;The default amount of time that a thread runs before switching to another thread is called the Default Thread Quantum, &lt;SPAN class=Bold&gt;&lt;I&gt;&lt;SPAN&gt;dwDefaultThreadQuantum&lt;/SPAN&gt;&lt;/I&gt;&lt;/SPAN&gt;. For example, if the default thread quantum is 100 milliseconds, then a thread would run continuously for 100 milliseconds before another thread ran, unless preempted by a higher-priority thread. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=Text&gt;&lt;FONT face=Verdana size=2&gt;In a system where threads run to the end of a 100-millisecond quantum, there is one thread switch per 100 milliseconds, or 10 thread switches per second. In contrast, in a system where threads run only 50 microseconds before switching, there is one switch per 50 microseconds, or 20,000 thread switches per second. Switching at such an elevated rate has a dramatic performance impact.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=Text&gt;&lt;FONT face=Verdana size=2&gt;You can use Remote Kernel Tracker to identify these situations. Remote Kernel Tracker depicts thread switches as vertical green lines.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=Text&gt;&lt;FONT face=Verdana size=2&gt;The following screenshot shows an example of an application with excessive thread switching. In this picture, I’ve set two markers in the time scale at the top of the display. The difference in time between the two is displayed in the status bar on the bottom right, so from time marker 1 to time marker 2 is 10 milliseconds. As you can see, there are numerous vertical green lines; each represents a switch from one thread to another.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;EM&gt;(scroll down if you can't see anything)&lt;/EM&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;IMG src="http://cenet.members.winisp.net/sloh_files/kt_contextswitch1.png"&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;EM&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/EM&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;SPAN&gt;You also can see above that the threads seem to be continuously repeating a pattern. The next picture zooms in on that pattern:&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;SPAN&gt;&lt;EM&gt;(again, scroll down if you can't see anything)&lt;/EM&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;IMG src="http://cenet.members.winisp.net/sloh_files/kt_contextswitch2.png"&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;As you can see in the preceding picture, the “&lt;SPAN class=bold&gt;OpenDeviceKey”&lt;/SPAN&gt; thread runs the longest continuous time, about 0.6 milliseconds. The next longest run-time in this screenshot, “&lt;SPAN class=bold&gt;RndisSendRndisMessage&lt;/SPAN&gt;&lt;STRONG&gt;,”&lt;/STRONG&gt; is 0.16 milliseconds. The greatest switching activity, between “&lt;SPAN class=bold&gt;UsbInterruptThreadStub”&lt;/SPAN&gt; and “&lt;SPAN class=bold&gt;DmacIntrThread&lt;/SPAN&gt;&lt;STRONG&gt;,” &lt;/STRONG&gt;occurs at a rate of one switch approximately every 50 &lt;U&gt;micro&lt;/U&gt;seconds. One thread switch per 50us is a rate of 20,000 thread switches per second. This means that thread switching occurs at a rate that is about 2000 times higher than the ideal.&lt;/P&gt;
&lt;P class=MsoNormal&gt;Let me describe where these screen shots came from:&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;B&gt;The problem:&lt;/B&gt; Poor USB throughput.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;On particular hardware we expected to get about 50Mbps throughput, but were getting only about 23Mbps.&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;B&gt;The investigation:&lt;/B&gt; We recorded a Monte Carlo profiling trace, with these results:&lt;/P&gt;
&lt;B&gt;HITS PER SYMBOL&lt;/A&gt;&lt;/B&gt;&lt;BR&gt;
&lt;TABLE cellSpacing=4&gt;

&lt;TR&gt;
&lt;TH&gt;Hits&lt;/TH&gt;
&lt;TH&gt;Percent&lt;/TH&gt;
&lt;TH&gt;Address&lt;/TH&gt;
&lt;TH&gt;Module&lt;/TH&gt;
&lt;TH align=left&gt;Routine&lt;/TH&gt;&lt;/TR&gt;
&lt;TR align=right&gt;
&lt;TD&gt;6557&lt;/TD&gt;
&lt;TD&gt;7.3&lt;/TD&gt;
&lt;TD&gt;0x8012C8FC&lt;/TD&gt;
&lt;TD&gt;NK.EXE&lt;/TD&gt;
&lt;TD align=left&gt;IDLE_STATE&lt;/TD&gt;&lt;/TR&gt;
&lt;TR align=right&gt;
&lt;TD&gt;4643&lt;/TD&gt;
&lt;TD&gt;5.2&lt;/TD&gt;
&lt;TD&gt;0x8010E330&lt;/TD&gt;
&lt;TD&gt;NK.EXE&lt;/TD&gt;
&lt;TD align=left&gt;INTERRUPTS_ENABLE&lt;/TD&gt;&lt;/TR&gt;
&lt;TR align=right&gt;
&lt;TD&gt;2882&lt;/TD&gt;
&lt;TD&gt;3.2&lt;/TD&gt;
&lt;TD&gt;0x02FEA884&lt;/TD&gt;
&lt;TD&gt;tcpstk.dll&lt;/TD&gt;
&lt;TD align=left&gt;tcpxsum&lt;/TD&gt;&lt;/TR&gt;
&lt;TR align=right&gt;
&lt;TD&gt;&lt;FONT color=#008000&gt;&lt;STRONG&gt;2166&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD&gt;&lt;FONT color=#008000&gt;&lt;STRONG&gt;2.4&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD&gt;&lt;FONT color=#008000&gt;&lt;STRONG&gt;0x80110894&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD&gt;&lt;FONT color=#008000&gt;&lt;STRONG&gt;NK.EXE&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD align=left&gt;&lt;FONT color=#008000&gt;&lt;STRONG&gt;ObjectCall&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR align=right&gt;
&lt;TD&gt;2123&lt;/TD&gt;
&lt;TD&gt;2.4&lt;/TD&gt;
&lt;TD&gt;0x03FA37B8&lt;/TD&gt;
&lt;TD&gt;coredll.dll&lt;/TD&gt;
&lt;TD align=left&gt;memcpybigblk&lt;/TD&gt;&lt;/TR&gt;
&lt;TR align=right&gt;
&lt;TD&gt;&lt;STRONG&gt;&lt;FONT color=#008000&gt;2064&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/TD&gt;
&lt;TD&gt;&lt;STRONG&gt;&lt;FONT color=#008000&gt;2.3&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/TD&gt;
&lt;TD&gt;&lt;STRONG&gt;&lt;FONT color=#008000&gt;0x8010DB7C&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/TD&gt;
&lt;TD&gt;&lt;STRONG&gt;&lt;FONT color=#008000&gt;NK.EXE&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/TD&gt;
&lt;TD align=left&gt;&lt;STRONG&gt;&lt;FONT color=#008000&gt;PrefetchAbort&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR align=right&gt;
&lt;TD&gt;&lt;STRONG&gt;&lt;FONT color=#008000&gt;1732&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/TD&gt;
&lt;TD&gt;&lt;STRONG&gt;&lt;FONT color=#008000&gt;1.9&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/TD&gt;
&lt;TD&gt;&lt;STRONG&gt;&lt;FONT color=#008000&gt;0x80110EC0&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/TD&gt;
&lt;TD&gt;&lt;STRONG&gt;&lt;FONT color=#008000&gt;NK.EXE&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/TD&gt;
&lt;TD align=left&gt;&lt;STRONG&gt;&lt;FONT color=#008000&gt;ServerCallReturn&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR align=right&gt;
&lt;TD&gt;1518&lt;/TD&gt;
&lt;TD&gt;1.7&lt;/TD&gt;
&lt;TD&gt;0x801491D4&lt;/TD&gt;
&lt;TD&gt;NK.EXE&lt;/TD&gt;
&lt;TD align=left&gt;OEMWriteDebugByte&lt;/TD&gt;&lt;/TR&gt;
&lt;TR align=right&gt;
&lt;TD&gt;&lt;FONT color=#0000ff&gt;&lt;STRONG&gt;1468&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD&gt;&lt;FONT color=#0000ff&gt;&lt;STRONG&gt;1.6&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD&gt;&lt;FONT color=#0000ff&gt;&lt;STRONG&gt;0x8011A094&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD&gt;&lt;FONT color=#0000ff&gt;&lt;STRONG&gt;NK.EXE&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD align=left&gt;&lt;FONT color=#0000ff&gt;&lt;STRONG&gt;SleepOneMore&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR align=right&gt;
&lt;TD&gt;&lt;FONT color=#0000ff&gt;&lt;STRONG&gt;1460&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD&gt;&lt;FONT color=#0000ff&gt;&lt;STRONG&gt;1.6&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD&gt;&lt;FONT color=#0000ff&gt;&lt;STRONG&gt;0x8011BCDC&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD&gt;&lt;FONT color=#0000ff&gt;&lt;STRONG&gt;NK.EXE&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD align=left&gt;&lt;FONT color=#0000ff&gt;&lt;STRONG&gt;WaitOneMore&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR align=right&gt;
&lt;TD&gt;&lt;FONT color=#0000ff&gt;&lt;STRONG&gt;1418&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD&gt;&lt;FONT color=#0000ff&gt;&lt;STRONG&gt;1.6&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD&gt;&lt;FONT color=#0000ff&gt;&lt;STRONG&gt;0x80119360&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD&gt;&lt;FONT color=#0000ff&gt;&lt;STRONG&gt;NK.EXE&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD align=left&gt;&lt;FONT color=#0000ff&gt;&lt;STRONG&gt;KCNextThread&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR align=right&gt;
&lt;TD&gt;&lt;FONT color=#0000ff&gt;&lt;STRONG&gt;1405&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD&gt;&lt;FONT color=#0000ff&gt;&lt;STRONG&gt;1.6&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD&gt;&lt;FONT color=#0000ff&gt;&lt;STRONG&gt;0x8011C154&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD&gt;&lt;FONT color=#0000ff&gt;&lt;STRONG&gt;NK.EXE&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD align=left&gt;&lt;FONT color=#0000ff&gt;&lt;STRONG&gt;SC_WaitForMultiple&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR align=right&gt;
&lt;TD&gt;1404&lt;/TD&gt;
&lt;TD&gt;1.6&lt;/TD&gt;
&lt;TD&gt;0x8010E00C&lt;/TD&gt;
&lt;TD&gt;NK.EXE&lt;/TD&gt;
&lt;TD align=left&gt;IRQHandler&lt;/TD&gt;&lt;/TR&gt;
&lt;TR align=right&gt;
&lt;TD&gt;&lt;FONT color=#0000ff&gt;&lt;STRONG&gt;1255&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD&gt;&lt;FONT color=#0000ff&gt;&lt;STRONG&gt;1.4&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD&gt;&lt;FONT color=#0000ff&gt;&lt;STRONG&gt;0x8010DEC0&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD&gt;&lt;FONT color=#0000ff&gt;&lt;STRONG&gt;NK.EXE&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD align=left&gt;&lt;FONT color=#0000ff&gt;&lt;STRONG&gt;SaveAndReschedule&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR align=right&gt;
&lt;TD&gt;1212&lt;/TD&gt;
&lt;TD&gt;1.4&lt;/TD&gt;
&lt;TD&gt;0x03F73CA0&lt;/TD&gt;
&lt;TD&gt;coredll.dll&lt;/TD&gt;
&lt;TD align=left&gt;xxx_CeLogData&lt;/TD&gt;&lt;/TR&gt;
&lt;TR align=right&gt;
&lt;TD&gt;1145&lt;/TD&gt;
&lt;TD&gt;1.3&lt;/TD&gt;
&lt;TD&gt;0x03F68258&lt;/TD&gt;
&lt;TD&gt;coredll.dll&lt;/TD&gt;
&lt;TD align=left&gt;xxx_GetTickCount&lt;/TD&gt;&lt;/TR&gt;
&lt;TR align=right&gt;
&lt;TD&gt;&lt;FONT color=#0000ff&gt;&lt;STRONG&gt;979&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD&gt;&lt;FONT color=#0000ff&gt;&lt;STRONG&gt;1.1&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD&gt;&lt;FONT color=#0000ff&gt;&lt;STRONG&gt;0x8010EF34&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD&gt;&lt;FONT color=#0000ff&gt;&lt;STRONG&gt;NK.EXE&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD align=left&gt;&lt;FONT color=#0000ff&gt;&lt;STRONG&gt;KCALLPROFON&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR align=right&gt;
&lt;TD&gt;&lt;FONT color=#0000ff&gt;&lt;STRONG&gt;908&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD&gt;&lt;FONT color=#0000ff&gt;&lt;STRONG&gt;1.0&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD&gt;&lt;FONT color=#0000ff&gt;&lt;STRONG&gt;0x8010EFE0&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD&gt;&lt;FONT color=#0000ff&gt;&lt;STRONG&gt;NK.EXE&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD align=left&gt;&lt;FONT color=#0000ff&gt;&lt;STRONG&gt;KCALLPROFOFF&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR align=right&gt;
&lt;TD&gt;865&lt;/TD&gt;
&lt;TD&gt;1.0&lt;/TD&gt;
&lt;TD&gt;0x017A4544&lt;/TD&gt;
&lt;TD&gt;pxa27x_dma.dll&lt;/TD&gt;
&lt;TD align=left&gt;InterruptDone&lt;/TD&gt;&lt;/TR&gt;&lt;/TABLE&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;The lines in&amp;nbsp;green are all related to making API calls.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;The ones in&amp;nbsp;blue are all involved with thread rescheduling.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;I was a little suspicious about the number of API calls and the amount of thread rescheduling that was going on here.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;KCNextThread is the primary kernel function which selects the next thread to run, and having that show up 1.6 percent of the time is pretty significant.&amp;nbsp; The API call time might also&amp;nbsp;be partly blamed on calling into the kernel to reschedule.&lt;/P&gt;
&lt;P class=MsoNormal&gt;Then we looked at a Kernel Tracker trace for the same scenario, and saw the screen shots above.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;I realized how much thread switching was going on, and brought it to the attention of the folks who owned the code involved.&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;B&gt;The fix:&lt;/B&gt; They changed the design so that the work done between the two most active threads (UsbInterruptThreadStub and DmacIntrThread) was all on one thread instead of shared between two.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;As a result, the USB throughput jumped from 23Mbps to almost 41Mbps.&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;/P&gt;
&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=421057" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/sloh/archive/tags/CE+Performance+Tools/default.aspx">CE Performance Tools</category></item><item><title>Remote Kernel Tracker: More things you should recognize</title><link>http://blogs.msdn.com/sloh/archive/2005/05/21/Remote-Kernel-Tracker-2.aspx</link><pubDate>Sat, 21 May 2005 08:06:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:420687</guid><dc:creator>sloh</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/sloh/comments/420687.aspx</comments><wfw:commentRss>http://blogs.msdn.com/sloh/commentrss.aspx?PostID=420687</wfw:commentRss><description>&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;I have a few more examples of patterns you can recognize when you’re looking at CeLog threading data in Remote Kernel Tracker.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;I style="mso-bidi-font-style: normal"&gt;Note: these images are wacky heights because I tweaked them to cut off white space that didn’t contain any CeLog data.&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/I&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;SPAN style="FONT-SIZE: 14pt"&gt;Thread Migration&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;I realized that in &lt;A href="/sloh/archive/2005/05/17/418739.aspx"&gt;my previous Kernel Tracker post&lt;/A&gt; I meant to add a screen shot of thread migration, and forgot.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is an example of what thread migration looks like in Remote Kernel Tracker.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;There’s a raised dashed line which represents that the thread is still running, but inside a different process.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;EM&gt;(scroll down if you can't see anything)&lt;/EM&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;IMG src="http://cenet.members.winisp.net/sloh_files/kt_migrate.png"&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-ALIGN: center; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" align=center&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;Screen Shot 1:&lt;/B&gt; Example of what thread migration looks like.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;SPAN style="FONT-SIZE: 14pt"&gt;KITL / debug messages&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;I like this example which hammers home how much work is involved in heavy KITL traffic.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I run a program called enumfiles.exe which enumerates all of the files in the device file system.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The KITL traffic is due to a few different things: mainly the heavy debug messages, and the enumeration of files inside the release directory via RELFSD.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;(The release directory file system driver, which mounts the release directory from the desktop PC as \Release on the device.)&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In this case I also loaded the program over KITL from my release directory, so some of this traffic is the work copying code onto the device.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;IMG src="http://cenet.members.winisp.net/sloh_files/kt_kitl.png"&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-ALIGN: center; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" align=center&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;Screen Shot 2:&lt;/B&gt; For a program that’s just enumerating the file system, that’s a lot of time on the KITL thread.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;As you can see, when the enumfiles.exe program starts, a lot of other activity begins too.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The KITL interrupt (25 on this device) and the KITL IST start working overtime.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I like this example because it shows that your code doesn’t always live in the vacuum you might expect.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The system calls you make, or the pure existence of your program, can fire off other activity in the system.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Does the system &lt;I style="mso-bidi-font-style: normal"&gt;really&lt;/I&gt; behave as you expect?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Tools like CeLog and Remote Kernel Tracker are the way to find out for sure.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;I style="mso-bidi-font-style: normal"&gt;&lt;A href="/mikehall/"&gt;Mike Hall&lt;/A&gt; uses an older version of my enumfiles program (walktree.exe) when he gives labs to teach people how to use Remote Kernel Tracker, so if you’ve taken any labs from Mike at DevCons or other events, you may have played with this same program yourself!&lt;o:p&gt;&lt;/o:p&gt;&lt;/I&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" /&gt;&lt;st1:place w:st="on"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;SPAN style="FONT-SIZE: 14pt"&gt;Flushing&lt;/SPAN&gt;&lt;/B&gt;&lt;/st1:place&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;SPAN style="FONT-SIZE: 14pt"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;It’s good to know what activity represents side effects of data gathering itself.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Whether you have Remote Kernel Tracker actively connected to a device and collecting data, or you’re running CeLogFlush.exe to save data on a standalone device, the thread that manages the data impacts the system a little itself.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;First, &lt;B style="mso-bidi-font-weight: normal"&gt;Screen Shot 3&lt;/B&gt; shows CeLogFlush.exe flushing periodically.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In this case I specified that CeLogFlush.exe should flush at 3-second intervals, so that more than one flush would show in the same window.&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;IMG src="http://cenet.members.winisp.net/sloh_files/kt_CeLogFlush.png"&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-ALIGN: center; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" align=center&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;Screen Shot 3:&lt;/B&gt; CeLogFlush data flushing at 3 second intervals when data’s not being logged heavily.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;As you can see above, when there’s not a lot of activity, flushing can be a pretty fast operation.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The vertical lines showing a lot of thread switching aren’t very wide; the flush is over quickly.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;Incidentally, you can see that the switching is between the CeLogFlush.exe thread and the KITL thread – OK now tell me where I was storing the log file?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That’s right, in \Release which required KITL to transport the file data to the release directory on the PC.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Otherwise there’d be less thread switching because it could write to local storage on the device without switching to the KITL thread.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;In contrast, &lt;B style="mso-bidi-font-weight: normal"&gt;Screen Shot 4&lt;/B&gt; shows how much of a load flushing can be on a busy system.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;There are a lot more events being logged, so there is more data to flush and flushes take longer.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The RAM buffer that the data is temporarily stored in fills more quickly than 3 seconds, so the flushes are more frequent.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;IMG src="http://cenet.members.winisp.net/sloh_files/kt_CeLogFlush2.png"&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-ALIGN: center; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" align=center&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;Screen Shot 4:&lt;/B&gt; CeLogFlush flushing during heavy logging activity.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;For completeness I’m including &lt;B style="mso-bidi-font-weight: normal"&gt;Screen Shot 5&lt;/B&gt; which shows what flushes look like when you’re using Remote Kernel Tracker to transport the data to your PC, instead of using CeLogFlush.exe.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;You can see that RTH.EXE does the flushing, and that it flushes over KITL about once per second.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;IMG src="http://cenet.members.winisp.net/sloh_files/kt_RTHFlush.png"&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-ALIGN: center; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" align=center&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;Screen Shot 5:&lt;/B&gt; Remote Kernel Tracker data flushing.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;SPAN style="FONT-SIZE: 14pt"&gt;Data Loss&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;I wrote up a couple of sections about data loss in our recent newly-released CeLog documentation:&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 39pt; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo1; tab-stops: list 39.0pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-FAMILY: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol"&gt;&lt;SPAN style="mso-list: Ignore"&gt;·&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;A href="http://msdn.microsoft.com/library/en-us/wcedebug5/html/wce51conAnalyzingDataLossWithRemoteKernelTracker.asp"&gt;Analyzing Data Loss with Remote Kernel Tracker&lt;/A&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 39pt; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo1; tab-stops: list 39.0pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-FAMILY: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol"&gt;&lt;SPAN style="mso-list: Ignore"&gt;·&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;A href="http://msdn.microsoft.com/library/en-us/wcedebug5/html/wce51conRecognizingDataLossInReadlogexe.asp"&gt;Analyzing Data Loss with Readlog&lt;/A&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;But I could not include screen shots.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Here is a screen shot to show you how to recognize data loss when you’re looking at it in Remote Kernel Tracker.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;IMG src="http://cenet.members.winisp.net/sloh_files/kt_dataloss.png"&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-ALIGN: center; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" align=center&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;Screen Shot 6:&lt;/B&gt; The signs of data loss.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;The three characteristics I describe in the Kernel Tracker article are visible in &lt;B style="mso-bidi-font-weight: normal"&gt;Screen Shot 5&lt;/B&gt;.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;First, it pops up a dialog box telling you how many bytes of data have been lost over time in the log.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Second, the interrupt activity appears to stop completely, and one thread appears to be running for a long period.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In this screen shot I didn’t expand explorer.exe to show that thread, but it was a single thread and it had no icons showing events occurring during the thread run-time.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Finally, when activity picks up again, the flush thread (RTH.EXE) is busy working.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;All of these characteristics are strong hints that the apparently “inactive” period is really a period of time from which data was lost.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;SPAN style="FONT-SIZE: 14pt"&gt;More Tips&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;While I was poking around building up screen shots for this write-up, I caught one view that surprised me a bit.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Look how much priority inversion is going on here!&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is a database test program spewing lots of debug output.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;KITL isn’t something that actually requires “real” real-time, but perhaps I should get someone to examine why we hit priority inversion so regularly.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;IMG src="http://cenet.members.winisp.net/sloh_files/kt_prioinversion2.png"&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-ALIGN: center; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" align=center&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;Screen Shot 7:&lt;/B&gt; Debug output leading to lots of priority inversion.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;Let it be a lesson that while you’re testing real-time response in your system, you should disable KITL.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And that while you’re running performance tests, for heaven’s sake don’t write a lot of debug messages.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;Another little exercise.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;On the left and right of &lt;B style="mso-bidi-font-weight: normal"&gt;Screen Shot 7&lt;/B&gt; are some periods where activity drops dramatically.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Do those periods represent data loss?&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;The answer is no, because of two clues.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;First, SYSINTR 0 is still going strong.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Keep an eye on that whenever you’re running a profiling build.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'; mso-fareast-font-family: 'MS Mincho'; mso-ansi-language: EN-US; mso-fareast-language: JA; mso-bidi-language: AR-SA"&gt;(I’d say all the time but only profiling builds record interrupts.)&lt;/SPAN&gt; &lt;/SPAN&gt;SYSINTR 0 occurs frequently enough you should always be able to find it.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Second, there are lots of events occurring on the testdb.exe thread during those periods.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;There are so many icons drawn on that thread that they don’t show up clearly in this screen shot.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If it was data loss, there’d be no such activity.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Since this particular test program was writing a lot of debug output; the less busy periods probably represent time when the test was doing solid periods of work instead of printing debug messages.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When you’re not running a profiling build, look for events on the thread that was supposedly executing during the quiet period, to see if that really is a period of data loss.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=420687" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/sloh/archive/tags/CE+Performance+Tools/default.aspx">CE Performance Tools</category></item><item><title>Introduction to Remote Kernel Tracker</title><link>http://blogs.msdn.com/sloh/archive/2005/05/17/Introduction-to-Remote-Kernel-Tracker.aspx</link><pubDate>Tue, 17 May 2005 17:52:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:418739</guid><dc:creator>sloh</dc:creator><slash:comments>9</slash:comments><comments>http://blogs.msdn.com/sloh/comments/418739.aspx</comments><wfw:commentRss>http://blogs.msdn.com/sloh/commentrss.aspx?PostID=418739</wfw:commentRss><description>&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;When you connect to a device with Remote Kernel Tracker, or when you open a log file that has been collected by one of the other CeLog tools, you’ll see a lot of data you may not understand.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;At MEDC this past week, a few people asked for a better explanation of what they’re seeing.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So let’s go over it.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;Screen Shot 1&lt;/B&gt; shows a sample of what you might typically see when you connect Remote Kernel Tracker to a device:&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;EM&gt;(scroll down if you can't see anything)&lt;/EM&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&amp;nbsp;&lt;IMG src="http://cenet.members.winisp.net/sloh_files/kt_idle1.png"&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-ALIGN: center" align=center&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;Screen Shot 1:&lt;/B&gt; Typical idle behavior, no processes expanded.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Someone asked me what all the information in the key means.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I’ll go through them a bit at a time.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;First, the thread and process state lines.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;IMG src="http://cenet.members.winisp.net/sloh_files/kt_icons_state.png"&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;You can see examples of the process state lines in &lt;B style="mso-bidi-font-weight: normal"&gt;Screen Shot 1&lt;/B&gt; above.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Each process in the system has a horizontal line.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When one of the threads owned by that process is running, the process line is wide and dark green.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Otherwise the process line is thin and black.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;(In case it’s not clear, only one thread ever runs at a time, so only one process ever runs at a time too.)&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So in the example above, threads owned by kernel (nk.exe) are running almost all the time.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The vertical lines you see are due to threads in other processes running for very short periods of time.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Remote Kernel Tracker draws vertical lines to represent switches between threads, to make it easier to see which threads ran before and after the thread switch.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Underneath each process are all the threads owned by that process.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Processes can be expanded and collapsed to show and hide the threads, for easy viewing.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;There are no thread lines in &lt;B style="mso-bidi-font-weight: normal"&gt;Screen Shot 1&lt;/B&gt;, because none of the processes have been expanded to display their threads yet.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;Screen Shot 2&lt;/B&gt; shows the same log, with some of the process lines expanded and with the key hidden for better viewing.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;IMG src="http://cenet.members.winisp.net/sloh_files/kt_idle2.png"&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-ALIGN: center" align=center&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;Screen Shot 2:&lt;/B&gt; Typical idle behavior, interrupts and some processes expanded.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;In &lt;B style="mso-bidi-font-weight: normal"&gt;Screen Shot 2&lt;/B&gt; you can see some thread lines too.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Like the process lines, the thread lines are wide and light green whenever the threads are running, and thin when they are not. Most of the threads, except for “0x00000000,” run for such short times that at the zoom level shown in this screen shot, that you can’t see the horizontal thread-run lines, but you can tell that they ran because you can see the vertical thread-switch lines.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;On the threads you can also see some other icons representing the actions taken by the threads.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;More on these later.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;You can also see that interrupts are represented as lines too, with one line for each SYSINTR value to show when interrupts occur.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;What you’re seeing in these screen shots is typical idle activity on a device.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The thread with handle “0x00000000” is not really a thread, but the placeholder to represent when the CPU is idle.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Most of the other threads that run now and then are interrupt service threads (ISTs).&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Every process will have one thread which has the same name as the process; that is the process’s primary thread, the one which starts running at &lt;SPAN style="FONT-FAMILY: 'Courier New'"&gt;main()&lt;/SPAN&gt; or &lt;SPAN style="FONT-FAMILY: 'Courier New'"&gt;WinMain()&lt;/SPAN&gt; or whatever flavor of entry point the process might use.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;All of the other threads in the process are given the name of the thread’s start routine, such as KITLInterruptThread under the process “NK.EXE” (the kernel).&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;An important detail to note at this point is that some of the features you can see here are due to the fact that you are running a profiling build.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;First, to minimize the impact of the logging hooks which record this data, interrupt data is only available on profiling builds.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When the profiler is not present, the “Interrupts” line will not appear.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Second, the thread names are also only available on profiling builds.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Remote Kernel Tracker does not look up thread names from the symbol files in the release directory.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Instead, on profiling builds the CeLog event logging hooks obtain thread names via the special symbol table that is included in ROM for use by the profiler, to represent all the code that is stored in &lt;?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" /&gt;&lt;st1:country-region w:st="on"&gt;&lt;st1:place w:st="on"&gt;ROM.&lt;/st1:place&gt;&lt;/st1:country-region&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The profiler uses that symbol table to look up symbols for profiling hits, and the logging hooks take advantage of the symbol table in order to provide thread names.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Threads from processes and DLLs that are not stored in the “modules” section of ROM will not have names, since they will not be listed in the profiler’s symbol table.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And on non-profiling builds, no threads will have names.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;There is also a trick you can use to make the desktop tool “readlog.exe” look up symbols from the release directory and build a new log file containing the thread names on any build and regardless of where the thread’s code is running from.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I don’t quite have documentation to point you to about that yet, but open up a release directory build window and type “readlog -?” on the command line to find out how to use readlog.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;The other thread line I haven’t discussed yet is the Thread Migrate line.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In Windows CE, when a thread calls a system API that is implemented by a different process, the thread moves from its owner process into the system process for the duration of the call.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The Thread Migrate line in Remote Kernel Tracker represents the period of time during which the thread is executing inside a process other than its owner.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;You can hover over the line to learn which process the thread is executing inside.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;In my opinion, this representation of thread migration is not terribly useful.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It helps you see when a thread is running inside a process other than its owner, but it does not help you see the entire set of processes the thread transitions to.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For example if your thread calls an API, and that API calls a different API, your thread may actually transition through multiple processes, but it is not easy to see if or when those transitions occur.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Nor does it help you understand why those transitions took place (which APIs the thread was calling).&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Back to the event types in the key.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The main events I pay attention to when I’m looking at a log in Remote Kernel Tracker are a subset of those related to thread scheduling:&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;IMG src="http://cenet.members.winisp.net/sloh_files/kt_icons_scheduling.png"&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;If you are familiar with the Win32 API set, you probably can guess what these mean.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The critical section events represent when threads call the EnterCriticalSection and LeaveCriticalSection functions, and encounter contention over the critical section object.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Critical sections are used so widely that logging every entry and exit would generate too many events and bog down system performance.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So only those calls which block the current thread or unblock another thread are logged.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The Set Event, Reset Event and Pulse Event events represent actions taken on Win32 “event” objects.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Similarly the Release Semaphore and Release Mutex events represent actions on Win32 semaphore and mutex objects.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The wait event represents a call to the Win32 WaitForSingleObject or WaitForMultipleObjects APIs, regardless of whether the thread blocks on those objects or not.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Finally, the Sleep Event event represents when the thread calls the Win32 Sleep API.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In general I am not a big fan of Sleep, at least non-zero Sleep periods.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Often it represents lazy programming, and results in polling that churns CPU time and drains power.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For example, observe the behavior of the selected thread in &lt;B style="mso-bidi-font-weight: normal"&gt;Screen Shot 3&lt;/B&gt; below.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This thread is polling at 500ms intervals.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;IMG src="http://cenet.members.winisp.net/sloh_files/kt_sleep.png"&gt;&lt;/P&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-ALIGN: center" align=center&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;Screen Shot 3:&lt;/B&gt; Using Sleep to poll at regular intervals consumes CPU and drains power.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;If you hunt around most logs, you’ll find cases where one thread will call the SetEvent API, then another thread will start running, do some work, and then block again in WaitForMultipleObjects on the same event handle.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;IMG src="http://cenet.members.winisp.net/sloh_files/kt_wait.png"&gt;&lt;/P&gt;&lt;SPAN style="mso-spacerun: yes"&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-ALIGN: center" align=center&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;Screen Shot 4:&lt;/B&gt; A waiting thread is awakened when another thread signals an object.&lt;/P&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'; mso-fareast-font-family: 'MS Mincho'; mso-fareast-language: JA; mso-ansi-language: EN-US; mso-bidi-language: AR-SA"&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;In &lt;B style="mso-bidi-font-weight: normal"&gt;Screen Shot 4&lt;/B&gt; you can see that the threadsample.exe main thread set an event (the “flag” icon) that the last thread in the same process was waiting for.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In this screen shot I double-clicked on the WaitForMultipleObjects event and the Set Event event to show their data.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This often makes it easier to compare handle values between events.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I know these two events are related because they both apply to handle value “0xA3E0FF96” in this case.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;There are a few other events I also look at when I’m examining logs.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;IMG src="http://cenet.members.winisp.net/sloh_files/kt_icons_misc.png"&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;The interrupt event you’ve already seen above, representing when interrupt service routines (ISRs) execute.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It’s worth mentioning that you can see relationships between interrupt service routines (ISRs) running – the “interrupt” events you see in Kernel Tracker – and their corresponding interrupt service threads (ISTs) waking up to do further interrupt handling.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In &lt;B style="mso-bidi-font-weight: normal"&gt;Screen Shot 5&lt;/B&gt; below, you can see the ISR for SYSINTR 1 (the timer interrupt, I believe?) run, and then two different ISTs follow up.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;You can also see the ISR for SYSINTR 30 (the KITL interrupt) run, and the KITLInterruptThread wake up to do some work.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If you look back at &lt;B style="mso-bidi-font-weight: normal"&gt;Screen Shot 2&lt;/B&gt; above, you can also see this relationship between the KITL interrupt and KITLInterruptThread when scaled back to a larger zoom level.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Note that no IST runs for SYSINTR 0, which is a no-op.&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;IMG src="http://cenet.members.winisp.net/sloh_files/kt_IST.png"&gt;&lt;/P&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-ALIGN: center" align=center&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;Screen Shot 5:&lt;/B&gt; The relationship between ISRs and ISTs.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;The Invert Priorities event is shown on a thread when the kernel temporarily changes the thread’s priority because it holds a resource that some other higher-priority thread needs.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For example, if a low-priority thread holds a critical section that a high-priority thread tries to enter, the kernel temporarily boosts the low-priority thread to a high priority, to execute until it releases the critical section.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Then the low-priority thread returns to its original priority.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For real-time behavior, you never want real-time threads to block on resources owned by lower-priority threads, since those threads may do an undetermined amount of work before releasing the resources.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;Screen Shot 6&lt;/B&gt; is an example of a case where a higher-priority thread ends up boosting the priority of another thread over and over again.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;IMG src="http://cenet.members.winisp.net/sloh_files/kt_prioinversion.png"&gt;&lt;/P&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-ALIGN: center" align=center&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;Screen Shot 6:&lt;/B&gt; Recurring cases of priority inversion.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;The icons in &lt;B style="mso-bidi-font-weight: normal"&gt;Screen Shot 6&lt;/B&gt; are a little&amp;nbsp;hard to see&amp;nbsp;– sorry – but what’s going on is that a high-priority IST in the kernel enters a critical section that is held every time by a low-priority thread from testdb.exe.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The kernel thread logs a priority-inversion event representing the priority-boost given to the testdb.exe thread.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Then the kernel thread blocks on the critical section.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The now-high-priority testdb.exe thread runs until it leaves the critical section, then logs a priority-inversion event representing its return to its regular priority.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The kernel thread then begins running again, now that it owns the critical section and is the highest-priority thread.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;You can see in this log that the inversion happens regularly in this particular case.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;The page fault event represents a costly page fault operation occurring on a thread.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In CE 4.2 and earlier, a page fault event was logged at the beginning of a page fault; in CE 5.0 and later, an event is also logged at the end of the page fault so that you can tell how long the page fault took.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I don’t see this event often, but sometimes I see cases like this, where a thread incurs many page faults:&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;IMG src="http://cenet.members.winisp.net/sloh_files/kt_pagefault.png"&gt;&lt;/P&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-ALIGN: center" align=center&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;Screen Shot 7:&lt;/B&gt; A thread incurring many page faults.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This log is from CE 5.0 so the fault markers are in begin/end pairs so that you can tell how long they took.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;When I see many page faults like this, I run the readlog.exe command-line tool to get a summary of the faults, to determine where they are occurring.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In general the important thing to check is whether the fault address is paged more than once.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Code must be paged once in order to execute at all, but if it is paged more than once, that means the kernel’s page pool is not large enough to hold all the executing code.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In that case the page pool may need to be enlarged.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If data such as memory-mapped files is paged more than once, then the data may not have good page locality, or the system may be in a low-memory state.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'; mso-fareast-font-family: 'MS Mincho'; mso-fareast-language: JA; mso-ansi-language: EN-US; mso-bidi-language: AR-SA"&gt;You can also log your own events from your code.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Since Remote Kernel Tracker does not have the ability to interpret your data blobs, you may find it useful to log your data using a set of event types that Remote Kernel Tracker does understand:&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;IMG src="http://cenet.members.winisp.net/sloh_files/kt_icons_user.png"&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;When Remote Kernel Tracker sees one of these event types, it expects the data logged for that event to be an array of the given type.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For example, for the “Raw ulong” type Remote Kernel Tracker interprets the data as an array of unsigned long integers (DWORDs).&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;IMG src="http://cenet.members.winisp.net/sloh_files/kt_raw3.png"&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'; mso-fareast-font-family: 'MS Mincho'; mso-fareast-language: JA; mso-ansi-language: EN-US; mso-bidi-language: AR-SA"&gt;For the “Raw wchar” type the data is an array of Unicode characters, and Remote Kernel Tracker will display it as a string.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;IMG src="http://cenet.members.winisp.net/sloh_files/kt_raw2.png"&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;To see the data corresponding to one of these event types, hover over the event to see the tooltip, or double-click on the event to get the data in a separate window.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Note also that the data is displayed in the bottom-left status bar when you click on an event.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;IMG src="http://cenet.members.winisp.net/sloh_files/kt_raw.png"&gt;&lt;/P&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-ALIGN: center" align=center&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;Screen Shot 8:&lt;/B&gt; Viewing “raw” data in Remote Kernel Tracker.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;/o:p&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;SPAN style="FONT-SIZE: 14pt"&gt;In Summary&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;I hope I have helped you understand what the tool is showing you, and see some of the things you can use CeLog and Remote Kernel Tracker for.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is a very versatile tool.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It might take some practice to recognize these relationships between events, but a basic understanding of what thread behavior looks like in Kernel Tracker is the first thing you need when you’re troubleshooting a wide range of performance problems.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Remote &lt;SPAN style="mso-bidi-font-weight: bold"&gt;Kernel Tracker&lt;/SPAN&gt; enables you to track down bugs related to thread interactions that are difficult to track with traditional development tools, including deadlocks, race conditions, excessive context switching or priority problems.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;I have some more posts coming in the near future, about more scenarios you can recognize when you get used to Remote Kernel Tracker.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=418739" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/sloh/archive/tags/CE+Performance+Tools/default.aspx">CE Performance Tools</category></item><item><title>CeLog documentation</title><link>http://blogs.msdn.com/sloh/archive/2005/05/16/417936.aspx</link><pubDate>Mon, 16 May 2005 16:55:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:417936</guid><dc:creator>sloh</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/sloh/comments/417936.aspx</comments><wfw:commentRss>http://blogs.msdn.com/sloh/commentrss.aspx?PostID=417936</wfw:commentRss><description>&lt;P&gt;At long last, a big chunk of work I did to add documentation of CeLog &amp;amp; Remote Kernel Tracker has finally shown up in a form you can view.&lt;/P&gt;
&lt;P&gt;&lt;A href="http://msdn.microsoft.com/library/en-us/wcedebug5/html/wce50conEventTracking.asp"&gt;http://msdn.microsoft.com/library/en-us/wcedebug5/html/wce50conEventTracking.asp&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;I did a huge brain dump and tried to get all of my tips &amp;amp; tricks down on paper.&amp;nbsp; There are descriptions of how to use tools to gather data on standalone devices, how to log your own data and how to customize the tools.&amp;nbsp; There is a little bit&amp;nbsp;more work&amp;nbsp;to go -- some information really required Kernel Tracker screen shots, and right now we can't include screen shots in our documentation.&amp;nbsp; We've been discussing other formats to release the information in, but for now I am planning to post a bunch of it on my blog.&amp;nbsp; I have it mostly written up, but am trying to set up a web share to hold the pictures.&amp;nbsp; (I don't have any storage space to use with my blog, so I can only post text at the moment, but that should change soon.)&lt;/P&gt;
&lt;P&gt;So look for more in the coming days!&amp;nbsp; I got to show off Remote Kernel Tracker to a lot of folks&amp;nbsp;at MEDC, and got some good questions.&amp;nbsp; I hope that between the documentation posted above and the material I'll add to my blog soon, you'll get to be as much an expert in using CeLog and Remote Kernel Tracker as I am.&lt;/P&gt;
&lt;P&gt;Happy logging!&lt;/P&gt;
&lt;P&gt;Sue&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=417936" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/sloh/archive/tags/CE+Performance+Tools/default.aspx">CE Performance Tools</category></item><item><title>What WINDOWS CE debugging tools would you like to see?</title><link>http://blogs.msdn.com/sloh/archive/2004/08/31/223430.aspx</link><pubDate>Tue, 31 Aug 2004 20:09:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:223430</guid><dc:creator>sloh</dc:creator><slash:comments>7</slash:comments><comments>http://blogs.msdn.com/sloh/comments/223430.aspx</comments><wfw:commentRss>http://blogs.msdn.com/sloh/commentrss.aspx?PostID=223430</wfw:commentRss><description>&lt;p&gt;Just an informal survey -- I use some of our tools all the time, some rarely.&amp;nbsp; I have my own nitpicks I'd like fixed and features I'd like to see added.&amp;nbsp; But there's no guarantee I see the world the way you do.&amp;nbsp; What are your opinions?&lt;/p&gt; &lt;p&gt;Here are some ideas of my own, to get the conversation started:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Remote regedit: Export/import data under a key.&amp;nbsp; Track and report changes under a key. &lt;li&gt;Remote performance monitor: More counters! &lt;li&gt;Kernel profiler: UI in the remote tools menu in addition to the on-device control we already have. &lt;li&gt;Remote kernel tracker... don't even get me started, I love this tool but have lots of features I want added.&amp;nbsp; What would YOU ask for? &lt;li&gt;Does anybody use Remote Heap Walker?? &lt;li&gt;I'd say we need to add a&amp;nbsp;memory visualization tool that shows you what&amp;nbsp;parts of the VM space are used&amp;nbsp;-- something like "mi full" from the target control window. &lt;li&gt;I also think we need to add a handle enumerator -- eg. to find out what file handles are open (and by whom), window handles, etc.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Tell&amp;nbsp;me what you think is most important!&amp;nbsp; What's the #1 debugging tool you wish you had?&amp;nbsp; What's the #1 feature our existing tools are missing?&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=223430" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/sloh/archive/tags/CE+Performance+Tools/default.aspx">CE Performance Tools</category></item><item><title>Thread Lab materials are posted for EDC participants</title><link>http://blogs.msdn.com/sloh/archive/2004/07/06/173979.aspx</link><pubDate>Tue, 06 Jul 2004 16:59:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:173979</guid><dc:creator>sloh</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/sloh/comments/173979.aspx</comments><wfw:commentRss>http://blogs.msdn.com/sloh/commentrss.aspx?PostID=173979</wfw:commentRss><description>&lt;P&gt;They've finally posted my thread lab handouts and code up on &lt;A href="http://www.edccontent.com"&gt;www.edccontent.com&lt;/A&gt;.&amp;nbsp; So if you went to DevCon and need that material, you can get it now.&amp;nbsp; The handout contains everything I talked about in my hands-off lab, but also has some details I didn't, mostly samples of other threads (explorer.exe, cmd.exe) interfering with program behavior.&amp;nbsp; Also check out the explanation of how to recognize data loss in section 5.&lt;/P&gt;
&lt;P&gt;If you didn't attend EDC and don't have access to the materials, I don't think I am supposed to give them out.&amp;nbsp; But I will be working to make them generally available one way or another -- hopefully to integrate them into&amp;nbsp;Platform Builder&amp;nbsp;help.&lt;/P&gt;
&lt;P&gt;Sue&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=173979" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/sloh/archive/tags/Misc.+Fun/default.aspx">Misc. Fun</category><category domain="http://blogs.msdn.com/sloh/archive/tags/CE+Performance+Tools/default.aspx">CE Performance Tools</category></item><item><title>I survived!</title><link>http://blogs.msdn.com/sloh/archive/2004/07/02/172055.aspx</link><pubDate>Fri, 02 Jul 2004 21:49:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:172055</guid><dc:creator>sloh</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/sloh/comments/172055.aspx</comments><wfw:commentRss>http://blogs.msdn.com/sloh/commentrss.aspx?PostID=172055</wfw:commentRss><description>&lt;P&gt;Hooray, I survived DevCon!&amp;nbsp; The kernel talk and perf talk were ready to go by Monday, and after many short nights last week and this week, my lab was ready &amp;#8220;enough&amp;#8221; by Wednesday morning.&amp;nbsp; The handouts are missing some screenshots and a lot of polish.&amp;nbsp; The program I demo'd with was not quite as complete as I had hoped.&amp;nbsp; But overall I think the content was good.&lt;/P&gt;
&lt;P&gt;Sounds like I need to work on my presentation skills :-(&amp;nbsp;so my apologies to any attendees who went to my talks.&amp;nbsp; Even though I know the material I guess I still get too nervous speaking about it.&amp;nbsp; The kernel talk was really too much for one session; it should have been a 100-level basics talk plus a 200- or 300- level OAL &amp;amp; driver development talk.&amp;nbsp; I goofed my lab and ran 15 minutes beyond time, because I had the wrong end time in mind, and a lot of material to cover.&amp;nbsp; I should have skipped going over how I built my image, and just dived right into the meat of things.&lt;/P&gt;
&lt;P&gt;Ahh well.&amp;nbsp; Hopefully someone benefited.&amp;nbsp; I'll be cleaning up my lab materials &amp;amp; demo code shortly, and hope to get it all into our SDK documentation or something.&amp;nbsp; I'm pretty excited about my lab handouts because I think they contain a lot of information people haven't easily found on their own before.&lt;/P&gt;
&lt;P&gt;Sue&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=172055" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/sloh/archive/tags/Misc.+Fun/default.aspx">Misc. Fun</category><category domain="http://blogs.msdn.com/sloh/archive/tags/CE+Performance+Tools/default.aspx">CE Performance Tools</category></item><item><title>Another DevCon talk</title><link>http://blogs.msdn.com/sloh/archive/2004/05/17/133664.aspx</link><pubDate>Tue, 18 May 2004 01:59:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:133664</guid><dc:creator>sloh</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/sloh/comments/133664.aspx</comments><wfw:commentRss>http://blogs.msdn.com/sloh/commentrss.aspx?PostID=133664</wfw:commentRss><description>&lt;P&gt;Looks like I'll also be giving&amp;nbsp; the &amp;#8220;Inside the Windows CE Kernel&amp;#8221; talk at DevCon.&amp;nbsp; It means a little bit of studying for me but it shouldn't be a disaster.&amp;nbsp; It's a lot of content for an hour though.&lt;/P&gt;
&lt;P&gt;I think my Hands-On Lab with CeLog/Kernel Tracker was turned into a Hands-Off Lab.&amp;nbsp; Which is too bad, so many people don't use our tools because they're intimidated, when it's actually very easy.&amp;nbsp; I would like to develop&amp;nbsp;the&amp;nbsp;content in a way that it can be converted to a hands-on lab anyway, say with a typical CEPC, so that people could go through it separately on their own time.&lt;/P&gt;
&lt;P&gt;Get excited about DevCon!&amp;nbsp; I am!&lt;/P&gt;
&lt;P&gt;Sue&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=133664" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/sloh/archive/tags/Misc.+Fun/default.aspx">Misc. Fun</category><category domain="http://blogs.msdn.com/sloh/archive/tags/CE+Performance+Tools/default.aspx">CE Performance Tools</category></item><item><title>See you at DevCon!</title><link>http://blogs.msdn.com/sloh/archive/2004/05/10/129453.aspx</link><pubDate>Tue, 11 May 2004 02:43:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:129453</guid><dc:creator>sloh</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/sloh/comments/129453.aspx</comments><wfw:commentRss>http://blogs.msdn.com/sloh/commentrss.aspx?PostID=129453</wfw:commentRss><description>&lt;P&gt;Sorry I haven't been posting any content.&amp;nbsp; Mainly I expect content to come out of newsgroup interaction and general customer questions, and I have been a slacker about being on the newsgroups.&amp;nbsp; Too many high-priority things going on right now.&lt;/P&gt;
&lt;P&gt;I'll be giving a talk (&amp;#8220;Tools and Techniques for Investigating Performance Problems on Windows CE-based Devices&amp;#8220;) and a hands-on lab (&amp;#8221;Tools and Methods for Examining Thread Behavior in Windows CE&amp;#8221;)&amp;nbsp;at the Windows Embedded DevCon in June.&amp;nbsp; So this will be your chance to pick&amp;nbsp;my brain for how to use our profiling and threading tools.&amp;nbsp; Suggestions and questions about my talks are more than welcome, they're encouraged!&lt;/P&gt;
&lt;P&gt;You can find abstracts for these&amp;nbsp;and all the other DevCon content at:&amp;nbsp; &lt;A href="http://www.windowsembeddeddevcon.com/tech_content.asp"&gt;http://www.windowsembeddeddevcon.com/tech_content.asp&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;[Yikes, why did I make the titles so long?]&lt;/P&gt;
&lt;P&gt;Sue&lt;/P&gt;
&lt;HR id=null&gt;

&lt;P&gt; This posting is provided "AS IS" with no warranties, and confers no rights. &lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=129453" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/sloh/archive/tags/Misc.+Fun/default.aspx">Misc. Fun</category><category domain="http://blogs.msdn.com/sloh/archive/tags/CE+Performance+Tools/default.aspx">CE Performance Tools</category></item></channel></rss>