views:

332

answers:

2

This is a strange one... In a windows forms app (VB.NET/VS 2005) I have the need to occasionally check if the application DVD is inserted.
In my production machine (and in the majority of our clients) this code takes less than an second to execute. But in some machines, it takes about 8 to 10 seconds. I couldn't find any common ground on those few pcs in which it was slower (different OS, different RAM,different processors, more drives, less drives, etc).
It happens on about 4% of our test machines (and a few of our friends machines, by now:) )
Since this funcion it is only called once, I can live with it. But the strange thing, and we stumbled upon this on pure luck, is that if a VMWare Virtual Machine is running, the code (running in the host OS ) will take the expected less than a second!!!
Has anyone ever encountered anything similar to this? Can anyone at least offer some explanation for this?

i_DrivesArray = GetLogicalDrives()
    i_DrivesCount = i_DrivesArray.Length


    For i_DriveNumber = 0 To i_DrivesCount - 1
        i_DriveInformation = New DriveInfo(i_DrivesArray(i_DriveNumber))

        If (i_DriveInformation.DriveType = i_DriveTargetType And i_DriveInformation.IsReady = True) Then

            If File.Exists(i_DriveInformation.Name.ToString & ci_CDIdentifiers(i_Counter).ToString) = True Then
                ci_IsCDInserted = True
                ci_PathCD = i_DriveInformation.Name.ToString
                Exit For
            End If

        End If
    Next
A: 
  • Have you considered network mapped drives? They can be very slow to respond for certain things.

  • Have you tried getting the list of drives, and then checking each drive in parallel rather than in serial? Cancel any pending requests when a result is found and return true. Since the real dvd drive will probably return right away, this would prevent any slow volumes from dragging the rest of the processes.

Joel Coehoorn
1)No network mapped drives on any of the tested machines.2)English is not my first language so excuse me if I got this wrong but the function exits after finding the right drive.
Antonio Louro
What if an earlier drive tested before the desired drive takes 8 to 10 seconds to finish? Your actual drive will have to wait for that drive to finish before it's checked. Doing this in parallel will allow you to check it right away.
Joel Coehoorn
I am sorry if I seem dumb but how would you do that? Are you talking about using threads?
Antonio Louro
Yes- check each drive in it's own thread. That way one bad-behaving volume can't hold up checking the rest of them, even if that bad volume is the first one in the list.
Joel Coehoorn
Thanks for the tip. It seems like something of a overkill for such a small feature but you may have a point as to being the safest way. It still does not answer the "why" the problem occurs, though:)
Antonio Louro
+1  A: 

Where's the cost in this code? Profiling would really help on a bad machine

I'd imagine the cost is somewhere in those DriveInfo calls - looking in reflector at the code behind DriveInfo:

.cctor seems pretty innocuous - just validates letter constraints.

.GetDriveType calls straight down into the equivalent Win32 API. Suspect this will try access the directory root since one of it's potential return results is DRIVE_NO_ROOT_DIR.

http://msdn.microsoft.com/en-us/library/aa364939.aspx

.IsReady - that appears to attempt "open" the drive root directory populate the FILE_ATTRIBUTE structure. Again that looks similar to GetDriveType - possibly expensive.

Both the latter API's have the potential to try and touch the drive filesystem. From there on down you're dependent on the behaviour of the device and it's drivers for the volume as to what "unmounted", "ready, "not ready" etc. means. e.g. trying to spin up a disk.

Since the delays are in the order of seconds I equally suspect that enumeration of the slow floppy/dvd/cd volumes is what takes the most time compared to other media types. Floppies especially used to have very long timeouts.

stephbu