Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <cstdio> // printf, fread
- #include <chrono> // std::chrono
- #include <fstream> // C++ STD file stream
- #include <memory> // smart pointers
- class ByteReadBase
- {
- public:
- virtual bool open( const char* file ) = 0; // Open file
- virtual void close() = 0; // Close file
- virtual unsigned char get_byte() = 0; // Get next byte
- virtual bool eof() const = 0; // End of file reached
- unsigned reads() const // Get number of read API calls
- {
- return reads_;
- }
- protected:
- virtual unsigned get_size() = 0; // Get file size
- bool file_opened_ = false; // File open flag
- unsigned reads_ = 0;
- };
- class Fread : public ByteReadBase
- {
- public:
- Fread() = default;
- ~Fread()
- {
- if ( file_opened_ )
- {
- close();
- }
- }
- bool open( const char* file ) override
- {
- if ( file_opened_ )
- {
- return false; // File already opened
- }
- fd_ = fopen( file, "rb" ); // Open for reading
- file_opened_ = fd_; // Set flag if file was successfully opened
- total_bytes_ = get_size(); // Save total file size
- return file_opened_;
- }
- void close() override
- {
- if ( file_opened_ )
- {
- fclose( fd_ );
- }
- }
- bool eof() const override
- {
- return total_bytes_ == 0;
- }
- unsigned char get_byte() override
- {
- unsigned char byte;
- fread( &byte, 1, 1, fd_ );
- reads_++;
- total_bytes_ = ( total_bytes_ > 0 ) ? --total_bytes_ : total_bytes_;
- return byte;
- }
- private:
- unsigned get_size() override
- {
- unsigned size = 0;
- if ( file_opened_ )
- {
- unsigned curr = (unsigned)ftell( fd_ ); // Get current position
- fseek( fd_, 0, SEEK_SET );
- size = (unsigned)ftell( fd_ );
- fseek( fd_, 0, SEEK_END );
- size = (unsigned)ftell( fd_ ) - size;
- fseek( fd_, curr, SEEK_SET ); // Get back to recent position
- }
- return size;
- }
- FILE *fd_;
- unsigned total_bytes_ = 0;
- };
- class Fstream : public ByteReadBase
- {
- public:
- Fstream() = default;
- ~Fstream()
- {
- if ( file_opened_ )
- {
- close();
- }
- }
- bool open( const char* file ) override
- {
- if ( file_opened_ )
- {
- return false;
- }
- fs_.unsetf( std::ios_base::skipws );
- fs_.open( file, std::ifstream::binary | std::ifstream::in );
- file_opened_ = fs_.good();
- total_bytes_ = get_size();
- return file_opened_;
- }
- void close() override
- {
- if ( file_opened_ )
- {
- fs_.close();
- }
- }
- bool eof() const override
- {
- return !( total_bytes_ && fs_.good() );
- }
- unsigned char get_byte() override
- {
- if ( total_bytes_ )
- {
- total_bytes_--;
- }
- reads_++;
- return fs_.get();
- }
- private:
- unsigned get_size() override
- {
- unsigned size = 0;
- if ( file_opened_ )
- {
- unsigned curr = (unsigned)fs_.tellg(); // Get current position
- fs_.seekg( 0, std::ios::beg );
- size = (unsigned)fs_.tellg();
- fs_.seekg( 0, std::ios::end );
- size = (unsigned)fs_.tellg() - size;
- fs_.seekg( 0, std::ios::beg ); // Get back to recent position
- }
- return size;
- }
- std::ifstream fs_;
- unsigned total_bytes_ = 0;
- };
- class FreadBuffered : public ByteReadBase
- {
- public:
- FreadBuffered( unsigned buffer_size )
- {
- buf_ = (char*)malloc( buffer_size );
- buffer_size_ = buffer_size;
- }
- ~FreadBuffered()
- {
- if ( file_opened_ )
- {
- close();
- }
- if ( buf_ )
- {
- free( buf_ );
- }
- }
- bool open( const char* file ) override
- {
- if ( file_opened_ )
- {
- return false; // File already opened
- }
- fd_ = fopen( file, "rb" ); // Open for reading
- file_opened_ = fd_; // Set flag if file was successfully opened
- total_bytes_ = get_size(); // Save total file size
- bytes_in_buf_ = 0;
- end_ = buf_ + buffer_size_;
- head_ = buf_;
- tail_ = buf_;
- return file_opened_;
- }
- void close() override
- {
- if ( file_opened_ )
- {
- fclose( fd_ );
- }
- }
- bool eof() const override
- {
- return total_bytes_ == 0;
- }
- unsigned char get_byte() override
- {
- if ( bytes_in_buf_ == 0 )
- {
- fill_buffer();
- }
- if ( bytes_in_buf_ == 0 )
- {
- return '\0';
- }
- unsigned char byte = *tail_; // get byte
- tail_++; // advance
- if ( tail_ == end_ )
- {
- tail_ = head_;
- }
- bytes_in_buf_--;
- if ( total_bytes_ )
- {
- total_bytes_--;
- }
- return byte;
- }
- private:
- unsigned get_size() override
- {
- unsigned size = 0;
- if ( file_opened_ )
- {
- unsigned curr = (unsigned)ftell( fd_ ); // Get current position
- fseek( fd_, 0, SEEK_SET );
- size = (unsigned)ftell( fd_ );
- fseek( fd_, 0, SEEK_END );
- size = (unsigned)ftell( fd_ ) - size;
- fseek( fd_, curr, SEEK_SET ); // Get back to recent position
- }
- return size;
- }
- void fill_buffer()
- {
- unsigned bytes_front = end_ - head_;
- unsigned bytes_behind = head_ - buf_;
- unsigned bytes = fread( head_, 1, bytes_front, fd_ );
- reads_++;
- bytes_in_buf_ += bytes;
- if ( bytes == bytes_front )
- {
- unsigned bytes = fread( head_, 1, bytes_behind, fd_ );
- reads_++;
- head_ = buf_ + bytes;
- bytes_in_buf_ += bytes;
- }
- else
- {
- head_ += bytes;
- }
- }
- FILE *fd_;
- unsigned total_bytes_ = 0;
- unsigned buffer_size_ = 0;
- unsigned bytes_in_buf_ = 0;
- char *buf_ = nullptr;
- char *end_ = nullptr;
- char *head_ = nullptr;
- char *tail_ = nullptr;
- };
- class FstreamBuffered : public ByteReadBase
- {
- public:
- FstreamBuffered( unsigned buffer_size )
- {
- buf_ = (char*)malloc( buffer_size );
- buffer_size_ = buffer_size;
- }
- ~FstreamBuffered()
- {
- if ( file_opened_ )
- {
- close();
- }
- if ( buf_ )
- {
- free( buf_ );
- }
- }
- bool open( const char* file ) override
- {
- if ( file_opened_ )
- {
- return false;
- }
- fs_.unsetf( std::ios_base::skipws );
- fs_.open( file, std::ifstream::binary | std::ifstream::in );
- file_opened_ = fs_.good();
- total_bytes_ = get_size();
- bytes_in_buf_ = 0;
- end_ = buf_ + buffer_size_;
- head_ = buf_;
- tail_ = buf_;
- return file_opened_;
- }
- void close() override
- {
- if ( file_opened_ )
- {
- fs_.close();
- }
- }
- bool eof() const override
- {
- return total_bytes_ == 0;
- }
- unsigned char get_byte() override
- {
- if ( bytes_in_buf_ == 0 )
- {
- fill_buffer();
- }
- if ( bytes_in_buf_ == 0 )
- {
- return '\0';
- }
- unsigned char byte = *tail_; // get byte
- tail_++; // advance
- if ( tail_ == end_ )
- {
- tail_ = head_;
- }
- bytes_in_buf_--;
- if ( total_bytes_ )
- {
- total_bytes_--;
- }
- return byte;
- }
- private:
- unsigned get_size() override
- {
- unsigned size = 0;
- if ( file_opened_ )
- {
- unsigned curr = (unsigned)fs_.tellg(); // Get current position
- fs_.seekg( 0, std::ios::beg );
- size = (unsigned)fs_.tellg();
- fs_.seekg( 0, std::ios::end );
- size = (unsigned)fs_.tellg() - size;
- fs_.seekg( 0, std::ios::beg ); // Get back to recent position
- }
- return size;
- }
- void fill_buffer()
- {
- unsigned bytes_front = end_ - head_;
- unsigned bytes_behind = head_ - buf_;
- fs_.read( head_, bytes_front );
- reads_++;
- unsigned bytes = (unsigned)fs_.gcount();
- bytes_in_buf_ += bytes;
- if ( bytes == bytes_front )
- {
- unsigned bytes = (unsigned)fs_.readsome( head_, bytes_behind );
- reads_++;
- head_ = buf_ + bytes;
- bytes_in_buf_ += bytes;
- }
- else
- {
- head_ += bytes;
- }
- }
- std::ifstream fs_;
- unsigned total_bytes_ = 0;
- unsigned buffer_size_ = 0;
- unsigned bytes_in_buf_ = 0;
- char *buf_ = nullptr;
- char *end_ = nullptr;
- char *head_ = nullptr;
- char *tail_ = nullptr;
- };
- int main( int argc, char** argv )
- {
- if ( argc < 3 )
- {
- printf( "Usage: %s <file name> <buf size>", argv[0] );
- return 1;
- }
- std::unique_ptr<ByteReadBase> f;
- auto run = [&]( ByteReadBase *fs ) {
- unsigned checksum = 0;
- unsigned bytes = 0;
- f.reset( fs );
- if ( f->open( argv[1] ) )
- {
- std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now();
- char byte = f->get_byte();
- while( !f->eof() )
- {
- byte = f->get_byte();
- checksum += byte;
- bytes++;
- }
- std::chrono::high_resolution_clock::time_point end = std::chrono::high_resolution_clock::now();
- printf( "Read %u bytes for %f seconds, called read API %d times, checksum: %X\n", bytes, std::chrono::duration_cast<std::chrono::duration<double>>(end - start).count(), f->reads(), checksum );
- }
- else
- {
- printf( "Failed to open file\n" );
- }
- };
- // printf( "Measuring C API (fread) performance\n" );
- // run( new Fread );
- // printf( "Measuring C++ API (ifstream) performance\n" );
- // run( new Fstream );
- unsigned buf_size = atoi( argv[2] );
- printf( "Measuring buffered C API (fread) performance\n" );
- run( new FreadBuffered( buf_size ) );
- // printf( "Measuring buffered C++ API (ifstream) performance\n" );
- // run( new FstreamBuffered( buf_size ) );
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement