I have decided to make a comparison for file IO operations on Win32, CRT, STL and MFC.

For all four libraries/APIs I have done the profiling in the following way:

  • open the file
  • allocate the buffer used for reading
  • start the timer
  • read/write from/to the file
  • stop the timer
  • close the file
  • release the memory

This way, the profiling only applies on the read or write operations, not on other task such as opening and closing files, allocating or releasing memory.

What I’ve used:

  • Win32: functions CreateFile, ReadFile, WriteFile and CloseHandle
  • CRT: functions FILE, fopen, fread, fwrite and fclose
  • STL: for reading class std::ifstream, and methods, open(), read() and close() and for writing class std::ofstream and methods open(), write() and close()
  • MFC: class CFile, and methods Open(), Read(), Write and Close()

I have performed the reading with different buffer sizes: 32, 64, 128, 256, 512 bytes and 1KB, 2KB, 4KB, 8KB, 16KB, 32KB, as well as with a buffer accomodating the entire file. Same buffer sizes were used for writing. For testing the write operation I also wrote the file at once. In all cases, I generated a 16MB file.

To decide which one is better overall, I have associated a score with each result. The faster (for each buffer size) got 4 points, the next 3, 2, and 1. The bigger the sum, the more performant overall.

I have run the program on two files for reading on a Intel(R) Pentium(R) 4 CPU at 3.20GHz, 1 GB RAM, running Windows XP, SP2. The results, representing an average of 15 runs, are shown bellow:

File 1: size 2,131,287 bytes

Buffer Size CRT Win32 STL MFC CRT Win32 STL MFC
32 0.01917630 0.063093700 0.02123180 0.064283700 4 2 3 1
64 0.01474360 0.031909200 0.01460960 0.032482700 3 2 4 1
128 0.01118370 0.016183700 0.01164060 0.016426700 4 2 3 1
256 0.00929148 0.008573490 0.01063090 0.008840810 2 4 1 3
512 0.01071420 0.004684040 0.00985086 0.004745970 1 4 2 3
1024 0.00883909 0.002584480 0.00907385 0.002486950 2 3 1 4
2048 0.00847502 0.001531440 0.00894887 0.001477660 2 3 1 4
4096 0.00776395 0.000981391 0.00891128 0.001009350 2 4 1 3
8192 0.00740465 0.000744340 0.00913489 0.000749145 2 4 1 3
16384 0.00740928 0.000604900 0.00936410 0.000673978 2 4 1 3
32768 0.00736531 0.000657141 0.00837419 0.000610040 2 3 1 4
file size 0.00955846 0.002496180 0.00981464 0.002428280 2 3 1 4
          28 38 20 34

File 2: size 110,999,662 bytes

Buffer Size CRT Win32 STL MFC CRT Win32 STL MFC
32 1.011360 3.3216500 2.47695 3.2822700 4 1 3 2
64 0.742683 1.6815600 0.804563 1.6836300 4 2 3 1
128 0.600344 0.8697840 0.639113 0.8750610 4 2 3 1
256 0.521233 0.4661430 0.586376 0.4751340 2 4 1 3
512 0.501420 0.2734540 0.532212 0.2653010 2 3 1 4
1024 0.474670 0.1532950 0.510266 0.1587330 2 4 1 3
2048 0.458538 0.1012430 0.479981 0.1067980 2 4 1 3
4096 0.432552 0.0715536 0.488251 0.0774886 2 4 1 3
8192 0.417481 0.0607284 0.467426 0.0674372 2 4 1 3
16384 0.400320 0.0510897 0.458111 0.0602826 2 4 1 3
32768 0.406497 0.0503835 0.461796 0.0572124 2 4 1 3
file size 0.523950 0.1867240 0.583327 0.1828440 2 3 1 4
          30 39 18 33

The first conclusion is that overall Win32 is the fastest, followed by MFC, then by CRT, the slowest being the STL.

The second conclusion is that CRT is the fastest with buffer sizes smaller than 256 bytes, and then Win32 and MFC are the faster.

The results for writing were a quite similar. Of course, running several times, can produce slight variation in the results (both for read and write).

File 3 : size 16,809,984

Buffer Size CRT Win32 STL MFC CRT Win32 STL MFC
32 0.273796 0.890973 0.335245 0.877301 4 1 3 2
64 0.219715 0.465254 0.259597 0.450076 4 1 3 2
128 0.181927 0.24715 0.201949 0.245169 4 1 3 2
256 0.178976 0.141146 0.189154 0.143666 2 4 1 3
512 0.153816 0.0872411 0.172239 0.0851424 2 3 1 4
1024 0.148846 0.0608282 0.159186 0.0601419 2 3 1 4
2048 0.139997 0.0493811 0.150503 0.0496117 2 4 1 3
4096 0.125797 0.0705146 0.15275 0.0508061 2 3 1 4
8192 0.126708 0.15708 0.1459 0.0655567 3 1 2 4
16384 0.121919 0.0282886 0.14662 0.158024 3 4 2 1
32768 0.124429 0.0247259 0.145496 0.0267301 2 4 1 3
16809984 0.148424 0.47066 0.146321 0.513205 3 2 4 1
          33 31 23 33

You can download the project I used for the benchmark from here.

Hits for this post: 18803 .

Every once in a while, I run into this site teaching techniques for writing unmaintainable code. Of course, the hole purpose is to teach exactly the contrary (or at least that’s what I hope). Some of my favorite techniques are:

  • use of single letter variable names, which of course makes searching almost impossible, and even less the understanding of what they stand for;
  • creative miss-spelling: use correct spelling of a word in some place, and mis-spell it in other places, if possible, in different ways; that will definitelly confused many people;
  • be as abstract as possible, by naming functions like DoYourStuff, Execute, DoIt, RunIt, etc.;
  • use Hungarian notation as the ultimate “tactical nuclear weapon of source code obfuscation”;
  • use long similar variable names, that differ only in a letter or even only in the case;
  • pass all data as pointer to void and then typecast into the appropriate type;
  • comments on top of functions should be at least 15 lines long and use a lot of blank lines (I love this one)

The site shows a lot more techniques, and I encourage you to read them, not for using, but for avoiding them. Because the code should be readable in order to be maintainable.

http://mindprod.com/jgloss/unmain.html

Hits for this post: 3882 .

Today we celebrate 30 years since Star Wars, A New Hope was released. It is estimated that 1 billion people have seen the movie. Here are my favorite lines from the saga:
Obi-wan “Use the Force, Luke”.

Leia: “I love you”. Han: “I know!”

Vader: “I am your father.”
Luke: “No. No. That’s not true! That’s impossible!”

Luke: “Jabba! This is your last chance. Free us or die.”

C-3PO: “I beg your pardon….what do you mean I’m naked? My parts are showing? Oh, my goodness. How embarrassing!”

Obi-Wan Kenobi: “Why do I get the feeling you’re going to be the death of me?!”

C-3PO: “Erase my memory?! Oh no!”

Padme: “I’m not afraid to die. I’ve been dying a little bit each day since you came back into my life.”

Chewbacca: “Groarggrrrrrrraaarrrrrrr! Gggrrrorrrrrrg! Gggrrrr!”

Leia: “You’re imagining things.”
Han: “Am I? Then why are you following me? Afraid I was going to leave without giving you a goodbye kiss?”
Leia: “I’d just as soon kiss a Wookiee.”
Han: “I can arrange that. You could use a good kiss!”

To all the fans in the world, may the Force be with you!

Hits for this post: 8624 .

Working correctly with the Windows Registry might prove a little difficult, especially for beginners. One thing one should care about for example is using the correct access rights (not just the default ones) when creating a registry key. To ease the burden of directly using the Win32 registry API, I decided to wrap them inside two classes and make them available for anyone that wants to use them.

The classes that I put together are:

  • SecurityAttributesUtils: this is transparent for the developer, and is used to create the necessary access rights for creating a registry key;
  • RegistryUtils: offers static functions for creating, deleting and closing a key, as well as reading and writing double words, strings and binary data to/from the registry;
  • RegistryUtilsEx: a class based on RegistryUtils used for reading and writing strings and binary data, that uses STL’s std::string or std::wstring classes.

To create a key you should use RegistryUtils::CreateKey. It takes a handle to an open key (usually one of the predefined keys HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, etc. or an already opened key), the name of the subkey the function opens or creates and the desire access rights. It returns the handle to the opened or created key as the first argument, and a value indicating the success or failure.

HKEY hKey = NULL;
// create or open the key
RegistryUtils::RegResult OpenMode = RegistryUtils::CreateKey(HKEY_CURRENT_USER,
		_T("Software\Bancila\Test"),
		KEY_READ|KEY_WRITE,
		hKey);



To write a string use either RegistryUtils::WriteString or RegistryUtilsEx::WriteString string if you use STL std::string or std::wstring. It takes the handle to the key, the name of the value and the value to write.

RegistryUtilsEx::WriteString(hKey, _T("key1"), _T("value1"));



To read a string use either RegistryUtils::ReadString or RegistryUtilsEx::ReaderString, the later for working with STL’s strings.

tstring str;
// read a string
if(RegistryUtils::Success != RegistryUtilsEx::ReadString(hKey, _T("key1"), str))
{
  // if not present, write it in registry
  RegistryUtilsEx::WriteString(hKey, _T("key1"), _T("value1")); 

  // now it should be read
  RegistryUtilsEx::ReadString(hKey, _T("key1"), str);
}



Simillary, you can use ReadDword() and WriteDword() for reading and writing integer values, and ReadBinary() and WriteBinary() for generic binary data.

// read an integer
DWORD number;
if(RegistryUtils::Success != RegistryUtils::ReadDword(hKey, _T("key2"), number))
{
  // if not present in the registry, write it
  RegistryUtils::WriteDword(hKey, _T("key2"), 44); 

  // this time it should be read
  RegistryUtils::ReadDword(hKey, _T("key2"), number);
}



To close an opened key call RegistryUtils::CloseKey().

RegistryUtils::CloseKey(hKey);


Additionally, RegistryUtils::DeleteKey() can be used to delete a specified key, along with all its sub-keys and values.

The code is available for download here.

Hits for this post: 13001 .

Suppose you have the following code:

void foo()
{
  throw std::runtime_error("a foo exception!");
}  

int main()
{
  foo();
}

When running the program, the following window is popped up:


When running it in the debugger, a different window is popped up:


and the debugger takes you to the line of code that threw the exception. Looking into the output window, you can see something like this:

First-chance exception at 0x7c812a5b in win32test.exe: Microsoft C++ exception: std::runtime_error at memory location 0x0012fd70..
Unhandled exception at 0x7c812a5b in win32test.exe: Microsoft C++ exception: std::runtime_error at memory location 0x0012fd70..

It shows a first-chance and an unhandle (also knows as second-chance) exception message. When running a program in debugger, the debugger always sees the exception before the program does. Thus, it is said that the debugger gets a first chance to handle the exception. If it does not do that, and the execution continues, the program will see the exception and has a chance to handle it. If the exception is not handled by the program, the debugger gets a second-chance to see the unhandled exception. This is the point when in the absense of the debugger, the program crashes.

So, what happened with the program above: the debugger saw an exception and printed the first-chance exception message, but did not handle it, and the program was allowed to continue. However, the program did not handle the exception either, and the debugger got its second-chance with the unhandled-exception; the unhandle exception messages was printed and the exception windows was popped.

Of course, you could change to code in function main to this:

int main()
{
   try {
      foo();
   }
   catch(...) {
   }
}

In this case when run, the program will not crash. But when running in the debugger, you will see the first-chance exception message:

First-chance exception at 0x7c812a5b in win32test.exe: Microsoft C++ exception: std::runtime_error at memory location 0x0012fd5c..

In this case, the program handled the exception (by doing nothing) and the debugger did not get the second-chance.

Now, suppose your program is much langer than the several lines of code shown above. When running in the debugger you see first-chance exception messages, but not the second-chance exception message, because your program handles the exception. Should you investigate the cause of the exception, problems arise simply because you don’t know where the exception was thrown. The good news is that you can customize the debugger to break on first-chance exception.

From the Debug menu, use the Exceptions command to open the dialog that allows you to specify on which exception should the debugger break.

There are several categories:

  • C++ exceptions
  • Common Language Runtime Exceptions
  • Managed Debugging Assistants
  • Native Run-Time Checks
  • Win32 Exceptions

By default, none of the C++ exceptions is checked. That means if you check std::exception (as shown in the picture), the debugger should stop when and exception of a type derived from std::exception is thrown. (To verify that run the code aboe in the debugger again.)

What if std::runtime_exception was replaced with a custom exception, foo_exception?

class foo_exception
{
  std::string Message;
public:
  foo_exception(const std::string& message):
    Message(message)
  {
  }  

  std::string GetMessage() const {return Message;}
}; 

void foo()
{
  throw foo_exception("a foo exception!");
}  

int _tmain(int argc, _TCHAR* argv[])
{
  try {
     foo();
  }
  catch(...) {
  }  

  return 0;
}

Of course, the debugger would not stop when having the first-exception to handle it, because foo_exception is not in its list. You can however, change than by adding foo_exception to the list from the Exceptions dialog (as shown below) and check it for breaking on first-chance.

Running again would stop the debugger when foo_exception is thrown.

Hits for this post: 12283 .

When I delivered the LINQ presentation at the RONUA meeting in April, I was asked how does LINQ perform on big data sets. To answer that I decided to test LINQ to XML against a 100+MB file. I decided to extract three different sets of data from this XML file:

  • 1 set representing about 0.5MB of the XML file,
  • 1 set representing about 10MB of the XML file, and
  • 1 set representing about 80MB of the XML file

Of course, I designed some data structures to map on the data from the XML file and run three queries against this file that would project instances of those data structures. The result was that all the three (different) queries took about same time to execute and generate my internal objects. Each time the entire file was re-parsed. The time for each query was about 3.5 seconds. Thus, I can draw two conclusions:

  • LINQ is very performant: it took less than 12 seconds to extract 90% of the data from a 100MB file; the performance is several times greater than the one I get in C++ for parsing the file; not to mention that the code is more than several times simpler;
  • there was’t too much difference between extracting 0.5MB or 100 times that;

I am quite confident that LINQ to SQL is as performant as LINQ to XML. If I’ll find a really big data base, I will query it.

Hits for this post: 31075 .

Being active in several forums for developers (CodeGuru, MSDN, Ronua) I see quite often people saying “I want to write games; what do I have to learn?” Turns out that the kind of games they want to write vary from chess to card games, from shooters to stragety games over the internet. But they can’t even write a “hello world” program. This post is dedicated to all the kids that after playing countless hours of Counter Strike, Unreal Tournament, Warcraft or Need For Speed decided that it would be really cool to write a games themselves.

Now, I’m not saying you could not write one, of course you could; but not something like FIFA World Cup. You could write a Gorillas, or Tic Tac Toe or even a simple five-in-a-row, but before even doing that you have to learn the concepts of programming. You have to pick a language (perhaps C++, C# or Java) and start learning what objects are, what are variables, arrays, strings, what is a virtual function, how do you handle memory, and many, many others. Then you have to start learning Windows programming concepts, and how you deal with windows, dialogs, controls, and many more. Only after than you could hope thinking about writing games.

As for games such as Unreal Tournament or Starcraft, take a look at the credits; you’ll see that tens, perhaps hundreds of people were involved in the development of such games. Designers, developers, testers, art directors, and many more. They have put thousands of hours of work each. Large teams take 1-2 years to write a game such as Need For Speed, even when a platform is already in place, from a previous version. It’s simply not something that one or two young unexperienced people can do.

But that doesn’t mean one day you could not be a part of such a team, working on the next greatest first person shooter. Before that, however, you have a long way ahead. So start learning programming first, and then think about games.

Hits for this post: 5963 .