Flash drive write performance tester (C#)

This small C# utility benchmarks the write performance in megabytes per second of a given flash drive.

Flash write performance tester 0.4 screenshot
Temporary files of arbitrary sizes are generated and copied to the drive a number of times, whereafter an average write speed is calculated.

The utility is available compiled for .NET framework 2.0 with source code included:

Download Flash write performance tester 0.4

Note that the utility uses the drive, the program is being executed from, for storage of the generated temporary test files, so reliable results depend on that drive not being the bottleneck (i.e. the read speed of that drive not being slower than the write speed of the drive tested).

Reference benchmark results:

Storage device
Connection
Write speed

A-data My Flash 2GB
USB key drive
2,6MB/sec

Sandisk Ultra II SD 2GB
USB card reader Hama 35 in 1
4,0MB/sec

Sandisk Extreme III CF 2GB
USB card reader Hama 35 in 1
6,2MB/sec

Buffalo 1GB
USB key drive
8,5MB/sec

Sandisk Ultra II SD 2GB
USB card reader Sandisk Extreme
9,5MB/sec

Sandisk Extreme III CF 2GB
USB card reader Sandisk Extreme
16,1MB/sec

Kingston DataTraveler ReadyFlash
USB key drive
18,1MB/sec


The performance of flash memory cards seems to be highly dependant on the card reader used. As seen in the above results, the same memory cards are more than twice as fast on the Sandisk reader than on the Hama reader. The fastest USB memory key in this test is more than six times faster than the slowest, even though they cost practically the same.

The standard disclaimer: The program is provided 'as is' without warranty of any kind. I have done my best to incorporate graceful exception handling and to test the code in different scenarios, so it shouldn't be able to do anything bad. The source code for the program is listed below.

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Text;
using System.IO;
using System.Threading;
using System.Reflection;

[assembly: AssemblyTitle("Flash write performance tester 0.4")]
[assembly: AssemblyDescription("A small C# utility benchmarks the write performance in megabytes per second of a given flash drive")]
[assembly: AssemblyCompany("www.808.dk")]
[assembly: AssemblyProduct("FlashTester")]
[assembly: AssemblyCopyright("Creative Commons Attribution (CC BY 3.0) http://creativecommons.org/licenses/by/3.0/ Reference source http://www.808.dk/?code-csharp-driveperformance")]
[assembly: AssemblyVersion("0.4.0.0")]
[assembly: CLSCompliant(true)]

public class FlashPerformanceForm : Form
{
  Label driveLabel = new Label();
  Label fileSizeLabel = new Label();
  Label loopsLabel = new Label();
  Button benchmarkButton = new Button();
  ComboBox driveLetter = new ComboBox();
  ComboBox fileSize = new ComboBox();
  ComboBox loops = new ComboBox();
  TextBox resultArea = new TextBox();
  string testDriveLetter;
  int testFileSize;
  int testIterations;

  public FlashPerformanceForm()
  {
    this.Text = "Flash write performance tester 0.4";
    this.Size = new Size(400,350);
    driveLabel.Location = new Point(5, 8);
    driveLabel.Text = "Device drive letter";
    driveLabel.Size = new Size (95, 20);
    driveLetter.Location = new Point(103, 5);
    driveLetter.Size = new Size(33, 15);
    driveLetter.Items.AddRange(GetRemovableDriveLetters());
    if (GetRemovableDriveLetters().Length > 0)
    {
      driveLetter.SelectedIndex = 0;
    }
    fileSizeLabel.Location = new Point(141, 8);
    fileSizeLabel.Text = "File size";
    fileSizeLabel.Size = new Size(50, 20);
    fileSize.Location = new Point(193, 5);
    fileSize.Size = new Size(49, 15);
    fileSize.Items.AddRange(new object[]
      {"100",
       "200",
       "400",
       "800",
       "1000",
       "2000"});
    fileSize.SelectedIndex = 1;
    loopsLabel.Location = new Point(248, 8);
    loopsLabel.Text = "Loops";
    loopsLabel.Size = new Size(36, 20);
    loops.Location = new Point(284, 5);
    loops.Size = new Size(37, 15);
    loops.Items.AddRange(new object[]
      {"1",
       "2",
       "3",
       "4",
       "5",
       "10",
       "20",
       "40"});
    loops.SelectedIndex = 4;
    benchmarkButton.Location = new Point(329, 5);
    benchmarkButton.Size = new Size(50, 20);
    benchmarkButton.Text = "Start";
    resultArea.Location = new Point(5, 30);
    resultArea.Size = new Size(375,278);
    resultArea.ReadOnly = true;
    resultArea.Multiline = true;
    resultArea.ScrollBars = ScrollBars.Vertical;
    resultArea.WordWrap = false;
    resultArea.Font = new Font("Courier New", 8);
    this.Controls.Add(driveLabel);
    this.Controls.Add(driveLetter);
    this.Controls.Add(fileSizeLabel);
    this.Controls.Add(fileSize);
    this.Controls.Add(loopsLabel);
    this.Controls.Add(loops);
    this.Controls.Add(benchmarkButton);
    this.Controls.Add(resultArea);
    benchmarkButton.Click += new EventHandler(benchmarkButton_Click);
  }
  private void benchmarkButton_Click(object sender, EventArgs e)
  {
    testDriveLetter = driveLetter.Text + ":";
    testFileSize = Convert.ToInt32(fileSize.Text) * 1000000;
    testIterations = Convert.ToInt32(loops.Text);
    Thread testThread = new Thread(new ThreadStart(TestPerf));
    testThread.Start();
  }

  private void TestPerf()
  {
    try
    {
      int appendIterations = testFileSize / 100000;
      resultArea.AppendText(
        "Running a " + testFileSize/1000000 + "MB file write on drive "
        + testDriveLetter + " " + testIterations + " times...\r\n");
      double totalPerf = 0;
      DateTime startTime;
      DateTime stopTime;
      string randomText = RandomString(100000);
      for(int j=1; j<=testIterations; j++)
      {
        Application.DoEvents();
        if (File.Exists(System.Environment.CurrentDirectory + "\\" +
          j + "test.tmp"))
        {
          File.Delete(System.Environment.CurrentDirectory + "\\" +
            j + "test.tmp");
        }
        StreamWriter sWriter = new StreamWriter(
          System.Environment.CurrentDirectory + "\\" + j +
          "test.tmp", true);
        for(int i=1; i<=appendIterations; i++)
        {
          sWriter.Write(randomText);
        }
        sWriter.Close();
        startTime = DateTime.Now;
        File.Copy(System.Environment.CurrentDirectory + "\\" + j +
          "test.tmp", testDriveLetter + "\\" + j + "test.tmp");
        stopTime = DateTime.Now;
        File.Delete(System.Environment.CurrentDirectory + "\\" + j +
          "test.tmp");
        File.Delete(testDriveLetter + "\\" + j + "test.tmp");
        TimeSpan interval = stopTime - startTime;
        resultArea.AppendText("Iteration " + j + ":   " +
          Math.Round((testFileSize/1000)/interval.TotalMilliseconds, 2) +
          " MB/sec\r\n");
        resultArea.Invalidate();
        totalPerf += (testFileSize/1000)/interval.TotalMilliseconds;
      }
      resultArea.AppendText("------------------------------\r\n");
      resultArea.AppendText("Average:       " +
        Math.Round(totalPerf/testIterations, 2) + " MB/sec\r\n");
      resultArea.AppendText("------------------------------\r\n");
      resultArea.Invalidate();
    }
    catch (Exception e)
    {
      resultArea.AppendText("An error occured: " + e.Message + "\r\n");
    }
  }

  private string RandomString(int size)
  {
    StringBuilder builder = new StringBuilder();
    Random random = new Random();
    char ch;
    for (int i = 0; i < size; i++)
    {
      ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65)));                
      builder.Append(ch);
    }
    return builder.ToString();
  }

  private string[] GetRemovableDriveLetters()
  {
    System.Collections.ArrayList RemovableDriveLetters = new System.Collections.ArrayList();
    DriveInfo[] allDrives = DriveInfo.GetDrives();
    foreach (DriveInfo d in allDrives)
    {
      if (d.DriveType == DriveType.Removable)
      {
        RemovableDriveLetters.Add(d.Name.Substring(0, 1));
      }
    }
    return RemovableDriveLetters.ToArray(typeof(string)) as string[];
  }

  static void Main()
  {
    Application.Run(new FlashPerformanceForm());
  }
}

Use the following command (from a folder containing the source file) to compile the program:

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\csc.exe /target:winexe /out:FlashTester.exe FlashTester.cs

Note: The path to the .NET framework compiler may not be exactly like above on all systems.

Page last updated 2008-09-18 22:11. Some rights reserved (CC by 3.0)