Created
August 1, 2013 20:30
-
-
Save harshavardhana/6134985 to your computer and use it in GitHub Desktop.
./test_mmap.static 1>nostrace.rhel63.static.log 2>&1 &
This file contains hidden or 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 --std=c++0x -o test_mmap test_mmap.cpp | |
*/ | |
#include <vector> | |
#include <sys/mman.h> | |
#include <sys/types.h> | |
#include <sys/stat.h> | |
#include <fcntl.h> | |
#include <stdio.h> | |
#include <errno.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include <string.h> | |
#include <stdint.h> | |
#include <time.h> | |
#include <cstdlib> | |
#include <ctime> | |
static const size_t MBYTES = 1048576; | |
static const size_t SEG_SIZE = 4 * MBYTES; | |
static const size_t STEP_SIZE = SEG_SIZE / 2048; | |
static inline uint64_t | |
get_clock_ticks(){ | |
register uint32_t low, high; | |
asm volatile("rdtscp" : "=a" (low), "=d" (high): : "%ecx"); | |
return ( ( (uint64_t)high ) << 32 ) | low; | |
} | |
static double | |
get_cpu_freq_in_hz() | |
{ | |
char buf[1024]; | |
double clock_in_mhz = 0; | |
FILE* f = fopen( "/proc/cpuinfo", "r" ); | |
while ( fgets( buf, sizeof(buf), f ) != 0 ) { | |
if ( sscanf( buf, "cpu MHz : %lf", &clock_in_mhz ) == 1 ) { | |
// printf( "Found clock : %.4f\n", clock_in_mhz ); | |
break; | |
} | |
} | |
fclose( f ); | |
return clock_in_mhz * 1000000; | |
} | |
static inline double | |
calc_interval_in_secs( uint64_t start, uint64_t finish ) | |
{ | |
static double freq_in_hz = get_cpu_freq_in_hz(); | |
return (finish - start) / freq_in_hz; | |
} | |
static inline uint64_t | |
convert_usecs_to_ticks( double usecs ) { | |
return usecs / 1000000.0 * get_cpu_freq_in_hz(); | |
} | |
class Stopwatch { | |
public: | |
static uint64_t get_default_report_threshold_in_ticks() { /* in ticks */ | |
static uint64_t report_threshold_in_ticks_ = convert_usecs_to_ticks( 500000.0 ); | |
return report_threshold_in_ticks_; | |
} | |
Stopwatch( const char* text ) | |
: text_( text ), start_( get_clock_ticks() ) | |
, report_threshold_in_ticks_( get_default_report_threshold_in_ticks() ) | |
{ | |
++indent_level_; | |
} | |
Stopwatch( const char* text, uint64_t report_threshold_in_usecs ) | |
: text_( text ), start_( get_clock_ticks() ) | |
, report_threshold_in_ticks_( convert_usecs_to_ticks( report_threshold_in_usecs ) ) | |
{ | |
++indent_level_; | |
} | |
~Stopwatch() | |
{ | |
uint64_t finish = get_clock_ticks(); | |
uint64_t dur = finish - this->start_; | |
--indent_level_; | |
if ( dur >= this->report_threshold_in_ticks_ ) { | |
double dur_in_secs = calc_interval_in_secs( this->start_, finish ); | |
printf( "%.*s%s / took %.1f usecs, report_threshold_in_usecs in usecs=%llu\n", indent_level_ * 2, "", this->text_, dur_in_secs * 1000000.0, (unsigned long long)( report_threshold_in_ticks_ / ( get_cpu_freq_in_hz() ) * 1000000 ) ); fflush(stdout); | |
} | |
} | |
private: | |
const char* text_; | |
uint64_t start_; | |
uint64_t report_threshold_in_ticks_; | |
static int indent_level_; | |
}; | |
int Stopwatch::indent_level_ = 0; | |
class Test_File { | |
public: | |
Test_File() | |
: file_name_( 0 ), fd_( -1 ), offset_( 0 ), seg_size_( SEG_SIZE ), step_size_( SEG_SIZE/8 ), segs_() | |
{ | |
} | |
void open_file_name( const char* file_name ) | |
{ | |
this->file_name_ = strdup( file_name ); | |
this->fd_ = open( this->file_name_, O_RDWR | O_CREAT, 0777 ); | |
if ( this->fd_ < 0 ) { | |
fprintf( stderr, "Error calling open(): %d (%s), file_name=%s\n", errno, strerror(errno), this->file_name_ ); | |
exit( errno ); | |
} | |
} | |
void read_out_of_band(){ | |
int random = 0; | |
random = std::rand() % (segs_.size()); | |
memcpy(&read_char_[0], segs_[random], 32); | |
if(random > 0) memcpy(&read_char_[0], segs_[random-1], 32); | |
} | |
void step() { | |
size_t offset = this->offset_; | |
this->offset_ += this->step_size_; | |
if ( ( offset % this->seg_size_ ) == 0 ) { | |
{ | |
Stopwatch s_lseek( "lseek" ); | |
lseek( this->fd_, offset + this->seg_size_ - 1, SEEK_SET ); | |
} | |
{ | |
Stopwatch s_write( "write 1 byte at end of seg" ); | |
write( this->fd_, "", 1 ); | |
} | |
char* p = 0; | |
int prot = PROT_READ | PROT_WRITE; | |
int flags = MAP_SHARED; | |
{ | |
Stopwatch s_mmap( "mmap 1 seg" ); | |
p = (char*) mmap( 0, this->seg_size_, prot, flags, this->fd_, offset ); | |
} | |
if ( p == MAP_FAILED ) { | |
fprintf( stderr, "Error calling mmap(): offset=%llu, %d (%s)\n", (unsigned long long)offset, errno, strerror(errno) ); | |
exit( errno ); | |
} | |
this->segs_.push_back( p ); | |
size_t seg_num = offset / SEG_SIZE; | |
if ( false && seg_num >= 100 ) { | |
Stopwatch s_madvise( "madvise MADV_DONTNEED", 500 ); | |
char* q = this->segs_[ seg_num - 100 ]; | |
int r = madvise( q, SEG_SIZE, MADV_DONTNEED ); | |
if ( r == - 1 ) { | |
fprintf( stderr, "Error calling madvise(): offset=%llu, %d (%s)\n", | |
(unsigned long long)offset, errno, strerror(errno) ); | |
exit( errno ); | |
} | |
} | |
} | |
{ | |
Stopwatch s_memset( "memset 1 seg", 1000 ); | |
char* p = this->segs_[ this->segs_.size() - 1 ]; | |
memset( p + offset, '\1', this->step_size_ ); | |
} | |
} | |
~Test_File() { | |
close( this->fd_ ); | |
free( (char*)file_name_ ); | |
} | |
private: | |
const char* file_name_; | |
int fd_; | |
int fd_rd_; | |
size_t offset_; | |
size_t seg_size_; | |
size_t step_size_; | |
char read_char_[32]; | |
std::vector<char*> segs_; | |
}; | |
int | |
main( int argc, const char* argv[] ) | |
{ | |
srand(time(0)); | |
char outdir[256]; | |
Test_File test_files[100]; | |
size_t max = 16 * 1024 * MBYTES; | |
size_t num_files = 50; | |
if(argc < 2) strcpy(outdir, "."); | |
else strcpy(outdir, argv[1]); | |
// Workaround for not picking up /etc/localtime automatically | |
setenv( "TZ", ":/etc/localtime", 0 ); | |
for ( size_t k=0; k < num_files; ++k ) { | |
char file_name[100]; | |
snprintf( file_name, sizeof(file_name), "%s/TEST_%d_%llu", outdir, getpid(), (unsigned long long)k ); | |
printf( "file_name=%s\n", file_name ); | |
test_files[k].open_file_name( file_name ); | |
} | |
time_t t; | |
time( &t ); | |
unsigned int seed = t; | |
srandom( seed ); | |
for ( size_t o=0; o < max; o += STEP_SIZE ) { | |
if ( o % (1 * STEP_SIZE) == 0 ) { | |
long v = (rand()%1000) * 2000;//( random() + 0.0 ) / RAND_MAX * 200000; | |
usleep( v ); | |
time_t t; | |
struct tm tm; | |
char date_time_buf[200]; | |
time( &t ); | |
localtime_r( &t, &tm ); | |
strftime( date_time_buf, sizeof(date_time_buf), "%T", &tm ); | |
//printf( "o=%zu, %s sleep = %llu\n", o, date_time_buf, v ); | |
} | |
for ( size_t k=0; k < num_files; ++k ) { | |
test_files[k].step(); | |
test_files[k].read_out_of_band(); | |
} | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment