Advertisement
Guest User

Untitled

a guest
Apr 23rd, 2019
86
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.34 KB | None | 0 0
  1. #include <cstdio> // printf, fread
  2. #include <chrono> // std::chrono
  3. #include <fstream> // C++ STD file stream
  4. #include <memory> // smart pointers
  5.  
  6. class ByteReadBase
  7. {
  8. public:
  9. virtual bool open( const char* file ) = 0; // Open file
  10. virtual void close() = 0; // Close file
  11. virtual unsigned char get_byte() = 0; // Get next byte
  12. virtual bool eof() const = 0; // End of file reached
  13. unsigned reads() const // Get number of read API calls
  14. {
  15. return reads_;
  16. }
  17.  
  18. protected:
  19. virtual unsigned get_size() = 0; // Get file size
  20.  
  21. bool file_opened_ = false; // File open flag
  22. unsigned reads_ = 0;
  23. };
  24.  
  25. class Fread : public ByteReadBase
  26. {
  27. public:
  28. Fread() = default;
  29. ~Fread()
  30. {
  31. if ( file_opened_ )
  32. {
  33. close();
  34. }
  35. }
  36.  
  37. bool open( const char* file ) override
  38. {
  39. if ( file_opened_ )
  40. {
  41. return false; // File already opened
  42. }
  43. fd_ = fopen( file, "rb" ); // Open for reading
  44. file_opened_ = fd_; // Set flag if file was successfully opened
  45. total_bytes_ = get_size(); // Save total file size
  46. return file_opened_;
  47. }
  48.  
  49. void close() override
  50. {
  51. if ( file_opened_ )
  52. {
  53. fclose( fd_ );
  54. }
  55. }
  56.  
  57. bool eof() const override
  58. {
  59. return total_bytes_ == 0;
  60. }
  61.  
  62. unsigned char get_byte() override
  63. {
  64. unsigned char byte;
  65. fread( &byte, 1, 1, fd_ );
  66. reads_++;
  67. total_bytes_ = ( total_bytes_ > 0 ) ? --total_bytes_ : total_bytes_;
  68. return byte;
  69. }
  70.  
  71. private:
  72. unsigned get_size() override
  73. {
  74. unsigned size = 0;
  75. if ( file_opened_ )
  76. {
  77. unsigned curr = (unsigned)ftell( fd_ ); // Get current position
  78. fseek( fd_, 0, SEEK_SET );
  79. size = (unsigned)ftell( fd_ );
  80. fseek( fd_, 0, SEEK_END );
  81. size = (unsigned)ftell( fd_ ) - size;
  82. fseek( fd_, curr, SEEK_SET ); // Get back to recent position
  83. }
  84. return size;
  85. }
  86.  
  87. FILE *fd_;
  88. unsigned total_bytes_ = 0;
  89. };
  90.  
  91. class Fstream : public ByteReadBase
  92. {
  93. public:
  94. Fstream() = default;
  95. ~Fstream()
  96. {
  97. if ( file_opened_ )
  98. {
  99. close();
  100. }
  101. }
  102.  
  103. bool open( const char* file ) override
  104. {
  105. if ( file_opened_ )
  106. {
  107. return false;
  108. }
  109. fs_.unsetf( std::ios_base::skipws );
  110. fs_.open( file, std::ifstream::binary | std::ifstream::in );
  111. file_opened_ = fs_.good();
  112. total_bytes_ = get_size();
  113. return file_opened_;
  114. }
  115.  
  116. void close() override
  117. {
  118. if ( file_opened_ )
  119. {
  120. fs_.close();
  121. }
  122. }
  123.  
  124. bool eof() const override
  125. {
  126. return !( total_bytes_ && fs_.good() );
  127. }
  128.  
  129. unsigned char get_byte() override
  130. {
  131. if ( total_bytes_ )
  132. {
  133. total_bytes_--;
  134. }
  135. reads_++;
  136. return fs_.get();
  137. }
  138.  
  139. private:
  140. unsigned get_size() override
  141. {
  142. unsigned size = 0;
  143. if ( file_opened_ )
  144. {
  145. unsigned curr = (unsigned)fs_.tellg(); // Get current position
  146. fs_.seekg( 0, std::ios::beg );
  147. size = (unsigned)fs_.tellg();
  148. fs_.seekg( 0, std::ios::end );
  149. size = (unsigned)fs_.tellg() - size;
  150. fs_.seekg( 0, std::ios::beg ); // Get back to recent position
  151. }
  152. return size;
  153. }
  154.  
  155. std::ifstream fs_;
  156. unsigned total_bytes_ = 0;
  157. };
  158.  
  159. class FreadBuffered : public ByteReadBase
  160. {
  161. public:
  162. FreadBuffered( unsigned buffer_size )
  163. {
  164. buf_ = (char*)malloc( buffer_size );
  165. buffer_size_ = buffer_size;
  166. }
  167. ~FreadBuffered()
  168. {
  169. if ( file_opened_ )
  170. {
  171. close();
  172. }
  173. if ( buf_ )
  174. {
  175. free( buf_ );
  176. }
  177. }
  178.  
  179. bool open( const char* file ) override
  180. {
  181. if ( file_opened_ )
  182. {
  183. return false; // File already opened
  184. }
  185. fd_ = fopen( file, "rb" ); // Open for reading
  186. file_opened_ = fd_; // Set flag if file was successfully opened
  187. total_bytes_ = get_size(); // Save total file size
  188. bytes_in_buf_ = 0;
  189. end_ = buf_ + buffer_size_;
  190. head_ = buf_;
  191. tail_ = buf_;
  192. return file_opened_;
  193. }
  194.  
  195. void close() override
  196. {
  197. if ( file_opened_ )
  198. {
  199. fclose( fd_ );
  200. }
  201. }
  202.  
  203. bool eof() const override
  204. {
  205. return total_bytes_ == 0;
  206. }
  207.  
  208. unsigned char get_byte() override
  209. {
  210. if ( bytes_in_buf_ == 0 )
  211. {
  212. fill_buffer();
  213. }
  214. if ( bytes_in_buf_ == 0 )
  215. {
  216. return '\0';
  217. }
  218. unsigned char byte = *tail_; // get byte
  219. tail_++; // advance
  220. if ( tail_ == end_ )
  221. {
  222. tail_ = head_;
  223. }
  224. bytes_in_buf_--;
  225. if ( total_bytes_ )
  226. {
  227. total_bytes_--;
  228. }
  229. return byte;
  230. }
  231.  
  232. private:
  233. unsigned get_size() override
  234. {
  235. unsigned size = 0;
  236. if ( file_opened_ )
  237. {
  238. unsigned curr = (unsigned)ftell( fd_ ); // Get current position
  239. fseek( fd_, 0, SEEK_SET );
  240. size = (unsigned)ftell( fd_ );
  241. fseek( fd_, 0, SEEK_END );
  242. size = (unsigned)ftell( fd_ ) - size;
  243. fseek( fd_, curr, SEEK_SET ); // Get back to recent position
  244. }
  245. return size;
  246. }
  247.  
  248. void fill_buffer()
  249. {
  250. unsigned bytes_front = end_ - head_;
  251. unsigned bytes_behind = head_ - buf_;
  252. unsigned bytes = fread( head_, 1, bytes_front, fd_ );
  253. reads_++;
  254. bytes_in_buf_ += bytes;
  255. if ( bytes == bytes_front )
  256. {
  257. unsigned bytes = fread( head_, 1, bytes_behind, fd_ );
  258. reads_++;
  259. head_ = buf_ + bytes;
  260. bytes_in_buf_ += bytes;
  261. }
  262. else
  263. {
  264. head_ += bytes;
  265. }
  266. }
  267.  
  268. FILE *fd_;
  269. unsigned total_bytes_ = 0;
  270. unsigned buffer_size_ = 0;
  271. unsigned bytes_in_buf_ = 0;
  272. char *buf_ = nullptr;
  273. char *end_ = nullptr;
  274. char *head_ = nullptr;
  275. char *tail_ = nullptr;
  276. };
  277.  
  278. class FstreamBuffered : public ByteReadBase
  279. {
  280. public:
  281. FstreamBuffered( unsigned buffer_size )
  282. {
  283. buf_ = (char*)malloc( buffer_size );
  284. buffer_size_ = buffer_size;
  285. }
  286. ~FstreamBuffered()
  287. {
  288. if ( file_opened_ )
  289. {
  290. close();
  291. }
  292. if ( buf_ )
  293. {
  294. free( buf_ );
  295. }
  296. }
  297.  
  298. bool open( const char* file ) override
  299. {
  300. if ( file_opened_ )
  301. {
  302. return false;
  303. }
  304. fs_.unsetf( std::ios_base::skipws );
  305. fs_.open( file, std::ifstream::binary | std::ifstream::in );
  306. file_opened_ = fs_.good();
  307. total_bytes_ = get_size();
  308. bytes_in_buf_ = 0;
  309. end_ = buf_ + buffer_size_;
  310. head_ = buf_;
  311. tail_ = buf_;
  312. return file_opened_;
  313. }
  314.  
  315. void close() override
  316. {
  317. if ( file_opened_ )
  318. {
  319. fs_.close();
  320. }
  321. }
  322.  
  323. bool eof() const override
  324. {
  325. return total_bytes_ == 0;
  326. }
  327.  
  328. unsigned char get_byte() override
  329. {
  330. if ( bytes_in_buf_ == 0 )
  331. {
  332. fill_buffer();
  333. }
  334. if ( bytes_in_buf_ == 0 )
  335. {
  336. return '\0';
  337. }
  338. unsigned char byte = *tail_; // get byte
  339. tail_++; // advance
  340. if ( tail_ == end_ )
  341. {
  342. tail_ = head_;
  343. }
  344. bytes_in_buf_--;
  345. if ( total_bytes_ )
  346. {
  347. total_bytes_--;
  348. }
  349. return byte;
  350. }
  351.  
  352. private:
  353. unsigned get_size() override
  354. {
  355. unsigned size = 0;
  356. if ( file_opened_ )
  357. {
  358. unsigned curr = (unsigned)fs_.tellg(); // Get current position
  359. fs_.seekg( 0, std::ios::beg );
  360. size = (unsigned)fs_.tellg();
  361. fs_.seekg( 0, std::ios::end );
  362. size = (unsigned)fs_.tellg() - size;
  363. fs_.seekg( 0, std::ios::beg ); // Get back to recent position
  364. }
  365. return size;
  366. }
  367.  
  368. void fill_buffer()
  369. {
  370. unsigned bytes_front = end_ - head_;
  371. unsigned bytes_behind = head_ - buf_;
  372. fs_.read( head_, bytes_front );
  373. reads_++;
  374. unsigned bytes = (unsigned)fs_.gcount();
  375. bytes_in_buf_ += bytes;
  376. if ( bytes == bytes_front )
  377. {
  378. unsigned bytes = (unsigned)fs_.readsome( head_, bytes_behind );
  379. reads_++;
  380. head_ = buf_ + bytes;
  381. bytes_in_buf_ += bytes;
  382. }
  383. else
  384. {
  385. head_ += bytes;
  386. }
  387. }
  388.  
  389. std::ifstream fs_;
  390. unsigned total_bytes_ = 0;
  391. unsigned buffer_size_ = 0;
  392. unsigned bytes_in_buf_ = 0;
  393. char *buf_ = nullptr;
  394. char *end_ = nullptr;
  395. char *head_ = nullptr;
  396. char *tail_ = nullptr;
  397. };
  398.  
  399. int main( int argc, char** argv )
  400. {
  401. if ( argc < 3 )
  402. {
  403. printf( "Usage: %s <file name> <buf size>", argv[0] );
  404. return 1;
  405. }
  406. std::unique_ptr<ByteReadBase> f;
  407.  
  408. auto run = [&]( ByteReadBase *fs ) {
  409. unsigned checksum = 0;
  410. unsigned bytes = 0;
  411. f.reset( fs );
  412. if ( f->open( argv[1] ) )
  413. {
  414. std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now();
  415. char byte = f->get_byte();
  416. while( !f->eof() )
  417. {
  418. byte = f->get_byte();
  419. checksum += byte;
  420. bytes++;
  421. }
  422. std::chrono::high_resolution_clock::time_point end = std::chrono::high_resolution_clock::now();
  423. 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 );
  424. }
  425. else
  426. {
  427. printf( "Failed to open file\n" );
  428. }
  429. };
  430.  
  431. // printf( "Measuring C API (fread) performance\n" );
  432. // run( new Fread );
  433. // printf( "Measuring C++ API (ifstream) performance\n" );
  434. // run( new Fstream );
  435. unsigned buf_size = atoi( argv[2] );
  436. printf( "Measuring buffered C API (fread) performance\n" );
  437. run( new FreadBuffered( buf_size ) );
  438. // printf( "Measuring buffered C++ API (ifstream) performance\n" );
  439. // run( new FstreamBuffered( buf_size ) );
  440. return 0;
  441. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement