Chinaunix首页 | 论坛 | 博客
  • 博客访问: 8033412
  • 博文数量: 594
  • 博客积分: 13065
  • 博客等级: 上将
  • 技术积分: 10324
  • 用 户 组: 普通用户
  • 注册时间: 2008-03-26 16:44
个人简介

推荐: blog.csdn.net/aquester https://github.com/eyjian https://www.cnblogs.com/aquester http://blog.chinaunix.net/uid/20682147.html

文章分类

全部博文(594)

分类: C/C++

2014-04-28 14:15:14



  1. #include <fcntl.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <sys/stat.h>
  5. #include <sys/types.h>
  6. #include <sys/time.h>
  7. #include <unistd.h>
  8. #include <glog/logging.h>
  9. #include <gflags/gflags.h>

  10. // 读文件类
  11. class CFileReader
  12. {
  13. public:
  14.     CFileReader()
  15.         : _buffer(NULL)
  16.     {
  17.     }

  18.     ~CFileReader()
  19.     {
  20.         free(_buffer);
  21.     }

  22.     bool open(const char* filepath)
  23.     {
  24.         // 以O_DIRECT方式打开文件
  25.         int fd = ::open(filepath, O_RDONLY | O_DIRECT);
  26.         if (-1 == fd)
  27.         {
  28.             LOG(ERROR) << "open " << filepath << " error: " << strerror(errno);
  29.             return false;
  30.         }

  31.         // 取得文件大小,以便一次性将文件读取出来
  32.         struct stat st;
  33.         if (-1 == fstat(fd, &st))
  34.         {
  35.             LOG(ERROR) << "stat " << filepath << " error: " << strerror(errno);
  36.             close(fd);
  37.             return false;
  38.         }

  39.         // 分配足以容纳整个文件的Buffer
  40.         // 由于以O_DIRECT方式读取,所以需要按页对齐
  41.         size_t size = st.st_size + (getpagesize() - st.st_size%getpagesize());
  42.         posix_memalign((void**)&_buffer, getpagesize(), size);
  43.         if (NULL == _buffer)
  44.         {
  45.             LOG(ERROR) << "malloc failed";
  46.             close(fd);
  47.             return false;
  48.         }
  49.     
  50.         // 将整个文件读取_buffer中
  51.         int bytes_read = read(fd, _buffer, size);
  52.         if (-1 == bytes_read)
  53.         {
  54.             LOG(ERROR) << "read " << filepath << " error: " << strerror(errno);
  55.             close(fd);
  56.             free(_buffer);
  57.             _buffer = NULL;
  58.             return false;
  59.         }
  60.         else if (bytes_read != size)
  61.         {
  62.             // 两组测试输出数据:
  63.             // FileSize(212000000) => AlignSize(212000768) -> RealSize(212000000)
  64.             // FileSize(2120000000) => AlignSize(2120003584) -> RealSize(2120000000)
  65.             printf("FileSize(%d) => AlignSize(%d) -> RealSize(%d)\n", st.st_size, size, bytes_read);
  66.         }

  67.         return true;
  68.     }

  69.     // 从文件中读取一个节点数据
  70.     // offset:偏移量
  71.     // return:返回指向记录的指针
  72.     template <class P>
  73.     const P* get_record(uint64_t offset) const
  74.     {
  75.         return reinterpret_cast<P*>(_buffer + offset);
  76.     }

  77.     // 取得文件所有的记录
  78.     template <class P>
  79.     const P** get_all_record() const
  80.     {
  81.         return reinterpret_cast<P**>(_buffer);
  82.     }

  83. private:
  84.     char* _buffer;
  85. };

  86. // 用于计时
  87. class TimeWatcher
  88. {
  89. public:
  90.     TimeWatcher(const std::string& tip)
  91.         : _tip(tip)
  92.     {
  93.         struct timeval now;
  94.         gettimeofday(&now, NULL);

  95.         _now_msec = (now.tv_sec * 1000) + (now.tv_usec / 1000);
  96.     }

  97.     ~TimeWatcher()
  98.     {
  99.         struct timeval now;
  100.         gettimeofday(&now, NULL);

  101.         time_t cur_msec = (now.tv_sec * 1000) + (now.tv_usec / 1000);
  102.         LOG(INFO) << _tip << " spend " << cur_msec - _now_msec << "ms";
  103.     }

  104. private:
  105.     std::string _tip;
  106.     time_t _now_msec;
  107. };

  108. struct User
  109. {
  110.     int32_t age;
  111.     int32_t hight;
  112.     int32_t weight;
  113.     char bitmap[50*4];
  114. };


  115. // 用于生成测试文件
  116. bool make_test_file(const char* filepath, int num_records)
  117. {
  118.     int fd = open(filepath, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
  119.     if (-1 == fd)
  120.     {
  121.         LOG(ERROR) << "open " << filepath << " error: " << strerror(errno);
  122.         return false;
  123.     }

  124.     User user;
  125.     TimeWatcher time_watcher("write");

  126.     for (int i=0; i<num_records; ++i)
  127.     {
  128.         user.age = i;
  129.         user.hight = i + i;
  130.         user.weight = i * i;

  131.         if (-1 == write(fd, &user, sizeof(user)))
  132.         {
  133.             LOG(ERROR) << "write " << filepath << " error: " << strerror(errno);
  134.             close(fd);
  135.             return false;
  136.         }
  137.     }

  138.     close(fd);
  139.     return true;
  140. }

  141. // 模拟随机读取
  142. void random_read(const CFileReader& file_reader, int num_random)
  143. {
  144.     int *index = new int[num_random];

  145.     for (int i=0; i<num_random; ++i)
  146.     {
  147.         srandom(time(NULL));
  148.         index[i] = random() % num_random;
  149.     }


  150.     TimeWatcher time_watcher("randmon read");
  151.     for (int i=0; i<num_random; ++i)
  152.     {
  153.         file_reader.get_record<struct User>(index[i]);
  154.     }
  155. }

  156. // 执行测试
  157. void test()
  158. {
  159.     int num_records1 = 1000000;
  160.     int num_records2 = 10000000;
  161.     std::string file1 = "./file_1000000";
  162.     std::string file2 = "./file_10000000";

  163.     if (make_test_file(file1.c_str(), 1000000)
  164.          && make_test_file(file2.c_str(), 10000000))
  165.     {
  166.         printf("to read, press ENTER to continue ...\n");
  167.         getchar();

  168.         CFileReader file_reader1;

  169.         {
  170.             TimeWatcher time_watcher("open");
  171.             if (!file_reader1.open(file1.c_str()))
  172.             {
  173.                 return;
  174.             }
  175.         }

  176.         random_read(file_reader1, 1000000);
  177.         random_read(file_reader1, 3000000);

  178.         CFileReader file_reader2;

  179.         {
  180.             TimeWatcher time_watcher("open");
  181.             if (!file_reader2.open(file2.c_str()))
  182.             {
  183.                 return;
  184.             }
  185.         }

  186.         random_read(file_reader2, 1000000);
  187.         random_read(file_reader2, 3000000);
  188.     }
  189. }

  190. int main(int argc, char* argv[])
  191. {
  192.     test();
  193.     return 0;
  194. }


阅读(2447) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~