logman is your tool for this. Here is how you can query for all the sessions and also how to see values from a particular session.
c:\> logman -ets
Data Collector Set Type Status
-------------------------------------------------------------------------------
AITEventLog Trace Running
Audio Trace Running
DiagLog Trace Running
EventLog-Application Trace Running
EventLog-System Trace Running
NtfsLog Trace Running
SQMLogger Trace Running
UBPM Trace Running
WdiContextLog Trace Running
MpWppTracing Trace Running
FSysAgentTrace Trace Running
MSMQ Trace Running
MSDTC_TRACE_SESSION Trace Running
test_trace Trace Running
The command completed successfully.
c:\> logman test_trace -ets
Name: test_trace
Status: Running
Root Path: C:\
Segment: Off
Schedules: On
Segment Max Size: 500 MB
Name: test_trace\test_trace
Type: Trace
Output Location: C:\09_19_44.etl
Append: Off
Circular: On
Overwrite: Off
Buffer Size: 8
Buffers Lost: 0
Buffers Written: 1
Buffer Flush Timer: 0
Clock Type: Performance
File Mode: File
Provider:
Name: Microsoft-Windows-Application Server-Applications
Provider Guid: {C651F5F6-1C0D-492E-8AE1-B4EFD7C9D503}
Level: 5
KeywordsAll: 0x0
KeywordsAny: 0xffffffff
Properties: 0
Filter Type: 0
The command completed successfully.In certain load tests you want to make sure a bunch of threads reach a particular state before they proceed with the rest of the work. You cannot make sure that all threads execute a point simultaneously since the CPU scheduling would determine this. However you can move these threads to Ready. A ready-thread is a thread can be scheduled for execution on a particular core - http://msdn.microsoft.com/en-us/library/dd627187%28VS.85%29.aspx
WaitForMultipleObjects helps synchronize multiple user mode threads.
“The WaitForMultipleObjects function determines whether the wait criteria have been met. If the criteria have not been met, the calling thread enters the wait state until the conditions of the wait criteria have been met or the time-out interval elapses.”
Here is a small example of how to start multiple threads and then let them proceed after all of them have reached a particular point in execution.
using System;
using System.Threading;
using System.IO;
namespace TestThreading
{
class Program
{
const int ThreadCount = 10;
static ManualResetEvent[] events = new ManualResetEvent[ThreadCount];
static ThreadStart onStart = new ThreadStart(Start);
static int locked = -1;
static void Main(string[] args)
{
Thread[] threads = new Thread[ThreadCount];
for (int i = 0; i < ThreadCount; i++)
{
threads[i] = new Thread(onStart);
events[i] = new ManualResetEvent(false);
}
for (int i = 0; i < ThreadCount; i++)
{
threads[i].Start();
}
Console.ReadLine();
}
private static void Start()
{
int threadCount = Interlocked.Increment(ref locked);
Console.WriteLine("Thread {0} started & waiting", threadCount);
Thread.Sleep(3000); //Simulate some work befor setting.
events[threadCount].Set();
ManualResetEvent.WaitAll(events);
Console.WriteLine("Thread {0} proceeded", threadCount);
}
}
}xperf –on base+cswitch+dispatcher –stackwalk cswitch+readythread
| Simple Copy | |||
| Calls | % Incl | % Excl | Function |
|
21,530 |
8.5 |
0.1 |
System.ServiceModel.Channels.BufferedMessageBuffer::CreateMessage • System.ServiceModel.Channels.Message() |
|
21,530 |
0.29 |
0.03 |
System.ServiceModel.Channels.Message::CreateBufferedCopy • System.ServiceModel.Channels.MessageBuffer(int32) |
|
int headerIndex = input.Headers.FindHeader(header.Name, header.Namespace); if (headerIndex >= 0) { input.Headers.RemoveAt(headerIndex); } input.Headers.Add(header); |
| With Single Header update | |||
| Calls | % Incl | % Excl | Function |
|
12,782 |
14.83 |
0.08 |
System.ServiceModel.Channels.DefaultMessageBuffer::CreateMessage • System.ServiceModel.Channels.Message() |
|
12,782 |
27.69 |
0.02 |
System.ServiceModel.Channels.Message::CreateBufferedCopy • System.ServiceModel.Channels.MessageBuffer(int32) |
| Scenario |
Copy and Forward |
Copy forwarding with new header |
| CPU Utilization Throughput |
98.6 % 11317.6545777148 |
98.7 % 6854.97017102 |
For greater flexibility our router can be something like a pass through router. If we are just calling a backend service then we can use a generic contract to receive and forward messages to the back end service as shown below.
Here we create a copy of the message to consume locally on the broker incase we want to validate some parts of the message or log etc. Ideally the fastest would be to just directly forward it over but application sometimes require all incoming messages to be logged or validated at the entry point of the DMZ.Next – How to Optimize Message Copying using CreateBufferedCopy?
I use the term broker and router very loosely here since they follow very similar guidelines as described here - WCF Broker Overview. Apologies for not being very rigid with these terms.
I will dive into best practices of building a router by progressing from a very simple implementation to a robust one through different scenarios and varying degrees of complexities.
The easiest implementation is by using a strongly typed contract with message forwarding as shown below.
[ServiceContract]
public interface IOrderService
{
[OperationContract]
Order[] GetOrders(int numOrders);
}
class OrderService:IOrderService
{
Order[] GetOrders(int numOrders)
{
return backendProxy.GetOrders(numOrders);
}
}
Next – Router Implementation – Message Forwarding – Copy/Pass through
A broker is usually a central point for message forwarding and pass-through for clients and backend services. There are many types of brokers that come into mind
But they mostly fall into the below basic model unless the client manages to bypass the broker with a P2P communication with the backend itself.
Router Implementation – Strong Typed with Message Forwarding
Aug’5’10
Here are 2 really good articles on MSDN that I would recommend for the functional aspects to architect your your router.