Last active
February 28, 2019 01:55
-
-
Save mikesart/29dccf1c67e529b13d75b3bd26b65671 to your computer and use it in GitHub Desktop.
Linux read times
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// g++ -O3 foobar.cpp -g -o foobar | |
// | |
// Create large input file | |
// dd if=/dev/zero of=/mnt/dev/infile.txt count=180 bs=1M | |
// | |
// Run test app | |
// foobar /mnt/dev/infile.txt /mnt/dev/outfile.txt | |
#include <errno.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <time.h> | |
#include <sys/file.h> | |
#include <sys/mman.h> | |
// https://github.com/nothings/stb/blob/master/stb.h | |
#define STB_DEFINE | |
#include "stb.h" | |
#ifndef MIN | |
#define MIN(a,b) (((a) < (b)) ? (a) : (b)) | |
#endif | |
double get_time() | |
{ | |
struct timespec ts; | |
clock_gettime( CLOCK_MONOTONIC, &ts ); | |
return ( double )ts.tv_sec * 1000.0 + ( double )ts.tv_nsec / 1000000.0; | |
} | |
int main( int argc, char *argv[] ) | |
{ | |
if ( argc < 3 ) | |
{ | |
printf( "USAGE: %s infile outfile\n", argv[ 0 ] ); | |
return 0; | |
} | |
bool do_sha = false; | |
bool use_mmap = false; | |
bool do_truncate = true; | |
const char *infilename = argv[ 1 ]; | |
const char *outfilename = argv[ 2 ]; | |
for ( int i = 3; i < argc; i++ ) | |
{ | |
if ( !strcmp( argv[ i ], "--no_truncate" ) ) | |
do_truncate = false; | |
else if ( !strcmp( argv[ i ], "--use_mmap" ) ) | |
use_mmap = true; | |
else if ( !strcmp( argv[ i ], "--do_sha" ) ) | |
do_sha = true; | |
} | |
printf( "use_mmap: %d\n", use_mmap ); | |
printf( "do_truncate: %d\n", do_truncate ); | |
printf( "do_sha: %d\n", do_sha ); | |
double start_time = get_time(); | |
// open in file | |
int fd; | |
{ | |
double t0 = get_time(); | |
fd = open( infilename, O_RDONLY | O_CLOEXEC ); | |
if ( fd == -1 ) | |
{ | |
printf( "ERROR: failed to open %s. %d\n", infilename, errno ); | |
return -1; | |
} | |
printf( "open %s: %.2f ms\n", infilename, get_time() - t0 ); | |
} | |
// opens out file | |
int fd2; | |
{ | |
double t0 = get_time(); | |
fd2 = open( outfilename, | |
O_CREAT | O_CLOEXEC | /*O_RDWR*/ O_WRONLY, | |
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ); | |
if ( fd2 == -1 ) | |
{ | |
printf( "ERROR: open %s failed. %d\n", outfilename, errno ); | |
} | |
printf( "open %s: %.2f ms\n", outfilename, get_time() - t0 ); | |
} | |
// ftruncate | |
if ( fd2 >= 0 ) | |
{ | |
int ret = flock( fd2, LOCK_EX | LOCK_NB ); | |
printf( "flock(%d, LOCK_EX | LOCK_NB): %d\n", fd2, ret ); | |
if ( do_truncate ) | |
{ | |
ret = ftruncate( fd2, 0 ); | |
printf( "ftruncate(%d, 0): %d\n", fd2, ret ); | |
} | |
} | |
// stat | |
struct stat fi; | |
{ | |
if ( stat( infilename, &fi ) == -1 ) | |
{ | |
printf( "ERROR: stat %s failed. %d\n", infilename, errno ); | |
return -1; | |
} | |
if ( !use_mmap ) | |
{ | |
// Doesn't appear to help... | |
// readahead( fd, 0, fi.st_size ); | |
} | |
} | |
unsigned char *data; | |
ssize_t size = fi.st_size; | |
if ( use_mmap ) | |
{ | |
data = ( unsigned char * )mmap( 0, size, PROT_READ, MAP_PRIVATE, fd, 0 ); | |
} | |
else | |
{ | |
data = ( unsigned char * )malloc( size ); | |
// read | |
{ | |
double t0 = get_time(); | |
size = read( fd, data, size ); | |
printf( "read: %.2f ms size:%ld\n", get_time() - t0, size ); | |
} | |
} | |
// sha1 | |
if ( do_sha ) | |
{ | |
double t0 = get_time(); | |
char sha1str[ 27 ] = { 0 }; | |
unsigned char sha1[ 20 ] = { 0 }; | |
stb_sha1( sha1, data, size ); | |
stb_sha1_readable( sha1str, sha1 ); | |
printf( "stb_sha1: %.2f ms (%s)\n", get_time() - t0, sha1str ); | |
} | |
// write | |
if ( fd2 >= 0 ) | |
{ | |
#define CHUNK_SIZE ( 64 * 1024 ) | |
double t0 = get_time(); | |
unsigned char *buf = ( unsigned char * )malloc( CHUNK_SIZE ); | |
int chunks = 0; | |
unsigned char *chunk = data; | |
while ( size > 0 ) | |
{ | |
ssize_t chunksize = MIN( size, CHUNK_SIZE ); | |
memcpy( buf, chunk, chunksize ); | |
if ( do_sha ) | |
stb_crc32( buf, chunksize ); | |
ssize_t count = write( fd2, buf, chunksize ); | |
if ( count != chunksize ) | |
{ | |
printf( "ERROR: write %d != %d errno:%d\n", count, chunksize, errno ); | |
break; | |
} | |
chunk += chunksize; | |
size -= chunksize; | |
chunks++; | |
} | |
printf( "write: %.2f ms (64k chunks:%d)\n", get_time() - t0, chunks ); | |
t0 = get_time(); | |
close( fd2 ); | |
printf( "close %s: %.2f ms\n", outfilename, get_time() - t0 ); | |
free( buf ); | |
} | |
if ( use_mmap ) | |
munmap( data, fi.st_size ); | |
else | |
free( data ); | |
printf( "total time: %.2f ms\n", get_time() - start_time ); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment