Viewing lock lifetimes
I added some more monitoring to the deadlock tool. You can now view the entire life cycle of the locks, from initialisation, through usage to destruction. The lock usage figures put the contention figures in context as you can see how often the lock was acquired by each thread and compare that to how often there was contention…
Note: the deadlock detector mentioned in this blog post is now available for download from www.lockexplorer.com.
Lock usage for: 0x0012fbe8
Initialised
by thread: 4500 @ 601
Location: 601
MTSCSS - I:\JetByteTools\Win32Tools\ThreadedCallbackTimerQueue.cpp: 56 - Win32::CThreadedCallbackTimerQueue::CThreadedCallbackTimerQueue
MTSCSS - I:\MTSCSS\ServerMain.cpp: 302 - ServerMain
MTSCSS - I:\MTSCSS\ServerMain.cpp: 651 - wWinMain
MTSCSS - _wWinMainCRTStartup
Locked
by thread: 2740 @ 603 41 times
by thread: 4960 @ 691 17 times
by thread: 5880 @ 772 13 times
by thread: 6020 @ 932 13 times
Location: 603
MTSCSS - I:\JetByteTools\Win32Tools\CriticalSection.cpp: 99 - Win32::CCriticalSection::Owner::Owner
MTSCSS - I:\JetByteTools\Win32Tools\ThreadedCallbackTimerQueue.cpp: 152 - Win32::CThreadedCallbackTimerQueue::GetNextTimeout
MTSCSS - I:\JetByteTools\Win32Tools\ThreadedCallbackTimerQueue.cpp: 133 - Win32::CThreadedCallbackTimerQueue::Run
MTSCSS - I:\JetByteTools\Win32Tools\Thread.cpp: 149 - Win32::CThread::ThreadFunction
MTSCSS - __beginthreadex
Location: 691
MTSCSS - I:\JetByteTools\Win32Tools\CriticalSection.cpp: 99 - Win32::CCriticalSection::Owner::Owner
MTSCSS - I:\JetByteTools\Win32Tools\ThreadedCallbackTimerQueue.cpp: 77 - Win32::CThreadedCallbackTimerQueue::CreateTimer
MTSCSS - I:\MTSCSS\ProtocolHandler.cpp: 102 - CProtocolHandler::CProtocolHandler
MTSCSS - Socket::CAsyncSocket::`vftable'
MTSCSS - I:\JetByteTools\SocketTools\AsyncSocket.cpp: 410 - Socket::CAsyncSocket::Read
Location: 772
MTSCSS - I:\JetByteTools\Win32Tools\CriticalSection.cpp: 99 - Win32::CCriticalSection::Owner::Owner
MTSCSS - I:\JetByteTools\Win32Tools\ThreadedCallbackTimerQueue.cpp: 100 - Win32::CThreadedCallbackTimerQueue::CancelTimer
MTSCSS - I:\MTSCSS\ProtocolHandler.cpp: 109 - CProtocolHandler::~CProtocolHandler
MTSCSS - CProtocolHandler::`vftable'
MTSCSS - I:\MTSCSS\ProtocolHandler.cpp: 515 - CProtocolHandler::OnConnectionFailed
Location: 932
MTSCSS - I:\JetByteTools\Win32Tools\CriticalSection.cpp: 99 - Win32::CCriticalSection::Owner::Owner
MTSCSS - I:\JetByteTools\Win32Tools\ThreadedCallbackTimerQueue.cpp: 100 - Win32::CThreadedCallbackTimerQueue::CancelTimer
MTSCSS - I:\MTSCSS\ProtocolHandler.cpp: 179 - CProtocolHandler::OnDataReceived
MTSCSS - I:\MTSCSS\OutgoingSocketServer.cpp: 238 - COutgoingSocketServer::OnDataAvailable
Unlocked
by thread: 2740 @ 604 41 times
by thread: 4960 @ 692 17 times
by thread: 5880 @ 773 13 times
by thread: 6020 @ 933 13 times
Location: 604
MTSCSS - I:\JetByteTools\Win32Tools\CriticalSection.cpp: 104 - Win32::CCriticalSection::Owner::~Owner
MTSCSS - I:\JetByteTools\Win32Tools\ThreadedCallbackTimerQueue.cpp: 154 - Win32::CThreadedCallbackTimerQueue::GetNextTimeout
MTSCSS - I:\JetByteTools\Win32Tools\ThreadedCallbackTimerQueue.cpp: 133 - Win32::CThreadedCallbackTimerQueue::Run
MTSCSS - I:\JetByteTools\Win32Tools\Thread.cpp: 149 - Win32::CThread::ThreadFunction
MTSCSS - __beginthreadex
Location: 692
MTSCSS - I:\JetByteTools\Win32Tools\CriticalSection.cpp: 104 - Win32::CCriticalSection::Owner::~Owner
MTSCSS - I:\JetByteTools\Win32Tools\ThreadedCallbackTimerQueue.cpp: 79 - Win32::CThreadedCallbackTimerQueue::CreateTimer
MTSCSS - I:\MTSCSS\ProtocolHandler.cpp: 102 - CProtocolHandler::CProtocolHandler
MTSCSS - Socket::CAsyncSocket::`vftable'
MTSCSS - I:\JetByteTools\SocketTools\AsyncSocket.cpp: 410 - Socket::CAsyncSocket::Read
Location: 773
MTSCSS - I:\JetByteTools\Win32Tools\CriticalSection.cpp: 104 - Win32::CCriticalSection::Owner::~Owner
MTSCSS - I:\JetByteTools\Win32Tools\ThreadedCallbackTimerQueue.cpp: 106 - Win32::CThreadedCallbackTimerQueue::CancelTimer
MTSCSS - I:\MTSCSS\ProtocolHandler.cpp: 109 - CProtocolHandler::~CProtocolHandler
MTSCSS - CProtocolHandler::`vftable'
MTSCSS - I:\MTSCSS\ProtocolHandler.cpp: 515 - CProtocolHandler::OnConnectionFailed
Location: 933
MTSCSS - I:\JetByteTools\Win32Tools\CriticalSection.cpp: 104 - Win32::CCriticalSection::Owner::~Owner
MTSCSS - I:\JetByteTools\Win32Tools\ThreadedCallbackTimerQueue.cpp: 106 - Win32::CThreadedCallbackTimerQueue::CancelTimer
MTSCSS - I:\MTSCSS\ProtocolHandler.cpp: 179 - CProtocolHandler::OnDataReceived
MTSCSS - I:\MTSCSS\OutgoingSocketServer.cpp: 238 - COutgoingSocketServer::OnDataAvailable
Deleted
by thread: 4500 @ 1026
Location: 1026
MTSCSS - I:\JetByteTools\Win32Tools\ThreadedCallbackTimerQueue.cpp: 73 - Win32::CThreadedCallbackTimerQueue::~CThreadedCallbackTimerQueue
MTSCSS - I:\MTSCSS\ServerMain.cpp: 403 - ServerMain
MTSCSS - I:\MTSCSS\ServerMain.cpp: 651 - wWinMain
MTSCSS - _wWinMainCRTStartup
Lock contention for: 0x0012fbe8
Thread: 5880 blocked @ 774 by thread: 2740 @ 603 1 times
Location: 603
MTSCSS - I:\JetByteTools\Win32Tools\CriticalSection.cpp: 99 - Win32::CCriticalSection::Owner::Owner
MTSCSS - I:\JetByteTools\Win32Tools\ThreadedCallbackTimerQueue.cpp: 152 - Win32::CThreadedCallbackTimerQueue::GetNextTimeout
MTSCSS - I:\JetByteTools\Win32Tools\ThreadedCallbackTimerQueue.cpp: 133 - Win32::CThreadedCallbackTimerQueue::Run
MTSCSS - I:\JetByteTools\Win32Tools\Thread.cpp: 149 - Win32::CThread::ThreadFunction
MTSCSS - __beginthreadex
Location: 774
MTSCSS - I:\JetByteTools\Win32Tools\CriticalSection.cpp: 99 - Win32::CCriticalSection::Owner::Owner
MTSCSS - I:\JetByteTools\Win32Tools\ThreadedCallbackTimerQueue.cpp: 112 - Win32::CThreadedCallbackTimerQueue::DestroyTimer
MTSCSS - I:\MTSCSS\ProtocolHandler.cpp: 111 - CProtocolHandler::~CProtocolHandler
MTSCSS - CProtocolHandler::`vftable'
MTSCSS - I:\MTSCSS\ProtocolHandler.cpp: 515 - CProtocolHandler::OnConnectionFailed
I also added per thread lock operation tracking, which allows you to see what each thread does to which locks, in which order. I’m starting to drown in data now and I think I’m reaching the point where a GUI is required…
One of the interesting things about the lock operation tracking is that I display the tick count when the operation took place. The idea was to display contention time for locks, ie how long a lock operation was blocked for, but unfortunately all this does is clearly illustrates that GetTickCount()
isn’t anywhere near accurate enough for this kind of thing; but I expected as much. As Raymond Chen points out GetTickCount()
has high precision but low accuracy. A link from Raymond’s comments led me to the Nvidia developer site which has some timer testing code available here, I think I’ll take a look at the alternatives and see if I can get some results that are more useful…