Showing posts with label programming. Show all posts
Showing posts with label programming. Show all posts

Thursday, May 20, 2010

Are C++ iostreams really slow?

In the C++ world, one often hears the statement “iostreams are slow, you should use printf instead”. Is this true?

It is possible that this story results from abuse of endl. Beginner's C++ books often recommend endl over '\n' for writing a newline. The observable result is often the same, but endl results in extra overhead: it flushes the stream. This results in a system call, slowing things down while often unnecessary.

Using my newly written TimedSection class, I tested whether the story is actually true, or just a myth. I tried three methods of printing:

  • cout with endl for line endings
  • cout with '\n' for line endings
  • printf (also with '\n' for line endings, so no forced flushing)

Each of these was tested in the following scenarios:

  • printing an empty line
  • printing a line containing a string literal
  • printing a line containing a string variable, a string literal, and an integer variable

All strings used were 20 characters long; I figured this would be a typical average length for printing messages. Newline characters were absorbed into string constants wherever possible.

Each of these was run 10 million times, redirecting the output to /dev/null. The testing machine is an Intel i7 920, running Ubuntu 10.4, Linux 2.6.32 and gcc 4.4.3.

Here are the results:

cout with only endl                     1461.310252 ms
cout with only '\n'                      343.080217 ms
printf with only '\n'                     90.295948 ms
cout with string constant and endl      1892.975381 ms
cout with string constant and '\n'       416.123446 ms
printf with string constant and '\n'     472.073070 ms
cout with some stuff and endl           3496.489748 ms
cout with some stuff and '\n'           2638.272046 ms
printf with some stuff and '\n'         2520.318314 ms

Surprise! Yes, for printing newlines, printf greatly outperforms cout. We can also see the huge slowdown of using endl inappropriately, something which is clearly to be avoided.

However, even for printing a moderately-sized string constant, cout outperforms printf. This effect becomes more pronounced as the string gets longer, probably because printf has to do more processing per character.

Finally, for some slightly more complicated formatting, the difference is quite small. For longer string constants, it becomes even smaller.

We can conclude that iostreams are definitely not always slower than C-style printf. It depends on the particular use, and as the formatting becomes more complicated, the difference drops to zero. Part of the myth may be ascribed to inappropriate use of endl; maybe another part is due to unoptimized implementations of the standard library. Either way: myth busted.

Update: For the curious, here is the full source code. You may need to link with -lrt to get clock_gettime.

#include <stdio.h>
#include <iostream>
#include <ctime>

class TimedSection {
    char const *d_name;
    timespec d_start;
    public:
        TimedSection(char const *name) :
            d_name(name)
        {
            clock_gettime(CLOCK_REALTIME, &d_start);
        }
        ~TimedSection() {
            timespec end;
            clock_gettime(CLOCK_REALTIME, &end);
            double duration = 1e3 * (end.tv_sec - d_start.tv_sec) +
                              1e-6 * (end.tv_nsec - d_start.tv_nsec);
            std::cerr << d_name << '\t' << std::fixed << duration << " ms\n"; 
        }
};

int main() {
    const int iters = 10000000;
    char const *text = "01234567890123456789";
    {
        TimedSection s("cout with only endl");
        for (int i = 0; i < iters; ++i)
            std::cout << std::endl;
    }
    {
        TimedSection s("cout with only '\\n'");
        for (int i = 0; i < iters; ++i)
            std::cout << '\n';
    }
    {
        TimedSection s("printf with only '\\n'");
        for (int i = 0; i < iters; ++i)
            printf("\n");
    }
    {
        TimedSection s("cout with string constant and endl");
        for (int i = 0; i < iters; ++i)
            std::cout << "01234567890123456789" << std::endl;
    }
    {
        TimedSection s("cout with string constant and '\\n'");
        for (int i = 0; i < iters; ++i)
            std::cout << "01234567890123456789\n";
    }
    {
        TimedSection s("printf with string constant and '\\n'");
        for (int i = 0; i < iters; ++i)
            printf("01234567890123456789\n");
    }
    {
        TimedSection s("cout with some stuff and endl");
        for (int i = 0; i < iters; ++i)
            std::cout << text << "01234567890123456789" << i << std::endl;
    }
    {
        TimedSection s("cout with some stuff and '\\n'");
        for (int i = 0; i < iters; ++i)
            std::cout << text << "01234567890123456789" << i << '\n';
    }
    {
        TimedSection s("printf with some stuff and '\\n'");
        for (int i = 0; i < iters; ++i)
            printf("%s01234567890123456789%i\n", text, i);
    }
}

Timing a section of code in C++

Sometimes it's useful to measure how long a certain part of your C++ code takes to execute. Here's a little utility class that makes this extremely easy. It can be used like this:

void foo() {
    TimedSection s("foo()");
    // do some long operation...
}

Calling foo() will print something like this to stderr:

foo()   336.856127 ms

As you may have guessed, a TimedSection records the time between its construction and its destruction. Since C++ has no garbage collection, destructors are called at a deterministic moment: when the local object (called s above) goes out of scope. If you want to time a section that is not a scope by itself, you can introduce a pair of braces to scope the object. If the section is even more complex (e.g. spanning multiple functions), you can use new and delete, but that destroys the elegant simplicity of TimedSection's usage.

The implementation is rather simple as well:

#include <iostream>
#include <ctime>

class TimedSection {
    char const *d_name;
    timespec d_start;
    public:
        TimedSection(char const *name) :
            d_name(name)
        {
            clock_gettime(CLOCK_REALTIME, &d_start);
        }
        ~TimedSection() {
            timespec end;
            clock_gettime(CLOCK_REALTIME, &end);
            double duration = 1e3 * (end.tv_sec - d_start.tv_sec) +
                              1e-6 * (end.tv_nsec - d_start.tv_nsec);
            std::cerr << d_name << '\t' << std::fixed << duration << " ms\n"; 
        }
};
I hereby release this little code snippet into the public domain. Enjoy!

Sunday, January 24, 2010

Review of free C++ IDEs for Linux

For my new project, I started looking into IDEs for Linux for the C++ language. And since I'm testing them anyway, I might as well write some quick reviews. ‘Quick’, because I'll mostly be going on first impressions, and some things I say might be quite wrong. Feel free to correct me in the comments!

My previous IDE experience includes Visual Studio for C++ and for C#, Eclipse for Java. I will sometimes compare to these.

Code::Blocks

I am greeted with very nice wizards, and it's easy to get up to speed. There is even a template for GLFW projects, which I select. But when trying to compile (using shortcuts nothing like any other IDE I know) I get a linker error; some XF86 library is missing, and even apt-file cannot tell me where to get it.

Hunting through the build settings, I notice many other problems. The settings are nested three levels deep: a bar with huge icons on the left, scrolling tabs (the horror) on the right, and nested tabs below those. Many options are unclear. When I press Esc to cancel my changes and dismiss the dialog, nothing happens.

Some parts of the Code::Blocks UI are really good, other parts are… not so good. I wouldn't want to work in this for a long time.

KDevelop

It starts up with a blank screen, so I have to ask it to create a new project myself. Not a big deal. The New Project wizard is reminiscent of Visual Studio, so I feel quickly at home. It allows me to create a CMake project; I like CMake. The wizard gives me a Hello World program, but I cannot run it: I have to create a Launch Configuration first. Then I run my program, I think, but where does the output go? The Debug Area (‘Perspective’) is empty. Turns out that building failed, because I moved the project in the mean time, and the project file contains absolute paths. Bad!

Support for external tools seems good. I already mentioned CMake; the Valgrind profiler and Git versioning system can also be used right from the IDE.

The IDE itself actually seems like a blend of Eclipse (borrowing much of its concepts and terminology), Visual Studio (some wizards and the layout of dialogs) and Kate (the general KDE stuff). Not bad at all. Still, I had some trouble getting everything set up, but once you've taken the time to do that, KDevelop might be a decent IDE.

Eclipse

Big, bloated, but feature-rich and quite user-friendly once you've warmed up to it. That's been my impression of Eclipse for Java, which I'm quite familiar with. For Java, it's easily the best IDE around; the refactoring options alone make it worthwhile. Let's see how Eclipse with the CDT plugin performs for C++.

I install Eclipse, grab the CDT plugin through its update site and restart Eclipse. A few clicks later, I have an empty C++ project. I add a main Hello World file, and after some strange trouble with the Debug Configuration, it runs. I add a library to link with, finding the option without any difficulty. Not being unhappy about this, I continue to write some more code, to try the completion and refactoring features.

Completion pleasantly surprises me. This stuff is better than Visual Studio's. It's fast, it's accurate, it gets the contents of a newly included header file right after I saved… nice! Smart insert mode adds closing paretheses, braces and quotes, but if I type them myself as well, they are overwritten.

Error highlighting is equally fancy. Unlike Visual Studio, syntax errors are highlighted in real time, without even having to save the file.

I ask it to create a new class, and get a header and source file with a nice skeleton. It's not exactly the way I would write it, but I'm sure it's customizable.

Refactoring, unfortunately, is not as fancy as it is for Java. It is limited to renaming identifiers, and doesn't rename the source and header file accordingly. It can also extract selected expressions/statements into a separate function, but it does not create this as a member function. There are no “quick fix” options for adding include directives, like with Java. Yet, it's better than what Visual Studio offers on this front.

Eclipse with the CDT plugin is not perfect, but it's good. I could live with it.

Anjuta

I am greeted with a welcome screen, which I ask to create a new project. I am asked for all kinds of needless details, like the license type and my e-mail address. No wonder: it creates an entire autotools project for me. I tried to add a library to the linker command, but couldn't find the option anywhere. Do I really have to edit the Makefile.am?

I've only had a brief look, and Anjuta seems like a nice IDE if you want what it wants, but at first sight doesn't seem flexible enough to cope with everything.

Qt Creator

Would this work for non-Qt applications as well? It wouldn't seem so at a first glance, but I imported an empty directory as a Makefile project, which seemed to work. I had to write a Makefile, of course, which failed because the IDE quietly changed my tab to four spaces. After fixing that, and some directory issues, I could build the program. Running it required similar trickery.

Code completion works very well, and identifiers from a newly included header are available quickly. The entire IDE looks and feels smooth and polished, and is reminiscent of Visual Studio in many details.

The build system remains weird, though. It created an autotools project for me, with about a dozen files, and not offering me any choice in the matter. There is a reference to CMake in the Preferences, but no clue how to create a CMake project.

Qt Creator is a slick, clean, usable IDE. I like it. Still, it is very Qt-centric, and its build system seems inflexible. Too bad.

NetBeans

Yes, another Java IDE that can be used for C++. I have actually never used NetBeans for Java before, so I have no preconceptions about how it should work.

I apt-get the IDE and install the C/C++ plugin; this is very straightforward. I create a new C++ project, and a Makefile gets created automatically. I run the empty main function, and the program pops up in an external terminal.

Then I start editing the code, and I'm pleasantly surprised by the editor. Not just syntax errors, but unknown identifiers get highlighted in real time. Function signatures pop up in a large, but helpful tooltip. Even the filenames of include files are autocompleted! The contents of the include file become available without even having to save the file.

Yet, not all compile errors are highlighted, even though you can click to them from the compiler output window. I could not manage to get the function signature to reappear while I was typing arguments. Refactoring options are all grayed out; I assume those work for Java only.

The project settings are very much like Visual Studio, but allow for little customization. It's just enough to add a -l flag to the linker command line to link in an external library. There is also Git integration (if you install the plugin) but I didn't try it.

I checked out NetBeans as an afterthought, but that seems to have been a mistake. Of all the IDEs I tried, this is actually one of the nicest. It doesn't have many bells and whistles, and its build system might be inflexible, but the code editor makes up for it.

Conclusion

Are IDEs for C++ worth the trouble? I'm not sure. The value of an IDE lies in fast code editing, refactoring options, easy building, and error highlighting, and integrated debugging. None of the IDEs I tried score highly on all these fronts. I can understand: a flexible, usable IDE for C++ is almost impossible to create. Maybe I'll just go back to my trusted old Kate and gnome-terminal…

Tuesday, February 26, 2008

Visual Studio/C++: Requested the Runtime to terminate?

The Visual Studio/Visual C++ woes continue. This time, my C++ application gave the message “This application has requested the Runtime to terminate it in an unusual way.” and my application died. This didn't happen on my development machine, but on a different machine on which I ran a Release build.

Googling gave me scary stuff, and that I'd need a hotfix that was not publicly available—you need to contact Microsoft to get it, so I did, and received the hotfix within the hour, but didn't need to install it anymore.

Turned out that the problem was something quite different. My application threw an exception, because a file was not found on the other machine. The error message actually meant to say: “This application threw an unhandled exception.” Thank you, Microsoft.

So, if you ever receive this message, before you look any further: make sure you catch every exception you throw.

Sunday, December 30, 2007

Visual C++/Studio: Application configuration incorrect?

If you have just written a program in Microsoft Visual C++ or Visual Studio (2005 and above, I believe), try to run it on another machine, and get the error message “This application has failed to start because the application configuration is incorrect. Reinstalling the application may fix this problem.” then you want to read on. If you just want to see me rant at Microsoft, read on as well.

The problem is really simple. If you write a C++ program, it links dynamically to the C Runtime Library, or CRT for short. This library contains your printf, your malloc, your strtok, etcetera. The library is contained in the file called MSVCR80.DLL. This file is not by default installed on a Windows system, hence the application cannot run.

The solution? Either install the DLL on the target machine through VCREDIST.EXE (the Visual C++ Redistributable Package), or link to the CRT statically (plug the actual code for the used functions straight into your EXE).

Distributing and installing VCREDIST along with a simple application is a pain in the arse, so I went for the second option: static linking. It's really easy: go to your project's properties, unfold C/C++, click Code Generation, and set the Runtime Library to one of the non-DLL options. That's all there is to it.

Now comes the rant part: how much effort it took me to figure all this out. You have been warned.

  1. “This application has failed to start because the application configuration is incorrect. Reinstalling the application may fix this problem.” What kind of error message is that? It's like saying “sorry, your car does not work, because the engine won't start; please buy a new car.”
    In the very least, you could tell me that I'm missing a DLL. Preferably also tell me which particular DLL.
  2. Reinstalling the application, like the error message suggested, did of course not fix my problem. But the message also does not give a hint where to go looking for the error. It took some web searching to figure that out: the Event Log. Itself hidden quite well inside Windows, it told me which particular DLL was missing on the system. The Dependency Walker, that also comes with Visual Studio, told me that MSVCR80.DLL was indeed the culprit.
    The error message should at least point toward the more useful information: “See the Event Log for details.”
  3. I searched around on the web for MSVCR80.DLL and found its purpose. It turned out to be possibly the most basic library any C programmer could wish for. So why the heck is it not installed on any Windows system? It turns out that some older versions of the CRT are installed with Windows, but these are really ancient and buggy, and I honestly wouldn't know how to make Visual Studio link against them.
    So why, in these days of automatically updating systems and always-on internet connections, is this small (612 kB) but very essential DLL not included in service packs, or in Windows Update?
  4. Now, to fix the problem, I had to install the DLL on the target system. Simply dropping it alongside my application didn't work, because nowadays DLLs actually need to be installed. This is because modern DLLs are what Microsoft calls Side-by-side (SxS) Assemblies, which have been introduced in a brave attempt to diminish DLL hell. I don't know the gory details; it's something to do with manifests, and probably lots of candles, pentagrams and holy water as well.
    Anyway, you cannot download the VCREDIST installer straight from the Microsoft website, because there's only an old version there. Or is there? A newer page does give you what you want, and there's a 2008 version too.
  5. Thinking that it must be possible to link statically to the C Runtime Library, I looked into the project options in Visual Studio. I could not find the option there. Not very surprising, considering its name: “Runtime Library.” What runtime library? The Grand Unified DLL of Making Coffee? Or is this just a general option relating to runtime libraries in general? The default value (“Multi-threaded DLL”) seems to suggest this. I dared not touch this option for fear of breaking my application. It's a common problem with Microsoft: they often use a very generic-sounding name for something very specific.
    Had the thing been called “C Runtime Library linkage” instead, I would immediately have grasped its meaning.

On a not completely unrelated note, I'm pleased to announce that this bug in Taekwindow has finally been resolved.

Friday, May 4, 2007

Equality checking on interrelated objects

Most, if not all, object-oriented programming languages allow you to define what it means for two objects to be “equal”. In C# and Java, this is done by overriding the Equals or equals function, respectively.

But what to test when comparing two objects? You'll obviously want to compare (most) instance fields, for example the name of a person or the number of wheels of a car. But it's less obvious when an object is (conceptually) part of another object, or dependent on it in some other way. I ran into such a situation today.

Consider the class Pig. A Pig is associated with a Farmer, the owner. Each farmer has, in turn, a list of ownedPigs. (I use Java capitalization conventions here to make a clear distinction between types and fields/methods.)

Suppose we want to check whether two Pigs are equal. (Do not just return true. Some animals are more equal than others.) Clearly, two Pigs are not equal if they are owned by a different Farmer, so we need to compare their owner fields. Reference equality on this field is not enough: if we can have multiple Pig objects representing the same pig, then the owner fields may well refer to different objects representing the same farmer. So we do a value comparison of the owner fields, by calling owner.equals.

Of course, two Farmers are not equal unless they own the same Pigs. We have to call Pig.equals for each owned pig. This, in turn, calls Farmer.equals, which calls Pig.equals … and so on ad infinitum (which is Latin for “stack overflow”).

How to solve this problem? The key is, when equality of type A depends on equality of A's fields of type B and vice versa, to check not the entire B objects for equality, but only compare the parts we're interested in.

For example, a Pig couldn't care less what the social security number of its owner is. It does, however, care where he lives: a pig on the South Pole will have very different life circumstances from one in the Sahara. In Pig.equals we would then only compare the addresses of the owners, and not the entire Farmer objects.

With this modification, the cycle is already broken. We could also tackle the problem from the other side: the Farmer cares only about how fat his pigs are, but not about their political preference. When comparing two Farmers we could look only at the weight of all their ownedPigs, disregarding their vote field.

I admit this example is a little contrived. I'm not programming an animal farm. But if you ever do, and your Pig.equals method gets called with a Farmer object, remember to return false.

Wednesday, May 2, 2007

Checks, exceptions and assertions

When programming in most modern languages, there are basically three different ways to deal with errors or abnormal situations: checking, exceptions and assertions. However, some people seem to misunderstand when to use which.

A check is the oldest trick in the book. It's simply an if (or equivalent) statement that checks whether a certain error condition holds. An exception can be raised (thrown) at the point where the error occurs, and then handled (caught) by any function lower down the call stack. An assertion is also a sort of check, but usually in the form of a library call or a language construct. A failed assertion usually results in terminating the program. Assertions can often disabled by a compiler parameter.

Now here's the flowchart that'll tell you which way of error handling to use:

  1. Do you think this error will ever occur?
    1. No » Use an assertion.
      Assertions reflect a claim made by the programmer: “this will never happen”. If it does happen, it must signify a bug. If you use assertions for anything else than validating things that you think must be true, you're using them incorrectly. Also, it's perfectly okay for a program to abort (with a meaningful message, mind you) when it encounters a bug during testing.
    2. Yes »
      Will this error occur in normal circumstances?
      1. No » Use an exception.
        Exceptions are made for, well, exceptional circumstances. They're meant for situations that you overlooked, or chose to overlook because they seemed (rightly or wrongly) rare enough that a check wasn't worth the effort. The great thing about exceptions is that they can be handled at a much higher level than the place where the error occured, a power that simple checks don't have. You can use this to catch the rarer errors at a high level, not having to scatter error checks all over the place.
      2. Yes » Use a check.
        Verify whether a file given on the command line exists. Do make sure that a person's last name does not contain any quotes. These are things that are actually expected to fail occur once in a while, even under normal circumstances. You can nearly always handle them locally, so there is no need to throw an expensive (performance-wise) exception around.

It's quite simple, really.

Monday, April 30, 2007

Review: Free C# code analysis tools

Over the upcoming days, I'll be reviewing the C# code I'm working on for my Bachelor's thesis. It consists of nearly 9.000 lines of code (over 300 kB), so I felt somewhat reluctant to read it all through. I decided to try and identify the most obvious problems using automated code analysis tools first. Because I use Visual Studio 2005 under Windows for C# development, the reviews will mainly be targeted at this environment.

I tried the following programs:

Potential problem detection
FxCop, Code Analyzer, Gendarme, devAdvantage
Quality metrics
devMetrics, NDepend, SourceMonitor, vil
Code coverage
NCover
Similarity detection
Simian

None of the following reviews are very comprehensive, because I only played around with the tools for a little while, but these reviews can give you a good indication on what to use and what to ignore.

FxCop

The FxCop program by Microsoft themselves checks assemblies for compliance with the .NET design guidelines, and identifies potential problems within the code.

Features

FxCop checks a lot of issues with Microsoft guidelines. It gives a certainty percentage for each issue found, and also clearly explains what the problem is, and how to fix it. Some of the more interesting issues that are checked for:

  • Are exceptions raised that should not be raised by user code? For example, System.Exception should not be thrown directly.
  • Is an IFormatProvider supplied when converting strings to numbers? Very important if your code is to behave correctly under other locales.
  • Are reference parameters of methods checked to be non-null before use?
  • Are fields initialized to default values that are already assigned by the runtime, like null for reference fields? This would result in an unnecessary extra assignment.
  • Does the string argument to ArgumentOutOfRangeException contain the name of the argument?
  • Are there any unused local variables?
  • Are you using public nested classes? These are considered harmful by the guidelines.
  • Do abstract types have a public constructor? This should be made protected.
  • Are there any unused methods?
  • Are variables like fileName capitalized correctly? “filename” is wrong since “file” and “name” are (apparently) separate words.
  • Are you using a derived type as a method parameter where a base type would suffice?

This list goes on and on. FxCop found 557 issues in my code from dozens of different rules.

You can jump directly from an issue to the corresponding source line(s) in Visual Studio or another application of your choice.

Judgement

I'm very impressed by the comprehensive list of flaws that this program detects. It is definitely very useful for anything larger than a toy application.

Code Analyzer

At first glance, the Code Analyzer tool seems to do similar things to FxCop. And indeed the website provides us with a useful list of the differences, broken English included:

FxCop advantages (comparing to Code Analyzer):
  • Extensive set of rules available out of box. Code Analyzer provides just limited set of sample rules.
  • Since it works with assembly metadata works with code created in any .NET language. Code Analyzer works now just with C# sources.
Code Analyzer advantages (comparing to FxCop):
  • FxCop is limited to assembly metadata, Code Analyzer works with source code and provides more functionality like comments, position in source code and more.
  • FxCop has flat rules structure, which makes orientation in policy more difficult for larger policies. Code analyzer has hierarchical structure, based on logical rules categories.
  • FxCop provides only one type of report, Code Analyzer is flexible and provides more report types and users can create their own report types.

Especially the first advantage of Code Analyzer, source code inspection (as opposed to assembly inspection) seems worthwhile. Unfortunately, the program crashed on startup so I am unable to test it.

Gendarme

Powered by the Cecil code inspection library, Gendarme tries to identify points of improvement in your code based on a certain set of rules. There is no binary version yet; you'll have to build it yourself from an SVN checkout.

Features

There is no GUI or IDE plugin, so you're stuck with the command line. Gendarme is run on assemblies, so it does not inspect the actual source code. On my program, it identified the following problems at multiple points in my code:

  • You should use String.Empty instead of the literal "", because it gives better performance.
  • A static field is written to by an instance method. (This was intentional: each object gets a unique ID, and I increment the “next ID” field in the constructor.)
  • Newline literals (\r\n or \n) in strings are not portable; use Environment.NewLine instead.

All in all, useful, but nothing spectacular.

Judgement

This could become a very useful tool, if the rule set is expanded. At the moment it will not identify very much. The lack of a decent user interface limits its practical use.

devAdvantage and devMetrics

devAdvantage is a Visual Studio add-in that helps you identify areas that might use refactoring. devMetrics is an add-in to compute code complexity metrics. The Community Editions can be downloaded for free. The programs look interesting, but do not work on Visual Studio 2005. Bummer.

NDepend

NDepend is a very feature-rich quality measurement tool, also powered by Cecil. It operates on .NET assemblies, but because it also extracts debug information it can link this back to the original source code. A free one-month version can be downloaded for trial, academic and open-source use. You can view the getting-started animation to get an idea of the possibilities.

Features

NDepend uses CQL, the Code Query Language, to extract information about the code. It allows you to construct your own queries if you're willing to invest the time to learn this. CQL is similar to SQL; take a look at this demo (3 minutes 30 seconds, Flash). For example, you can find all methods with over 200 intermediate language instructions, and sort them by descending number of instructions, using the following query:

SELECT METHODS WHERE NbILInstructions > 200 ORDER BY NbILInstructions DESC

NDepend comes with a few dozen built-in CQL queries that measure certain aspects of your code and can be used to quickly spot potential problems.

NDepend will spit out an HTML file like this one with humongous amounts of information on your project, most of which is just detailed factual information that is almost entirely useless. In my situation, NDepend failed to include the CQL results in the HTML file for some unknown reason.

The HTML file does, however, contain some useful information. It provides you with a table where the worst statistics are highlighted per method. It also lists warnings that, as far as I could tell, are not produced with CQL queries. In my case these were mainly “method so-and-so is protected and could be made private” warnings.

Other interesting features are the TypeRank and MethodRank, computed like the proven Google PageRank. It shows which types and methods are the most important in your program. On my program it did indeed give a very good indication.

The main part of the program is the VisualNDepend. This produces a two-dimensional chart much like the disk-space charts from SequoiaView (among others). The area of each rectangle indicates the value of some metric. by default this is the number of lines of code of the respective class or method, but you can also select metrics like the MethodRank or the cyclomatic complexity.

Unfortunately, there is no easy way to ignore certain source files or methods, e.g. designer-generated code. You'll want to ignore these while scanning the results, because generated code usually makes for terrible metrics. You can use CQL to do this, but you'll have to modify each of the predefined CQL quality metrics.

Judgement

NDepend is a difficult tool to work with at first. It can give you a wealth of useful information once you get the hang of it, but for a quick inspection it is less practical.

SourceMonitor

SourceMonitor is a simple free program to compute quality metrics on your code. Apart from C#, it can also be used for C, C++, Java, Visual Basic, VB.NET, Delphi and (strangely) HTML.

Features

SourceMonitor produces a table view of some quality metrics of your code, organized per source file. In the table view, you can double-click on any source file to get more detailed information about this file. This produces, among others, a chart showing how many statements are at a particular “block depth”, the number of brace pairs surrounding it.

The program creates a checkpoint for each measurement, so you can easily track the (hopefully) downward slope of your program's complexity while you are refactoring.

Judgement

A simple, yet useful tool. Very easy to use and understand.

Vil

Everything that Vil does, according to its web site, is done better by NDepend. Also, Vil has no GUI yet and gives a very discontinued impression. I won't bother.

NCover

NCover is a code coverage tool. Its main purpose is to determine how much of your code is covered by your unit tests. It does this by simply running the program or tests and looking which lines are actually executed.

Features

NCover is a simple command line tool without many bells and whistles. Simply tell it which program to run. It generates a large XML file with the output data (445 kB already in my relatively small program). The XML can be viewed with an accompanying XSLT style sheet, which you have to copy over to the right directory yourself.

The resulting view gives you a percentage bar for each class, showing the amount of code executed in that class. Clicking the class name expands it, breaking it down into methods. Clicking a method name breaks it down further into its individual lines.

There are ways to run NCover periodically and monitor the coverage of your tests. I haven't tried this.

Judgement

A simple tool, but more useful than I thought at first glance. It can give you a good indication which parts (especially, which if branches) your unit tests have missed. (Then again, this turns unit testing more into a white-box test when it was intended to be black-box.)

Simian

Simian identifies regions of code that are similar. It is a little Java-oriented, but also supports many other popular languages. Simian is free for non-commercial projects and for trial purposes.

Features

There is no GUI or Visual Studio plugin, you'll have to work from the command line. This hugely diminishes the ease of use, especially because the Windows command prompt is so clunky. Simian produces a list with entries like the following:

Found 11 duplicate lines in the following files: Between lines 30 and 63 in maths\MatrixAlgebra.cs Between lines 28 and 61 in maths\Vector.cs

Correct, MatrixAlgebra.cs was split up into Matrix.cs and Vector.cs, and should be removed entirely.

Judgement

A duplicate code finder sounds very useful, but it's use is very limited. It found nothing useful on my project. The results may vary for other coders. In any case, the lack of IDE integration for .NET analysis makes using this tool more effort than it's worth.

Conclusion

If you care about the details, don't look any further than FxCop. It's very comprehensive and easy to use. Code Analyzer may complement FxCop nicely, if you can get it to run.

For a more general view on things, NDepend can be very useful, if you're willing to invest some hours to get acquainted with it. For a quick overview, SourceMonitor can be a better alternative.

If there's any free program that I've overlooked, please let me know so I can include it!