Skip to content

Instantly share code, notes, and snippets.

@GuilhermeRossato
Last active April 23, 2019 22:16
Show Gist options
  • Save GuilhermeRossato/1f1f670086c415a6523906739535b90d to your computer and use it in GitHub Desktop.
Save GuilhermeRossato/1f1f670086c415a6523906739535b90d to your computer and use it in GitHub Desktop.
Simple C Disk Writing Benchmark for Windows
/*
* Description:
* C program for windowsto write to a file in 4096-byte blocks to a new file until it reaches 16777216 bytes (16MB)
*
* Supported OS:
* Windows and Linux
*
* Recomendations:
* Disable linux disk cache:
* sudo /sbin/sysctl -w vm.drop_caches=3
*
* Expected output:
*
* -- TESTING WRITE SPEED --
* Cache
* Test: Generating 67.11 MB in blocks of 8 bytes
* Result: 780ms
* CPU
* Test: Generating 67.11 MB in blocks of 8 bytes
* Result: 796ms
* Disk
* Test: Generating 67.11 MB in blocks of 8 bytes
* Result: 1388ms
* Final Result: 592ms caused by disk
*
* New file has been created with 67.11 MBytes
* The write speed is 113.36 MB/s
*
* -- TESTING READ SPEED --
* Disk
* Result: 156ms
* File has been read with 67.11 MBytes
* The read speed is 430.19 MB/s
*
* Notes:
*
* Cache test is done so that the instruction processor cache fills up before testing.
* CPU test is after the processor and memory cache is full, so we know how much is CPU overhead.
* Disk test is the actual disk test PLUS the unavoidable CPU overhead.
* The CPU overhead is discarted from the disk test and then used to calculate disk write speed.
* File reading has embedded cache and it's hidden.
*
* Compiled with TCC (Tiny C Compiler) - Can be compiled with GCC too, but with TCC is reliable (and faster!).
*
* @tcc test-disk-speed.c -o main.exe && main.exe || echo Something went wrong
*
* No usage restriction, free to use, no warranties. I'm just using to test SSDs.
*/
#include <stdio.h>
#include <stdlib.h>
#ifdef _WIN32
#include <windows.h>
#else
#include <time.h>
#endif
int g_seed = 15262;
#define FILE_NAME "testing-hard-drive.txt"
int fastrand() {
g_seed = (214013 * g_seed + 2531011);
return (g_seed >> 16) & 0x7FFF;
}
void print_bytes(unsigned int param) {
long double bytes = param;
if (bytes < 10000) {
printf("%.2Lf B", bytes);
} else if (bytes < 1000000) {
bytes = bytes * 0.001;
printf("%.2Lf kB", bytes);
} else if (bytes < 1000000000) {
bytes = bytes * 0.000001;
printf("%.2Lf MB", bytes);
} else {
bytes = bytes * 0.000000001;
printf("%.2Lf GB", bytes);
}
}
unsigned long timestamp() {
#ifdef _WIN32
DWORD ms = GetTickCount();
#else
unsigned long ms = time(NULL);
#endif
return (unsigned long)ms;
}
char buffer[16384];
char mini_buffer[16];
unsigned long test_write_sequential_blocks(unsigned long * start, unsigned long * end, int has_file) {
unsigned long i, j, byte_count;
unsigned long block_size = 8192;
unsigned long block_count = 8192;
printf("Test: Generating ");
print_bytes(block_size*block_count);
printf(" in blocks of %lu bytes\n", block_size);
*start = timestamp();
FILE *fp;
if (has_file) {
fp = fopen(FILE_NAME, "w");
if (!fp) {
return 1;
}
}
byte_count = 0;
unsigned long bytes_so_far;
for (i = 0; i < block_count; i++) {
bytes_so_far = 0;
for (j = 0; j < block_size; j++) {
//snprintf(mini_buffer, 10, "%d", fastrand());
//buffer[bytes_so_far] = mini_buffer[0];
buffer[bytes_so_far] = 48+(j%10);
bytes_so_far++;
}
buffer[bytes_so_far] = '\0';
if (has_file) {
fputs(buffer, fp);
}
byte_count = byte_count + bytes_so_far;
}
//printf("Written %u bytes\n", byte_count);
if (has_file) {
fclose(fp);
}
*end = timestamp();
return byte_count;
}
void print_speed_in_bytes(double bytes) {
print_bytes(bytes);
printf("/s");
}
unsigned long test_read_file_bytes(unsigned long * start, unsigned long * end, unsigned int test_repeat_count) {
double accumulator = 0;
int c;
unsigned long byte_count;
unsigned long length;
unsigned int i = 10;
if (test_repeat_count == 0)
{
byte_count = 0;
*start = timestamp();
}
for (i = 0; i < test_repeat_count+1; i++)
{
FILE *fp;
fp = fopen(FILE_NAME, "r");
if (!fp)
{
return 1;
}
length = fread(buffer, 0, 8192, fp);
// try to fix starting file wrongly
if (length == 0) {
length = fread(buffer, 1, 8192, fp);
}
while (length == 8192)
{
accumulator += (c - 48);
byte_count += length;
if (byte_count/16 % 2 == 1) {
printf("%c", buffer[15]);
}
length = fread(buffer, 1, 8192, fp);
}
printf("\n");
// both never happens, this is only to avoid optimization
if (accumulator == '0' || accumulator == 1 * 2) {
if (length > 1) {
printf("\n");
} else {
printf("\n");
}
}
fclose(fp);
// real startup
if (i == 0 && test_repeat_count != 0) {
byte_count = 0;
*start = timestamp();
}
}
*end = timestamp();
return byte_count;
}
int test_write() {
unsigned long start, end, dif0, dif1, dif2, dif_out, byte_count;
printf("\n -- TESTING WRITE SPEED -- \n");
printf("Cache\n\t");
test_write_sequential_blocks(&start, &end, 0);
dif0 = end - start;
printf("\tResult:\t%lums\n", dif0);
printf("CPU\n\t");
test_write_sequential_blocks(&start, &end, 0);
dif1 = end - start;
printf("\tResult:\t%lums\n", dif1);
printf("Disk\n\t");
byte_count = test_write_sequential_blocks(&start, &end, 1);
dif2 = end - start;
printf("\tResult:\t%lums\n", dif2);
dif_out = (dif2 > dif1)?dif2-dif1:dif1-dif2;
printf("Final Result: %lums caused by %s\n", dif_out, (dif2>dif1)?"disk\n":"cpu\n");
printf("New file has been created with ");
print_bytes(byte_count);
printf("ytes\n");
if (dif_out == 0) {
dif_out = 100000000;
}
printf("The write speed is ");
double byte_per_second = (float) byte_count / (1.0 * dif_out / 1000.0);
print_speed_in_bytes(byte_per_second);
printf("\n");
return 0;
}
int test_read() {
unsigned long start, end, dif1, dif_out, byte_count;
printf("\n -- TESTING READ SPEED -- \n");
printf("Disk\n\t");
byte_count = test_read_file_bytes(&start, &end, 1);
dif1 = end - start;
printf("\tResult:\t%lums\n", dif1);
dif_out = dif1;
printf("File has been read with ");
print_bytes(byte_count);
printf("ytes\n");
printf("The read speed is ");
if (dif_out == 0) {
dif_out = 100000000;
}
double byte_per_second = (float)byte_count / (1.0 * dif_out / 1000.0);
print_speed_in_bytes(byte_per_second);
printf("\n");
return 0;
}
int main()
{
test_write();
test_read();
return 0;
}
(
Type: HD
Size: 1 TB
Model: ST1000DM003-1CH162 ATA Device
SectorSize: 512
)
-- TESTING WRITE SPEED --
Cache
Test: Generating 67.11 MB in blocks of 8192 bytes
Result: 327ms
CPU
Test: Generating 67.11 MB in blocks of 8192 bytes
Result: 312ms
Disk
Test: Generating 67.11 MB in blocks of 8192 bytes
Result: 1077ms
Final Result: 765ms caused by disk
New file has been created with 67.11 MBytes
The write speed is 87.72 MB/s
-- TESTING READ SPEED --
Disk
Result: 156ms
File has been read with 67.11 MBytes
The read speed is 430.19 MB/s
(
Type: SSD
Size: 240 GB
Model: Kingston 240 GB
)
-- TESTING WRITE SPEED --
Cache
Test: Generating 67.11 MB in blocks of 8 bytes
Result: 780ms
CPU
Test: Generating 67.11 MB in blocks of 8 bytes
Result: 796ms
Disk
Test: Generating 67.11 MB in blocks of 8 bytes
Result: 1388ms
Final Result: 592ms caused by disk
New file has been created with 67.11 MBytes
The write speed is 113.36 MB/s
(
Type: USB
Size: 16 GB
Model: SanDisk Cruzer Fit CZ33 16GB
)
-- TESTING WRITE SPEED --
Cache
Test: Generating 67.11 MB in blocks of 8192 bytes
Result: 500ms
CPU
Test: Generating 67.11 MB in blocks of 8192 bytes
Result: 562ms
Disk
Test: Generating 67.11 MB in blocks of 8192 bytes
Result: 206234ms
Final Result: 205672ms caused by disk
New file has been created with 67.11 MBytes
The write speed is 326.29 kB/s
-- TESTING READ SPEED --
Disk
Result: 375ms
File has been read with 67.11 MBytes
The read speed is 178.96 MB/s
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment