Advertisement
Guest User

Untitled

a guest
Aug 21st, 2014
150
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.08 KB | None | 0 0
  1. /*
  2.  * Copyright (C) 2014 Cloudius Systems, Ltd.
  3.  *
  4.  * This work is open source software, licensed under the terms of the
  5.  * BSD license as described in the LICENSE file in the top-level directory.
  6.  */
  7.  
  8. // Use this benchmark to measure root file system performance when doing
  9. // parallel I/O into different ranges from the same file.
  10. // For example, ZFS allows parallel reads, or even parallel writes into
  11. // different ranges, on the same file.
  12. //
  13. // To run this benchmark on Linux:
  14. //    g++ -pthread -std=c++11 tests/misc-concurrent-io.cc
  15. //    ./a.out create
  16. //    ./a.out write
  17. //    ./a.out read
  18. // To run on OSv:
  19. //    make image=tests
  20. //    scripts/run.py -e "tests/misc-concurrent-io.so create"
  21. //    scripts/run.py -e "tests/misc-concurrent-io.so write"
  22. //    scripts/run.py -e "tests/misc-concurrent-io.so read"
  23.  
  24. #include <sys/types.h>
  25. #include <fcntl.h>
  26. #include <stdio.h>
  27. #include <errno.h>
  28. #include <unistd.h>
  29. #include <stdlib.h>
  30. #include <string.h>
  31. #include <time.h>
  32. #include <assert.h>
  33. #include <pthread.h>
  34. #include <float.h>
  35. #include <chrono>
  36.  
  37. using Clock = std::chrono::high_resolution_clock;
  38.  
  39. static constexpr int num_threads = 10;
  40. static constexpr unsigned file_range_length = 10 * 1024 * 1024;
  41. static constexpr unsigned file_size = num_threads * file_range_length;
  42.  
  43. static Clock s_clock;
  44. static std::chrono::time_point<Clock> test_start;
  45. static char *buf;
  46. static float min_secs = FLT_MAX;
  47. static float max_secs = 0;
  48. static pthread_mutex_t mutex;
  49.  
  50. struct file_range {
  51.     int id;
  52.     int fd;
  53.     off_t offset;
  54. };
  55.  
  56. template<typename T>
  57. static float to_seconds(T duration)
  58. {
  59.     return std::chrono::duration<float>(duration).count();
  60. }
  61.  
  62. static void *read_function(void *arg)
  63. {
  64.     struct file_range *file_range = (struct file_range *) arg;
  65.     const int fd = file_range->fd;
  66.     const off_t offset = file_range->offset;
  67.  
  68.     auto start = s_clock.now();
  69.     auto ret = pread(fd, buf, file_range_length, offset);
  70.     auto end = s_clock.now();
  71.     assert(ret == file_range_length);
  72.  
  73.     auto test_start_to_start = to_seconds(start - test_start);
  74.     auto test_start_to_end = to_seconds(end - test_start);
  75.     pthread_mutex_lock(&mutex);
  76.     if (test_start_to_start < min_secs) {
  77.         min_secs = test_start_to_start;
  78.     }
  79.  
  80.     if (test_start_to_end > max_secs) {
  81.         max_secs = test_start_to_end;
  82.     }
  83.     pthread_mutex_unlock(&mutex);
  84.  
  85. #if 1
  86.     printf("Thread %d, %d bytes read from offset %d, "
  87.         "Duration %.2f ms : %.2f ms.\n",
  88.         file_range->id, file_range_length, offset,
  89.         test_start_to_start * 1000,
  90.         test_start_to_end * 1000);
  91. #endif
  92.  
  93.     return nullptr;
  94. }
  95.  
  96. static void *write_function(void *arg)
  97. {
  98.     struct file_range *file_range = (struct file_range *) arg;
  99.     const int fd = file_range->fd;
  100.     const off_t offset = file_range->offset;
  101.  
  102.     auto start = s_clock.now();
  103.     auto ret = pwrite(fd, buf, file_range_length, offset);
  104.     auto end = s_clock.now();
  105.     assert(ret == file_range_length);
  106.  
  107.  
  108.     auto test_start_to_start = to_seconds(start - test_start);
  109.     auto test_start_to_end = to_seconds(end - test_start);
  110.     pthread_mutex_lock(&mutex);
  111.     if (test_start_to_start < min_secs) {
  112.         min_secs = test_start_to_start;
  113.     }
  114.  
  115.     if (test_start_to_end > max_secs) {
  116.         max_secs = test_start_to_end;
  117.     }
  118.     pthread_mutex_unlock(&mutex);
  119.  
  120. #if 1
  121.     printf("Thread %d, %d bytes written to offset %d, "
  122.         "Duration %.2f ms : %.2f ms.\n",
  123.         file_range->id, file_range_length, offset,
  124.         test_start_to_start * 1000,
  125.         test_start_to_end * 1000);
  126. #endif
  127.  
  128.     return nullptr;
  129. }
  130.  
  131. static void run_test(int fd, void *(*function)(void *))
  132. {
  133.     pthread_t thread_id[num_threads];
  134.     file_range file_ranges[num_threads];
  135.  
  136.     test_start = s_clock.now();
  137.     for (int i = 0; i < num_threads; i++) {
  138.         file_ranges[i].id = i;
  139.         file_ranges[i].fd = fd;
  140.         file_ranges[i].offset = i * file_range_length;
  141.  
  142.         pthread_create(&thread_id[i], nullptr, function,
  143.             (void *)&file_ranges[i]);
  144.     }
  145.  
  146.     for (int i = 0; i < num_threads; i++) {
  147.         pthread_join(thread_id[i], nullptr);
  148.     }
  149. }
  150.  
  151. static void usage(char *app)
  152. {
  153.     fprintf(stderr, "usage: %s <create|read|write>\n", app);
  154. }
  155.  
  156. int main(int argc, char **argv)
  157. {
  158.     char fname[64] = "/tst-concurrent-io.tmp";
  159.  
  160.     if (argc != 2) {
  161.         usage(argv[0]);
  162.         return -1;
  163.     }
  164.  
  165.     if (!strcmp(argv[1], "create")) {
  166.         int oflags = O_CREAT | O_WRONLY | O_DIRECT;
  167.         int fd = open(fname, oflags);
  168.         if (fd == -1) {
  169.             perror("open");
  170.             return -1;
  171.         }
  172.         assert(ftruncate(fd, file_size) == 0);
  173.  
  174.         buf = new char[file_size];
  175.         memset(buf, 0xAB, file_size);
  176.         auto ret = pwrite(fd, buf, file_size, 0);
  177.         assert(ret == file_size);
  178.         delete buf;
  179.  
  180.         printf("%s: creation phase finished successfully!\n", argv[0]);
  181.  
  182.         close(fd);
  183.     } else if (!strcmp(argv[1], "read")) {
  184.         int oflags = O_RDONLY | O_SYNC;
  185.         int fd = open(fname, oflags);
  186.         if (fd == -1) {
  187.             perror("open");
  188.             return -1;
  189.         }
  190.  
  191.         buf = new char[file_range_length];
  192.         run_test(fd, read_function);
  193.         delete buf;
  194.         printf("%s: read: Duration %.2f ms : %.2f ms = %.2fms\n",
  195.             argv[0], min_secs * 1000, max_secs * 1000,
  196.             (max_secs - min_secs) * 1000);
  197.  
  198.         close(fd);
  199.     } else if (!strcmp(argv[1], "write")) {
  200.         int oflags = O_WRONLY | O_SYNC;
  201.         int fd = open(fname, oflags);
  202.         if (fd == -1) {
  203.             perror("open");
  204.             return -1;
  205.         }
  206.  
  207.         buf = new char[file_range_length];
  208.         memset(buf, 0xBA, file_range_length);
  209.         run_test(fd, write_function);
  210.         delete buf;
  211.         printf("%s: write: Duration %.2f ms : %.2f ms = %.2fms\n",
  212.             argv[0], min_secs * 1000, max_secs * 1000,
  213.             (max_secs - min_secs) * 1000);
  214.  
  215.         close(fd);
  216.     } else {
  217.         usage(argv[0]);
  218.         return -1;
  219.     }
  220.  
  221.     return 0;
  222. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement