I was working with a customer today and discovered that their application was calling into one of my drivers repeatedly to read 4 bytes at a time, each time reading the next 4 bytes of data. The driver reads a minimum of 4 bytes, or they probably would have read less, but the driver is capable of reading large quantities of data on each call from the application.
This really isn’t all that uncommon though and it actually will read the data correctly. The problem is that each call to the driver has some overhead. So if the calling into the driver takes a few microseconds it isn’t bad. But if the application multiplies that overhead by hundreds or thousands of calls, it starts to add up and reduce application and even system performance.
To demonstrates cost of overhead, I wrote the following code:
void TestDriverShell()
{
                HANDLE hDS;
                DWORD Count;
                DWORD StartTime;
                DWORD EndTime;
 
                hDS = CreateFile( TEXT("XXX1:"), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
 
                if( hDS != INVALID_HANDLE_VALUE )
                {
                                StartTime = GetTickCount();
                                ReadFile( hDS, &Count, 4, &Count, 0 );
                                EndTime = GetTickCount();
                                RETAILMSG( 1, (TEXT("ReadFile time: %d\n"), EndTime - StartTime ));
                               
                                StartTime = GetTickCount();
                                for( Count = 0; Count < 512; Count++ )
                                                ReadFile( hDS, &Count, 4, &EndTime, 0 );
                                EndTime = GetTickCount();
                                RETAILMSG( 1, (TEXT("ReadFile time: %d\n"), EndTime - StartTime ));
                }
}
This code calls ReadFile() on the DriverShell example driver that I included in another post Windows CE: A Stream Interface Driver Shell. DriverShell doesn’t do anything but return when ReadFile() is called. This means that the time it takes to call ReadFile() is all overhead.
On the system that I tested this on, the first call reports that the time to call ReadFile() is 0 milliseconds, but the time to call it 512 times is 26 milliseconds. What is 26 milliseconds? Really not much, but imagine that a real driver spends more time actually reading data from hardware. That could start to really add up, and in cases like reading from a serial port, the application could start to lose data.
Calling WriteFile with small amounts of data can have the same effect.
Copyright © 2009 – Bruce Eitman
All Rights Reserved