Welcome to MSDN Blogs Sign in | Join | Help

WCF is all about communication objects – channels, listeners, factories, all implement the ICommunicationObject interface (some through the CommunicationObject class). This provides a base implementation for the basic state machine states and transitions common to all communication-oriented object.

At any given point in time, the communication objects find themselves in a CommunicationState. Here is a diagram with the states and the transitions:

image

When we look at a communication object in a debugger, we see something like this (some columns and internal objects removed for brevity reasons):

Name: System.ServiceModel.Channels.ServiceChannel

Fields:

Type VT Value Name
System.Boolean 1 0 aborted
System.Boolean 1 0 closeCalled
System.Boolean 1 0 onClosingCalled
System.Boolean 1 0 onClosedCalled
System.Boolean 1 1 onOpeningCalled
System.Boolean 1 1 onOpenedCalled
System.Boolean 1 0 raisedClosed
System.Boolean 1 0 raisedClosing
System.Boolean 1 0 raisedFaulted
System.Boolean 1 0 traceOpenAndClose
System.Object 0 000000000131d8e0 eventSender
System.Int32 1 2 state
System.EventHandler 0 0 Closed
System.EventHandler 0 0 Closing
System.EventHandler 0 0 Faulted
System.EventHandler 0 0 Opened
System.EventHandler 0 0 Opening


In our example, the communication object is in state 2. How does that translate to the actual states? To tell you the truth, I always take some time to map the number to the state, so I started using this cheat sheet:

public enum CommunicationState
{
    Created = 0,
    Opening = 1,
    Opened = 2,
    Closing = 3,
    Closed = 4,
    Faulted = 5
}

So in our case, the ServiceChannel is Opened. We could identify the state by looking at the other variable – if close called or aborted was called, we can only by in state 4 or 5 and so on. But the cheat sheet makes it simple.

Hope you find it useful!

Every other year, Microsoft organizes a conference for women. Why? Because it recognizes that women more than men feel the need to get inspired by listening to some sessions oriented towards the emotional space and, more to the point, women feel the need to talk to other women, find out what issues those women have and feel that they are not alone. Well, this is more why women participate at the conference. But the conference benefits Microsoft as well, because inspired women are more creative, work harder and more efficiently.

This year's theme was “Opportunity In Change”. The planning team was formed by volunteers that did a great job – the organization was really well planned, the sessions and the speakers well chosen and from registration to food and networking events everything went flawlessly.

And I want to share with you some of the things I learned. The conference took 2 days and a half. In the 2 full days, there were a couple of sessions going in parallel. Of course, I chose the sessions that seemed more interesting to me. But I learned that the content and the speaker are not enough to make it a good presentation; in order to inspire you, the information and the delivery must match some internal struggle you are dealing with. There were sessions contained the right info, where the speaker did all the right things to attract and connect to the audience, but that didn’t honestly impress me. And sessions that I found heart reaching did nothing for other women.

The session I liked most was one by Nancy D. Solomon, talking about impact. As a writer, speaker, facilitator and executive coach, Nancy has built her career around one simple question: “What did you come here to do, and are you getting it done?” In this session, she gave us the definition of impact -  impact is the fingerprint, not the finger that left the print. Put it simply, it's the consequence of what you do/say/think that matters and not the action/word/thought per se. This was a good point for me, as I have the tendency to look at actions instead of the impact of those actions.

Another good point: people usually don't know what they want, because nobody asked them and, more importantly, they never asked themselves. This is quite applicable inside Microsoft. I know people that do things because they think that that is what they should be doing: I'll take this job because I'll be better positioned for the next , I'll do this because it will increase my visibility, etc. Very few ask: what do I really want? She told us about a study that looks at how engaged the employees are. I believe I found the study, and it says:

The Gallup Management Journal publishes a semi-annual Employee Engagement Index. Recent results for the U.S. indicated that:

•    Only 29% of employees are actively engaged in their jobs and feel a passion for their work and a connection to their company.
•    Over half of employees (54%) are not engaged in their work and have essentially “checked out.” They are going through the motions; putting in their time and keeping busy but not working with passion.
•    The remaining employees, 17%, are actively disengaged. Such employees act on their unhappiness and undermine the work their engaged co-workers are trying to accomplish.

When it comes to career progress, Nancy sais a lot of people think that personal satisfaction and achievement are on the same axis, and therefore in order to get one, the other will be neglected, Instead, she argues that people move an 2 axes, so it's possible to move to accomplish both if you do what you like.

Personal satisfaction / achievement graph 

Another session I liked was Bonnie St John’s one, about achieving peak performance in spite of the fact that life is sometimes tough. This was a very inspiring story: Bonnie had a most interesting life:

Due to a condition called pre-femoral focal disorder, Bonnie had her right leg amputated above the knee when she was only 5 years old. Despite this challenge, she went on to excel as an athlete, a scholar, a mother, and a businesswoman. After graduating Magna Cum Laude from Harvard University in 1986, Bonnie won a Rhodes Scholarship to Oxford University where she earned her M.Litt. Degree in Economics in 1990. She worked in the White House during the Clinton administration as a Director for the National Economic Council, and is currently CEO of Courageous Spirit, Inc. Bonnie provides inspirational and motivational keynote speeches to dozens of business organizations annually, touching literally tens of thousands of lives each year with her messages of strength and courage.

The most important take away from her presentation was that if people often compare life with sports, nowadays, companies are better compared with disabilities sports (due to the economic situation that’s not quite pink – in case you haven’t noticed). Companies need to thrive despite their disabilities; same for people. About the people she competed with at Paralympics, she said: "what they don't have doesn't matter". What matters is to do the best with what you have.

Instead of playing it safe to stay up all the time, it's more important to learn how to get up fast after you fall.

Now, most of the sessions touched upon some common themes:

  • Be yourself, and be the best you can be.
  • Take risks, get out of your comfort zone.
  • Enjoy the small moments of life, take time regularly to feel joy and delight.
  • Find and follow your purpose in life to be more efficient.
  • Soft skills impact business performance. A study shows that people give in average 85% off what they could be giving on the job; they put in more depending on the direct manager’s soft skills and the soft skills of people around them.

I also loved the quote Mitch Shepard shared with us at her session about Emotional Intelligence: The cure for exertion is not rest, it’s living wholeheartedly. I believe I’ll make this my motto.

Hope this gives you an idea of what happened at the Microsoft conference. Like Lisa Brummel, Microsoft’s senior VP for HR said at the conference, there are a lot of opportunities for personal development and learning activities in Microsoft; if people don’t know about them, it’s management’s fault; if they know and don’t take advantage of them, it’s their own fault. The women’s conference is an opportunity for women to network and connect with other women, learn and get inspired by different opinions, opportunities, and a variety of experiences. If your company organizes something similar, I highly recommend going.

Event Tracing for Windows is the standard way to trace used by all features of Windows. Like the article Improve Debugging And Performance Tuning With ETW explains, ETW is

“a general-purpose, high-speed tracing facility provided by the operating system. Using a buffering and logging mechanism implemented in the kernel, ETW provides a tracing mechanism for events raised by both user-mode applications and kernel-mode device drivers. Additionally, ETW gives you the ability to enable and disable logging dynamically, making it easy to perform detailed tracing in production environments without requiring reboots or application restarts. The logging mechanism uses per-processor buffers that are written to disk by an asynchronous writer thread. This allows large-scale server applications to write events with minimum disturbance.”

The article above explains the ETW architecture (that suffered great improvements since Windows Vista), explaining events and sessions, event providers and event consumers. As a quick overview: an event provider writes events to ETW sessions (it can be any user-mode application, managed application, driver etc). When events are written, ETW adds more info about the time it took place, process and thread ID that generated it, processor number, and CPU usage data of the logging thread. This info is used by the event consumers - application that reads log files or listens to a session for real time events and processes them. More about providers at ETW Trace Providers - When to use what.

Since Windows Vista, the event provider APIs are simpler to use and offer richer functionality (like same way to use trace and event logs). To register as an ETW provider, software components need to provide a GUID as a unique identifier and a callback that will be invoked when notifications are enabled. When enabling a provider, a controller can specify

- a level (1-byte integer) – used to show the severity or verbosity of events (eg. verbose, info, error, critical)

- keywords (8-byte bit masks) – indicate subcomponents in a provider, so subcomponents can be enabled separately.

.Net Framework offers a managed ETW provider API (see System.Diagnostics.Eventing Namespace).

Once a provider is installed, users can collect events from the provider using the logman tool or Reliability and Performance Monitor (Perfmon in Vista and above). The Event Viewer offers another means for collecting and viewing events. Logman is a controller that offers the following options:

logman create - Create a counter, trace, configuration data collector, or API.

logman query - Query data collector properties.

logman start | stop - Start or stop data collection.

logman delete - Delete an existing data collector.

logman update - Update the properties of an existing data collector.

logman import | export - Import a data collector set from an XML file or export a data collector set to an XML file.

To read more about logman, try Two Minute Drill: LOGMAN.EXE.

Tracerpt can be used to process event trace logs or real-time data from instrumented event trace providers. It generates trace analysis reports and CSV (comma-delimited) files for the events generated. LogParser 2.2 also knows to parse ETW events.

There are other tools that can help with event logging information, like Event trace and ETW Trace Viewer.

To see an example of how to use ETW, read Capturing and analyzing an ETW Trace article.

The tools I mentioned so far are useful to get and analyze the traces. From a developer point of view, if you want to generate traces for your software application, you can create a trace source and then write events to it. Using an ETW listener offers huge performance improvements over other trace listeners. For a managed application that uses the existing trace listeners or other custom listeners, the only change is to switch to the EventProviderTraceListener (a configuration change). For a provider with GUID 4a632b62-b345-42d4-56dc-g1sac9hfjr14 (generated and installed by you), the config file can look like this:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.diagnostics>
    <sources>
      <source name="MySourceName" switchName="mySwitch" 
              switchType="System.Diagnostics.SourceSwitch">
        <listeners>
          <remove name="Default" />
          <add name="MyEventProviderTraceListener"
               type="System.Diagnostics.Eventing.EventProviderTraceListener, 
               System.Core, Version=3.5.0.0, Culture=neutral, 
               PublicKeyToken=b77a5c561934e089"
               initializeData="4a632b62-b345-42d4-56dc-g1sac9hfjr14" />
        </listeners>
      </source>
    </sources>
    <trace autoflush="true" indentsize="4"/>
  </system.diagnostics>
</configuration>

But more about this in a future post. Stay tuned!

I recently had to solve these kind of requirements: some components execute actions and at some point in time need to notify other components that certain events happened, so the other components can execute code related to these events. For example, class A executes method ChangeStateOfObjectX, and needs to notify class B when X is changed; then B does a certain action (for example, increments a perf counter that illustrates the number of inner objects in X, or writes an event entry or plays a song) when it’s notified. Let’s call class A the Events Generator (because it generates events :)) and B the Events Consumer (because it takes actions in response to the events generated by A).

Let’s take a concrete example: the class ProjectProgressTracker keeps track of a project progress – this is the Events Generator; when a task is added, completed or blocked (all internal states that the user doesn’t have access to), it needs to let a monitor system know – the Events Consumer.

// generates events when a task is added, completed, blocked etc
class ProjectProgressTracker {
    static Random r = new Random((int)DateTime.Now.Ticks);
    List<Task> tasks;

    public ProjectProgressTracker(string[] initialTasks) {
        this.tasks = new List<Task>();
        if (initialTasks != null)
            foreach (string s in initialTasks)
                this.tasks.Add(new Task(s));
    }

    public void NextAction() {
        int randomNumber = r.Next(10);
        if (randomNumber < 3)
            // a new task was added
        else if (randomNumber > 6)
            // a task is blocked
        else
            // the task is done
    }

    class Task {
        string name;
        public Task(string name)
            this.name = name;
        // other properties & methods
    }
}

This monitor system – StatusUpdatePublisher, sends mails and updates calendars.

// the class that reacts to events generated by ProjectProgressTracker
class StatusUpdatePublisher {
    public void OnTaskAdded(string taskName) {
        this.UpdateCalendar(true);
        this.SendMail(taskName, "added");
    }
    public void OnTaskBlocked(string taskName) {
        this.SendMail(taskName, "blocked");
    }
    public void OnTaskCompleted(string taskName) {
        this.UpdateCalendar(false);
        this.SendMail(taskName, "completed");
    }

    void SendMail(string taskName, string action) {
        Console.WriteLine("Task {0} was {1}", taskName, action);
    }
    void UpdateCalendar(bool taskAdded) {
        Console.WriteLine("Task was {0}", taskAdded ? "added" : "removed");
    }
}

The 2 functionalities (generator / consumer) are completely separate.

1. One way to implement this is to pass an Events Consumer object when constructing the Events Generator; then the generator class simply uses the consumer instance to call the desired methods.

class ProjectProgressTracker {
    static Random r = new Random((int)DateTime.Now.Ticks);
    List<Task> tasks;
    readonly StatusUpdatePublisher publisher;

    public ProjectProgressTracker(
        string[] initialTasks, StatusUpdatePublisher publisher) {
        this.publisher = publisher;
        // other functionality, see above
    }

    public void NextAction() {
        // This should be replaced with the actual logic
        int randomNumber = r.Next(10);
        if (randomNumber < 3)
            publisher.OnTaskAdded(randomNumber.ToString());
        else if (randomNumber > 6)
            publisher.OnTaskBlocked(randomNumber.ToString());
        else
            publisher.OnTaskCompleted(randomNumber.ToString());
    }

    // other methods & classes
}

This works, but makes the events generator class tightly coupled with the events consumer. Consider now that we want to add another monitor system that generates documentation tasks. If we follow the style above, we should pass it too inside the events generator class so it can call the correct methods. Of course, this model doesn’t scale very well.

2. Another option is to raise some events at the correct time.

class TaskEventArgs : EventArgs {
    public TaskEventArgs(string taskName) {
        this.TaskName = taskName;
    }
    public string TaskName { get; private set; }
}

delegate void TaskEventHandler(object sender, TaskEventArgs e);

The events generator class has 3 events – for tasks added, completed and blocked.

class ProjectProgressTracker {
    public event TaskEventHandler OnTaskAdded;
    public event TaskEventHandler OnTaskCompleted;
    public event TaskEventHandler OnTaskBlocked;

    public void NextAction() {
        // This should be replaced with the actual logic
        int randomNumber = r.Next(10);
        TaskEventArgs eventArgs = new TaskEventArgs(
            randomNumber.ToString());
        if (randomNumber < 3)
            this.OnTaskAdded(this, eventArgs);
        else if (randomNumber > 6)
            this.OnTaskBlocked(this, eventArgs);
        else
            this.OnTaskCompleted(this, eventArgs);
    }

    // other methods & classes
}

Then the user of the class needs to hook up the events to the correct methods in the consumer class.

ProjectProgressTracker tracker = new ProjectProgressTracker(
    new string[] {"Gather requirements", "Prototype"});
tracker.OnTaskAdded += 
    (object o, TaskEventArgs e) => publisher.OnTaskAdded(e.TaskName);
tracker.OnTaskCompleted += 
    (object o, TaskEventArgs e) => publisher.OnTaskCompleted(e.TaskName);
tracker.OnTaskBlocked += 
    (object o, TaskEventArgs e) => publisher.OnTaskBlocked(e.TaskName); 

The benefit of this approach is that the generator class is not modified, no matter how many consumer classes we want to add to it. The disadvantage is that the user class needs to hook up all events to the correct implementation in consumers.

3. Another solution is to use the Observable/Observer pattern. The Observer-Observable design pattern is a a very useful pattern for maintaining one-way communication between one object and a set of other objects. The observers receive communications from the Observable. Observers do not have a reference back to the Observable, so the communication is strictly from the Observable to the Observers. The observable is the object the Observers are "watching". The Observable maintains some sort of  list of references to Observers. That way, the Observable can send a message to all the Observers by calling each of their update methods.

This is a known pattern, but since it’s not implemented in .Net Framework 3.5, I am just going to define some interfaces that suit my needs.

Here, the class that generates events is the IObservable<T> and the class that consumes events in IObserver<T>:

interface IObservable<T> {
    void Subscribe(IObserver<T> observer);
    bool Unsubscribe(IObserver<T> observer);
}

interface IObserver<T> {
    void OnNext(T value);
}

In our case, T is a class that contains the state of the task – the name of the task and the action that was taken:

enum TaskAction { Added, Completed, Blocked }
class TaskState {
    public TaskState(string taskName, TaskAction taskAction) {
        this.TaskAction = taskAction;
        this.TaskName = taskName;
    }
    public string TaskName { get; private set; }
    public TaskAction TaskAction { get; private set; }
}

So our classes change accordingly: the ProjectProgressTracker implements the IObservable interface, and the status update class implements the IObserver interface.

class ProjectProgressTracker : IObservable<TaskState> {
    List<IObserver<TaskState>> observers = 
        new List<IObserver<TaskState>>();

    public void Subscribe(IObserver<TaskState> observer) {
        this.observers.Add(observer);
    }
    public bool Unsubscribe(IObserver<TaskState> observer) {
        return this.observers.Remove(observer);
    }

    public void NextAction() {
        // This should be replaced with the actual logic
        int randomNumber = r.Next(10);
        TaskEventArgs eventArgs = new TaskEventArgs(
            randomNumber.ToString());
        if (randomNumber < 3)
            foreach (IObserver<TaskState> observer in this.observers)
                observer.OnNext(
                    new TaskState(randomNumber.ToString(), TaskAction.Added));
        else if (randomNumber > 6)
            foreach (IObserver<TaskState> observer in this.observers)
                observer.OnNext(
                    new TaskState(randomNumber.ToString(), TaskAction.Blocked));
        else
            foreach (IObserver<TaskState> observer in this.observers)
                observer.OnNext(
                    new TaskState(randomNumber.ToString(), TaskAction.Completed));
    }

    // other methods & classes
}

class StatusUpdatePublisher : IObserver<TaskState> {
    public void OnNext(TaskState state) {
        switch (state.TaskAction) {
            case TaskAction.Added:
                this.OnTaskAdded(state.TaskName); break;
            case TaskAction.Blocked:
                this.OnTaskBlocked(state.TaskName); break;
            case TaskAction.Completed:
                this.OnTaskCompleted(state.TaskName); break;
        }
    }

    // the other methods
}

Now the user just constructs the classes and registers the desired consumers:

StatusUpdatePublisher publisher = new StatusUpdatePublisher();
ProjectProgressTracker tracker = new ProjectProgressTracker(
    new string[] {"Gather requirements", "Prototype"});
tracker.Subscribe(publisher);

This pattern has a couple of advantages:

  • Multiple consumers can be added easily
  • The events generator doesn’t need to know anything about the consumers; no change in the generator is needed when one or more of the consumers is changed.

But we pay the penalty of wrapping the state in a class and then analyzing it in the Observer to see what concrete method to implement.

4. Another possible implementation is the IRegistrar pattern (Disclaimer: I’m not aware of a pattern with this name described. The name is something I came up with). This is somewhat similar with the IObservable pattern, but instead of a class that wraps the state when the event occurs, we specify an interface for the type of events.

interface IProjectEvents {
    void OnTaskAdded(string taskName);
    void OnTaskBlocked(string taskName);
    void OnTaskCompleted(string taskName);
}

interface IRegistrar<T> {
    void Subscribe(T consumer);
    bool Unsubscribe(T consumer);
}

The events consumers implement this interface:

class StatusUpdatePublisher : IProjectEvents {
    // the original methods
}

The generator class can register consumers that know to consume events of type T (IProjectEvents in our case).

class ProjectProgressTracker : IRegistrar<IProjectEvents> {
    List<IProjectEvents> consumers = new List<IProjectEvents>();

    public void Subscribe(IProjectEvents consumer) {
        this.consumers.Add(consumer);
    }
    public bool Unsubscribe(IProjectEvents consumer) {
        return this.consumers.Remove(consumer);
    }

    public void NextAction() {
        // This should be replaced with the actual logic
        int randomNumber = r.Next(10);
        TaskEventArgs eventArgs = new TaskEventArgs(
            randomNumber.ToString());
        if (randomNumber < 3)
            foreach (IProjectEvents consumer in this.consumers)
                consumer.OnTaskAdded(randomNumber.ToString());
        else if (randomNumber > 6)
            foreach (IProjectEvents consumer in this.consumers)
                consumer.OnTaskBlocked(randomNumber.ToString());
        else
            foreach (IProjectEvents consumer in this.consumers)
                consumer.OnTaskCompleted(randomNumber.ToString());
    }

    // other methods & classes
}

The usage is just as the one for the IObservable pattern.

In our case, it seems that this pattern works the best, because we get all the previous advantages plus strongly typing when calling consumer methods.

Depending on your project requirements, you may choose one of these solutions or look for a better one. Some requirements may be:

  • Loosely coupling between the events generator and the consumers
    • Changing the consumer doesn’t affect the generator
  • One or more consumers can be added
  • Producers can have inner producers and the consumers must be propagated
  • Etc… who knows?

The .NET Framework 4.0 and Visual Studio 2010 Beta 1 are live. If you haven’t tried the bits, do so and give the team feedback. There are some very cool features added – just take a look at the highlights.

On the Communications front, Windows Communication Foundation has 3 major new features: support for WS-Discovery, standard endpoints (pre-defined endpoints with some of the properties fixed) and workflow services (messaging activities make the implementation of workflows very easy).

I am really excited with the support for the WS-Discovery protocol. From the msdn documentation:

“The Service Discovery feature enables client applications to dynamically discover service addresses at run time in an interoperable way using WS-Discovery. The WS-Discovery specification outlines the message-exchange patterns (MEPs) required for performing lightweight discovery of services, both by multicast (ad hoc) and unicast (using a network resource).”

To learn more about Discovery, take a at the Discovery MSDN SDK samples. Plus, the Discovery team is blogging, so go to the Discovery team’s blog. Or start with the Channel9 Discovery video:

image

When it comes to performance, there's a hard lesson I had to learn: never trust anyone, measure for yourself! Don't trust the gurus, the MSDN documentation, the technical fellow that wrote the code. Instead, do some simple performance measurements to see what is really going on.

I had to instrument my C# code with performance counters. I started reading the MSDN PerformanceCounter documentation, and here is what I found out:

The Increment, IncrementBy, and Decrement methods use interlocks to update the counter value. This helps keep the counter value accurate in multithreaded or multiprocess scenarios, but also results in a performance penalty. If you do not need the accuracy that interlocked operations provide, you can update the RawValue property directly for up to a 5 times performance improvement. However, in multithreaded scenarios, some updates to the counter value might be ignored, resulting in inaccurate data.

Because the application I instrumented was multithreaded, I didn't want to use the RawValue mechanism. Not much choice to be made, no headache. My application needed to create and cleanup multiple performance counter instances based on certain object instances, and these objects were accessed from multiple threads. Then, my requirements changed: I had to introduce my own locks around perf counters. So the question became: should I use the PerformanceCounter.Increment/Decrement functions inside my lock, or just change the RawValue directly? Based on the documentation, the second option should have been more performant.

But, like I said: never trust the documentation. So I wrote a simple program to test the 2 methods. First, I created a performance counter category and added a counter to it:

CounterCreationDataCollection dataCollection = 
    new CounterCreationDataCollection();
dataCollection.Add(new CounterCreationData(
    "MyCounterName", 
    "My special test counter", 
    PerformanceCounterType.NumberOfItems64));
PerformanceCounterCategory.Create(
    "MyCategory", 
    "My special test category",
    PerformanceCounterCategoryType.SingleInstance,
    dataCollection);

Now that the counters are installed, let's start incrementing them. I tested 4 configurations: 1. using RawValue, 2. using RawValue under a lock, 3. using Increment, 4. using Increment under a lock.

enum PerfCounterOperations
{
    Increment,
    IncrementLock,
    Raw,
    RawLock
}

I created a disposable class that instantiates a performance counter in our installed category.

using System;
using System.Diagnostics;
using System.Threading;

sealed class PerfCounterWrapper : IDisposable
{
    static Stopwatch watch = new Stopwatch();
    int noRepetitions = 10000;

    readonly PerformanceCounter perfCounter;
    bool enabled;
    readonly object thisLock;

    public PerfCounterWrapper()
    {
        this.thisLock = new object();
        try
        {
            this.perfCounter = new PerformanceCounter(
                "MyCategory", 
                "MyCounterName", 
                false);
            this.perfCounter.RawValue = 0;
            this.enabled = true;
        }
        catch (InvalidOperationException ex)
        {
            // The category is not installed 
            // or there isn't enough memory to create the counter
            Console.WriteLine("Error creating counter: {0}", ex.ToString());
            this.enabled = false;
        }
    }

    public void Dispose()
    {
        if (this.enabled)
        {
            this.perfCounter.Dispose();
            this.enabled = false;
        }
    }     .....
}

Here is the method that simulates the 4 types of increment operations:

void Increment(object perfCounterOperation)
{
    PerfCounterOperations operation = 
        (PerfCounterOperations)perfCounterOperation;
    switch (operation)
    {
        case PerfCounterOperations.Increment:
            if (this.enabled)
                for (int i = 0; i < noRepetitions; i++)
                    this.perfCounter.Increment();
            break;
        case PerfCounterOperations.IncrementLock:
            for (int i = 0; i < noRepetitions; i++)
                // We could simplify this, but we don't want to; 
                // requirements: check "enabled" inside the lock
                lock (this.thisLock)
                    if (this.enabled)
                        this.perfCounter.Increment();
            break;
        case PerfCounterOperations.Raw:
            if (this.enabled)
                for (int i = 0; i < noRepetitions; i++)
                    this.perfCounter.RawValue += 1;
            break;
        case PerfCounterOperations.RawLock:
            for (int i = 0; i < noRepetitions; i++)
                lock (this.thisLock)
                    if (this.enabled)
                        this.perfCounter.RawValue += 1;
            break;
    }
}

The class has methods that measure the number of ticks necessary to increment the counters in a loop. I measured the results with and without contention (by starting multiple threads in the first case and just one thread in the second).

void IncrementCounterSingleThread(PerfCounterOperations operation)
{
    watch.Reset();
    watch.Start();
    this.Increment(operation);
    watch.Stop();
    Console.WriteLine("{0}: {1} ticks", operation, watch.ElapsedTicks);
}

void IncrementCounterMultipleThreads(PerfCounterOperations operation)
{
    Thread[] t = new Thread[10];
    for (int i = 0; i < 10; i++)
        t[i] = new Thread(new ParameterizedThreadStart(this.Increment));

    watch.Reset();
    watch.Start();
    for (int i = 0; i < 10; i++)
        t[i].Start(operation);

    for (int i = 0; i < 10; i++)
        t[i].Join();

    watch.Stop();
    Console.WriteLine("{0}: {1} ticks", operation, watch.ElapsedTicks);
}

Then we just call these methods for the 4 types of operations and get the results.

void MeasureOpSingleThread(int noRepetitions)
{
    this.noRepetitions = noRepetitions;
    Console.WriteLine("Single threaded - no contention");
    this.IncrementCounterSingleThread(PerfCounterOperations.Raw);
    this.IncrementCounterSingleThread(PerfCounterOperations.RawLock);
    this.IncrementCounterSingleThread(PerfCounterOperations.Increment);
    this.IncrementCounterSingleThread(
            PerfCounterOperations.IncrementLock);
}

void MeasureOpMultipleThread(int noRepetitions)
{
    this.noRepetitions = noRepetitions;
    Console.WriteLine("Multiple threads - with contention");
    this.IncrementCounterMultipleThreads(PerfCounterOperations.Raw);
    this.IncrementCounterMultipleThreads(PerfCounterOperations.RawLock);
    this.IncrementCounterMultipleThreads(PerfCounterOperations.Increment);
    this.IncrementCounterMultipleThreads(
            PerfCounterOperations.IncrementLock);
}

Lastly, we create a wrapper and measure the operations for different number of repetitions:

    static void Main(string[] args)
    {
        using (PerfCounterWrapper p = new PerfCounterWrapper())
        {
            for (int i = 5000; i < 100000; i += 5000)
            {
                p.MeasureOpSingleThread(i);
                p.MeasureOpMultipleThread(i);
            }
        }
    }

And here are the results:

image

image

Based on our measurements, the MSDN documentation is misleading: accessing the RawValue is slower than using the Increment/Decrement function, both under lock and with no lock.

Notice that the code is throw away - far from ship quality, doesn't contain code to handle exceptions or corner cases; all I wanted is to write a simple test fast and get some numbers. This is just one example; the general lesson is: when it comes to performance, do your own tests. Measure, measure, measure.

As part of the project I am working on, I had to create performance counter categories and counters for monitoring and debugging purposes. So I wrote the code that installs the counters and everything worked as expected on my machines. Then someone told me that the application failed on his machine with this error:

ERROR: caught unexpected exception System.ComponentModel.Win32Exception: The configuration registry key is invalid

   at System.Diagnostics.PerformanceCounterLib.RegisterFiles(String arg0, Boolean unregister)

   at System.Diagnostics.PerformanceCounterLib.UnregisterCategory(String categoryName)

   at System.Diagnostics.PerformanceCounterCategory.Delete(String categoryName)

   at MyProgram.PerfCountersHelper.DeleteCategory(String categoryName)

   at MyProgram.PerfCountersHelper.CleanupCategories()

I looked at the code and everything seemed fine - before installing the new category, I was looking if a category with the same name exists and if it did, I deleted it. After I scratched my head for a while, I decided to take a look at his machine. And surprise, surprise, perfmon showed that there were some default counters missing, which hinted toward perf counter corruption.

Performance counters can become corrupted; so if you don't see categories in Perfmon, or they are missing counters, or names are replaces with numbers, you're probably experiencing this phenomena. To fix the issue, run the lodctr tool with the option /R from a commnd prompt with administrative privileges: LODCTR /R
This command rebuilds the perf registry strings and info from scratch based on the current registry settings and backup INI files.

If this doesn't work or you need more specific steps, look at the article http://support.microsoft.com/?kbid=300956

I consider regular expressions one of the most useful features ever. I use them a lot, not only when coding, but also when editing files and instead of copy and paste. I find the Visual Studio Find/Replace feature with regular expressions really useful as well. In case you are not familiar with it, you can use regular expressions to find and replace characters like this:

image

In the picture, I used the expression {[^;]+}; - meaning tag the string formed by any characters until ";" (at least one character) and replace the matching text with "// " followed by the tagged expression, forgetting the last ";". There are a lot of tutorials about regular expressions. I just learned the basics, and now I just try, fail, undo, and try again until I get it right.

Moving back to coding, .NET has great support for regular expressions. The classes are relatively easy to use (though at the beginning I had to play a while to find out how to capture strings in one match and other more advanced features). The biggest advantages I find in using Regex are that it makes parsing input very easy (once you have the regular expression in place) and it makes it much harder to introduce bugs - less code has by definition fewer bugs, and parsing with regular expressions requires less code than the traditional method of parsing strings with different string methods like get substring at different indexes, check that is starts or ends with certain characters etc.

However, there are cases when the string concatenation and parsing is better than the regular expressions: when the checks are done on a path that is executed a lot (a hot path), and that has strict performance requirements. Why? The regular expressions are slower than string concatenation.

I did a simple experiment and measured the time needed by regex and strings to perform the same operations. I considered I need to keep data about persons in the format "Firstname:Oana Lastname:Platon Money:2183 UniqueIdentifier:fwsjfjehfjkwh8r378". I have defined a constant that represents this format, and I'll use it to serialize the person data.

const string nameFormat = "Firstname:{0} Lastname:{1} Money:{2} UniqueIdentifier:{3}";

The data must be serialized and deserialized a lot of times (lets say that we need to send the data on the wire frequently or something like that). When deserializing the data, we need to make sure that it respects the pattern and then we need to extract the firstname, lastname etc.

1. Using regular expressions

I defined a regular expression like this:

static Regex regex = new Regex("^Firstname:(\\w+)\\sLastname:(\\w+)\\sMoney:(\\d{1,9})\\sUniqueIdentifier:([\\w-]+)$", RegexOptions.IgnoreCase | RegexOptions.Compiled);

Then, the code to parse the expressions and get the desired data is:

void ParseWithRegex(string description)

{

    Match m = regex.Match(description);

    if (!m.Success)

    {

        throw new ArgumentException("description doesn't follow the expected format");

    }

    this.firstname = m.Groups[1].Value;

    this.lastname = m.Groups[2].Value;

    if (!int.TryParse(m.Groups[3].Value, out this.age))

    {

        throw new ArgumentException("age doesn't have the correct value");

    }

    this.uniqueIdentifier = m.Groups[4].Value;

}

2. Using string operations

The verification that the given string respects the format becomes more difficult. In our case, the patters is pretty simple, but imagine that we needed to check an email address or something more complicated. In that case, the code would have had a lot of cases, to follow all possible solutions.

void ParseWithStrings(string description)

{

    string[] parts = description.Split(new char[] { ' ', '\t' });

    if (parts.Length != 4)

    {

        throw new ArgumentException("description doesn't follow the expected pattern");

    }

    this.firstname = parts[0].Substring(parts[0].IndexOf(":") + 1);

    this.lastname = parts[1].Substring(parts[1].IndexOf(":") + 1);

    if (!int.TryParse(parts[2].Substring(parts[2].IndexOf(":") + 1), out this.age))

    {

        throw new ArgumentException("age doesn't have the correct value");

    }

    this.uniqueIdentifier = parts[3].Substring(parts[3].IndexOf(":") + 1); ;

}       

See that this is much more error prone than the previous code, because it needs to look at a lot of indexes and to substract the desired part of the string.

However, when I run the 2 methods in a loop and I measure how long they take with a stopwatch (from System.Diagnostics namespace), I get these results:

image

In conclusion, when choosing between using traditional string parsing or regular expressions, I would recommend:

- Start with regular expressions; if the path is not a hot path and doesn't have any strict performance requirements, this is the best choice, since it makes the code easier to read and maintain.

- If the performance goals are not reached (which means you have performance goals and you measured the performance!), try to improve your regular expressions. For example, adding ^ and $ (to specify that the pattern you are looking for is at the beginning or at the end of the string) when appropriate can improve the performance a lot. Also, make sure you use compiled expressions (if possible).

- If you are still not in graphic, replace the regular expressions with string concatenation and parsing.

Using Visual Studio to write code requires creating a project (well, you can use Visual Studio without a project, but you won’t get very much past Notepad functionality – there’s not even Intellisense on files) . After creating / opening an existing project, we can add new files (classes, class diagrams, XML files etc) by selecting the Project menu, then Add New Item (or add Class / Windows Forms / Windows Component or User Control, if this is what you need). After you specify all the details (file name), a file is added with some default text in it. Assuming you have Visual Studio 2008 SP1 installed, the templates that generate this text are stored at %ProgramFiles%\Microsoft Visual Studio 9.0\Common7\IDE\ProjectTemplates  and %ProgramFiles%\Microsoft Visual Studio 9.0\Common7\IDE\ProjectTemplatesCache (for x64 machines, look in % ProgramFiles(x86)%).

Let’s add a new C# class, Tester, to the class library project SimpleTests. By default, in Visual Studio 2008 it will contain the following text:

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace SimpleTests

{

    class Tester

    {

    }

}

 

This text comes from the Class template. If we look in the ProjectTemplateCache folder, inside CSharp (the language we used to add the class) -> Code -> 1033 -> Class.zip, we find a class.cs looking like this:

 

using System;

using System.Collections.Generic;

$if$ ($targetframeworkversion$ == 3.5)using System.Linq;

$endif$using System.Text;

 

namespace $rootnamespace$

{

      class $safeitemrootname$

      {

      }

}

 

This explains the text we get. But how can we customize the default? I really would appreciate some changes:

-          I don’t want all these usings added by default – I prefer to start without any using statement, and to add them while the code requires them. Of course, I could do it the other way around: add all the usings I think I may need; when I am done coding, remove the unused ones. Visual Studio lets you do that easily by right clicking on the page, selecting Organize Usings -> Remove Unused Usings (or Remove and Sort).

-          Second, I prefer Usings inside the namespace declaration and I want to add a header to the file.

I can change the Class.cs file and replace the Class.zip in ProjectTemplatesCache folder:

 

//------------------------------------------------------------

// Copyright (c) Oana Platon

//------------------------------------------------------------

 

namespace $rootnamespace$

{

    using System;

   

    class $safeitemrootname$

    {

    }

}

 

Then when I reopen Visual Studio and Add a class, I get this file:

 

//------------------------------------------------------------

// Copyright (c) Oana Platon

//------------------------------------------------------------

 

namespace SimpleTests

{

    using System;

 

    class MyCustomizedTester

    {

    }

}

 

Cool, right?

This change will be lost the first time when devenv /installvstemplates command is called (this command replaces the ItemTemplatesCache folder with what finds in ItemTemplates folder). To make it permanent, make the change in ItemTemplates folder instead and run devenv /installvstemplates to propagate the change to ItemTemplatesCache.

The registry editor has a very useful functionality that many people overlook – the favorites. You can add the keys you are interested in the favorites category, so that you can access them later with one click. To add a key, navigate to it, then choose Favorites->Add Favorites from the menu. You can delete the key from the favorites list when you don’t need it anymore.

Registry editor - Favorites menu

The interesting thing is that the favorites are kept into another registry key - HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Applets\Regedit\Favorites. So you can Export this key and open it on another computer to restore your favorites.

Registry editor - Export key

Like I mentioned in my previous article, CLR integrates WER in order to be able to add managed-specific information in the reports generated on crashes (if you are not familiar with Windows Error Reporting, read more in the article Windows Error Reporting (WER) for developers).

The CLR WER integration brings some problems, most of them due to the large matrix of OSs that must be supported. WER was introduced with Windows XP, so for older OSs, CLR must use Dr. Watson. Also, the support in Vista and Windows Server 2008 was enhanced, so there are differences on how CLR leverages WER on these platforms compared to Windows XP and Windows Server 2003. Because of the large matrix, there are some corner cases that are not treated as well as they should.

Other problem with WER integration stems from the report parameters. Like I mentioned in Windows Error Reporting and CLR integration article, CLR uses the method desc and the IL offset inside the method to identify the faulting instruction (for native applications, one of the parameters is the hash of the current stack). This can introduce issues if we wrap the code that deals with the error in one function and multiple functions call that function. For example, we have a function DealWithUnexpectedConditions that calls Environment.FailFast to terminate the process fast. Then any function that meets an unexpected condition, simply calls DealWithUnexpectedConditions.

class StaticHelper

{

    public static void DealWithUnexpectedConditions(string message)

    {

        Environment.FailFast(message);

    }

     

}

 

class Runner

{

    internal void CheckCurrentProcessHealth()

    {

        if (!CurrentProcess.IsHealthy) // user defined methods

        {

            StaticHelper.DealWithUnexpectedConditions("The current process is not healthy");

        }

    }

 

    internal void CheckEnvironmentHealth()

    {

        if (!CurrentEnvironment.IsHealthy) // user defined methods

        {

            StaticHelper.DealWithUnexpectedConditions("The environment has some unexpected properties");

        }

    }

     

}

Because CLR doesn’t look at the entire call stack, it will treat a failure due to current process being unhealthy the same way as a failure due to unhealthy environment. The 2 failures will go into the same bucket, so the developer won’t see 2 different issues.  What we want to see is one more parameter that will ensure the categorization is done based on the hash of the current stack, which will take into consideration the callers as well as the current instruction that generated the failure.

Another issue with CLR WER integration is that for each change in WER, CLR must update its code. A very useful WER feature is collecting user-mode dumps. Starting with Windows Server 2008 and Windows Vista with Service Pack 1 (SP1), Windows Error Reporting can be configured so that full user-mode dumps are collected and stored locally after a user-mode application crashes. This is done by changing some registry values under HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\Windows Error Reporting\LocalDumps key. So, if you configure these values and a native application crashes, a dump will be generated irrespective of whether Windows Error Reporting is enabled or not. However, no dump is generated in the specified folder when a managed application crashes. Why? The changes in OS happened too late for CLR to be able to update the functionality for current versions; based on their priorities, the feature didn't meet the bar to be introduced as a DCR. .NET Framework 4.0 will not have this functionality on OSs lower that Windows 7. The behavior will probably be added in the version after .NET Framework 4.0.

In future versions, CLR will leverage the OS more to generate WER reports. This will ensure more consistency between the managed and native behavior and will make CLR WER integration less error prone.

Windows Error Reporting (WER) monitors and collects information on crashes and hangs on Windows platforms newer that Windows XP. The information collected can be sent to a server for investigation (read more in my previous WER article).

When creating reports, WER generates some parameters to bucket-ize the failures. Since the OS doesn’t know anything about managed applications, CLR integrates WER and adds these parameters to create correct buckets:

-          AppName - The filename of the EXE (e.g., “Explorer.exe”);

-          AppVer – Assembly version number for an managed EXE (major.minor.build.revision) or the PE header version number (e.g. “2.0.40220.13”) for unmanged

-          AppStamp - The timestamp on the executable.

-          AsmAndModName – Assembly and module name if the module is part of a multi-module assembly (e.g., “MyAssembly+MyModule.dll”)

-           AsmVer - Managed assembly version number of the faulting assembly (major.minor.build.revision)

-          ModStamp - The timestamp of the faulting module.

-          MethodDef - MethodDef token for the faulting method, after stripping off the high byte.

-          Offset - The IL offset of the faulting instruction.

-          ExceptionType -               The name of the type of the most-inner exception, with "Exception" removed from the end, if present. (E.g., "System.AccessViolation")

For example, I have a managed app (TestWERDefaultCategorizationAndDumps) that crashed. A report was created with these parameters:

Problem signature

Problem Event Name:                      CLR20r3

Problem Signature 01:                     XFU1LOPV1B5JQH0HBYGNH00TXWMZP45M

Problem Signature 02:                     1.0.0.0

Problem Signature 03:                     49833e70

Problem Signature 04:                     TestWERDefaultCategorizationAndDumps

Problem Signature 05:                     1.0.0.0

Problem Signature 06:                     49833e70

Problem Signature 07:                     1            -> methodDesc

Problem Signature 08:                     16          -> offset

Problem Signature 09:                     System.ArgumentNullException   -> exception type

OS Version:                                        6.0.6001.2.1.0.256.4

Locale ID:                                           1033

 

So the application crashed because a System.ArgumentNullException was unhandled. If we attach the debugger to the application (windbg –pn TestWERDefaultCategorizationAndDumps if the application is running or windbg TestWERDefaultCategorizationAndDumps to start the app under debugger), we can use the offset and the methodDesc to find out what happened. First, we need to load sos (.loadby sos mscorwks) and then we can use !token2ee Module MethodDesc to find out the method that threw. To determine the methodDesc, append 060000 to the number in the report.

0:000> !token2ee TestWERDefaultCategorizationAndDumps 06000001

Module: 0000064280012e20 (TestWERDefaultCategorizationAndDumps.exe)

Token: 0x0000000006000001

MethodDesc: 0000064280013580

Name: TestWERDefaultCategorizationAndDumps.Program.ThrowUnhandledException()

JITTED Code Address: 00000642801504b0

 

So the function that threw the exception is ThrowUnhandledException  in class Program (TestWERDefaultCategorizationAndDumps.Program.ThrowUnhandledException). Once we know the method desc, we can dump the IL of the method and see what line failed:

0:000> !dumpil 0000064280013580

ilAddr = 0000000000eb2050

IL_0000: nop

IL_0001: ldstr "Thow Argument Null Exception"

IL_0006: call System.Console::WriteLine

IL_000b: nop

IL_000c: ldstr "test"

IL_0011: newobj System.ArgumentNullException::.ctor

IL_0016: throw

The report says the offset is 16, so we look at IL_0016 and we find our throw. If we take a look at the code, it all makes sense:

static void ThrowUnhandledException()

{

    Console.WriteLine("Thow Argument Null Exception");

    throw new ArgumentNullException("test");

}

Windows Error Reporting is the replacement for Dr. Watson on OSs newer that Windows XP. It monitors failures and collects useful information that can be sent to a server to be analyzed (if the user allows it). This feature helped Microsoft to fix a lot of bugs – due to the reports received, Microsoft was able to prioritize bugs (based on the biggest number of hits or other severity measures) and to solve a lot of problems. What is really cool is that any developer can request the reports for his/her product. From Bill Gates at PDC 2003:  “..whenever an application or the system malfunctions, you get the ability to send a report back to Microsoft. We get a lot of those reports, and we've created very good data-management systems to go in and look at those things, and therefore understand what drivers aren't reliable. We allow anyone who has an application that runs on Windows to sign up and get the reports that relate to their application, and we've got winqual.microsoft.com where people can do that.

Here’s how WER works: when a process crashes, WER collects the data and sends it to a server (if the user allows it; by default WER asks for consent). For non-Microsoft programs, this server is Winqual (Windows Quality Online Services). On the server side: Based on the parameters of the crash, a bucket is created to hold the new error, or the report is added to an already existing bucket (which means someone met this issue before). A developer can analyze the failure; if a solution can’t be found based on the collected data, he/she can request additional information (a dump, registry key values etc). Also, he/she can add a message explaining the failure. When an instance of the same type of crash happens, the server will display the message the developer set and will ask for the additional information if necessary. If the developer finds a solution, at the next crash the server can provide solutions (see diagram below). Read more about error reports collection and classification.

WER Flow 

On Vista and above, the user with the crashed program can go to Control Panel -> Problem Reports and Solutions (start wercon.exe) to see what failures happened on the machine.

Problem Reports and Solutions

Here, you can check for solutionsand see identified problems.

Problem Reports and solutions - View problems 

You can look at the parameters for each issue and see the bucket in which the report was categorized.

Problem Reports and Solutions - Report Parameters

As a developer, you can go to Winqual and register to receive reports for failures. But there are other ways you can take advantage of WER. You can configure WER to send the reports to one of your servers, so you can take a look at them directly. For example, imagine you have a couple of machines you want to monitor. You can use System Center Operations Manager (SCOM) with Agenteless Error Monitoring (AEM) to transfer all reports to a monitoring server instead of sending them to Winqual. You don’t even have to use Active Directory integration and group policies, but you can manually configure the WER registry keys to specify the CorporateWERServer (with the port and the security options you prefer).

Another way to take advantage of WER is to save the reports locally. For the rest of the article, I will assume that WER is enables (default setting).

Like I said, WER tries to collect as little data as possible and asks for more only if necessary. But this behavior can be configured. If you need a dump collected at every crash, you can set HKEY_CURRENT_USER\Software\Microsoft\Windows\Windows Error Reporting\ForceQueue to 1 (or the HKLM\Software\Microsoft\Windows\Windows Error Reporting\ForceQueue=1, to apply the settings globally).This will force a dump to be generated and included in the report. The reports are usually saved at %localAppData%\Microsoft\Windows\WER, in 2 directories: ReportArchive, when a server is available or ReportQueue, when the server is not available. From here, the data is transferred to the server. Another way to look at the contents of the generated report, is to use wercon.exe (as explained above). If you want to keep the data locally, just set the server to a non-existing machine (HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\CorporateWERServer=NonExistingServer).

Now what if you want to generate reports on different conditions that a crash? Maybe you are monitoring the event log or some performance counters like CPU or memory and you want to see what happens when the conditions are violated. Or you want to generate more data than just a dump (for example, your applications has a trace file you want to save, or you want to copy event log entries etc)? Well, you’re in luck, because WER has API you can use. With this API, whenever your desired conditions are met, you can:

-          Create a report with WerReportCreate

-          Take a dump with WerReportAddDump

-          Add other files of interest with WerReportAddFile

-          Set up to 10 parameters that can be used to categorize the failure (the faulting program, the faulting function, stack trace, whatever you consider useful to investigate the issue)

-          Close and submit the report with WerReportSubmit

One thing you must keep in mind (and this was not obvious to me at all, I got burned actually) is that WerReportAddDump will suspend the threads one by one when taking a dump. That can’t ensure a consistent view of the memory - a thread can be suspended and then while the next one is suspended can change memory or do other damage; this is especially troublesome if your application has a lot of threads. It’s your responsibility to suspend all threads if you need a consistent view. Also, it is a good idea to call this function out of process.

Ok, so now you know how to use WER to always generate dumps on failure, send the reports to a server you specify or queue them locally and to build custom reports. Hope you'll find this info useful to debug and monitor issues related to your apps.

There are situations when we want to look closely at a process that is running in production environment – when a crash happens or when it just behaves badly (consumes too much memory, too much CPU, it hangs etc). There are multiple tools that can tell us what is wrong:

-          Event log (Window Key + Run -> type Eventvwr). Here we can see warnings and errors related to our app. This will shed some light in some of the situations, but quite often there are no entries that can help.

-          Performance monitor (Window Key + Run -> perfmon). We can look at the perf counters that are relevant to our application and the issue we are trying to investigate. In general, it’s a good idea to look at the perf counters to know what the processes are doing, but it won’t give us much insight on why apps crashed.

-          Sysinternal tools. These contain file & disk utilities, process utilities, networking utilities and much more. You can read more about it on Mark's blog.

-          Debuggers (Visual Studio, windbg etc). While developing and testing, the debugger is our best friend. In production however, debugging might not be just as easy. One way to investigate issues is to take dumps when something unexpected happens.

How do we take dumps?

When the process is running under debugger – it has cdb or windbg attached, we can use the .dump command. Most of the times we want a mini-dump. For a managed process, we need to take a full minidump in order to be able to load sos and debug the managed structures. Use the command .dump /ma dumpName.dmp – it will add full memory data, handle data, unloaded module information, basic memory information, and thread time information to the mini dump. If you want to generate multiple dumps with unique names, a simple trick is to add /u switch, that appends the data, time and PID of the process to the dump name.

Taking Notepad Dump using Windbg

If the process is not running under debugger, we can:

-          Attach the debugger – using <debugger> –p PID or <debugger> -pn ProcessName, where <debugger> is cdb or windbg, and then do what I mentioned above. For example, to attach the debugger to the worker process (and you have just one worker process running), use windbg –pn w3wp.exe. If you have multiple processes with the same name, you need to specify the PID of the process you want to attach (Eg windbg –p 1232). After attaching, take the dump and then run .detach to detach without killing the process. If you don’t want to keep running the process, use .q (ends the debugging session and closes the target application).

-          Use adplus in hang mode. This will take a snapshot of the process right now (not waiting for a hang or anything), then detaches and leaves the process running: adplus -hang -pn processname.exe.

-          If you want to take a dump later, when a crash will occur, use adplus in crash mode: adplus –crash -pn processname.exe. This attaches cdb.exe to the process in invasive mode, and waits for the crash – If it happens, it will take a full mini dump. It will also create mini dumps for access violation exceptions.

-          Use DebugDiag. DebugDiag it’s really easy to use – it has a graphic interface and we can manually take dumps by right-clicking the process in the processes view and by selecting Create Full Userdump.

DebugDiag: Manually take dump of a process

      With DebugDiag, we can also create crash rules or hag rules (for IIS).

 DebugDiag: crash rule

Take a look at this post with more details about DebugDiag and AdPlus (including some configuration files for AdPlus that let you control the behavior better).

There are some registry keys we can set to change the processes behavior:

-          Under HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\

o   GCFailFastOnOOM – This DWORD registry key causes failfast on out of memory conditions when it is set to a non-zero value:

§  1: an event message is logged in the application event log.

§  2: you experience a break in the debugger (app calls DebugBreak()).

§  4: an event message is logged that includes the size of the allocation that failed and the number of bytes in use, like “Failed to allocate x bytes with y bytes in use. Process will be Terminated.”

For more information, see this post on how to debug ASP.NET Out of memory exceptions using DebugDiag and this registry key.

o   DbgJITDebugLaunchSetting  - controls whether a debugger should be started and attached to the process that throws an uncaught exception. See Enabling JIT-attach Debugging article on MSDN.

o   DbgManagedDebugger – what debugger is used to debug managed code, if the previous setting shows that a debugger will be started

-          HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug – We can specify the Auto value and Debugger key that tells what debugger to be started in case of failure – full path and command arguments. The default value is “drwtsn32 -p %ld -e %ld –g”, that will start Dr Watson. To start Windbg instead, set Auto = 1 and Debugger="C:\Program Files\Debugging Tools for Windows\windbg.exe" -p %ld -e %ld

Later on, I will write a post about Windows Error Reporting, and how we can use it to take dumps and create reports.

Is it just me or most developers like to implement functionality and logic for their websites and freak out when they have to make it pretty? I personally hate writing style sheets – CSS may sound easy, and I understand the concepts, but don't ask me to apply them. CSS Zen Garden is a demonstration of what can be achieved with CSS, and it's really impressive.

The strange thing is that CSS looks easy; but when I have to write them, the headache hits. I start to diligently work to make my pages pretty in one browser, I somewhat succeed and then try a different browser – total disaster.

Matthew Osborn, a colleague in the ASP.NET team, wrote some simple web sites with CSS lessons. Take a look at http://css101.osbornm.com/ and http://css201.osbornm.com/. He also recorded some webcasts: CSS 101: The Basics screen cast & CSS 210: Theory and Practice screen cast.

For a simple tip, if you need to test your website in multiple versions of Internet Explorer, you can use Multi IE to install them on the same machine.

More Posts Next page »
 
Page view tracker