~sysbench-developers/sysbench/0.4

« back to all changes in this revision

Viewing changes to sysbench/sysbench.c

  • Committer: Alexey Kopytov
  • Date: 2011-07-21 13:29:08 UTC
  • Revision ID: akopytov@gmail.com-20110721132908-tt2u2572kihrnzs6
Bug #811105: Add an option to dump full stats after specified time
             intervals.

Added a new --report-checkpoints option that allows to dump full
statistics and reset all counters at specified points in time. The
argument is a list of comma-separated values representing the amount of
time in seconds elapsed from start of test when report checkpoint(s)
must be performed. Report checkpoints are off by   Report checkpoints
are off by default.

Show diffs side-by-side

added added

removed removed

Lines of Context:
59
59
#ifdef HAVE_SIGNAL_H
60
60
# include <signal.h>
61
61
#endif
 
62
#ifdef HAVE_LIMITS_H
 
63
# include <limits.h>
 
64
#endif
62
65
 
63
66
#include "sysbench.h"
64
67
#include "sb_options.h"
91
94
  {"report-interval", "periodically report intermediate statistics "
92
95
   "with a specified interval in seconds. 0 disables intermediate reports",
93
96
    SB_ARG_TYPE_INT, "0"},
 
97
  {"report-checkpoints", "dump full statistics and reset all counters at "
 
98
   "specified points in time. The argument is a list of comma-separated values "
 
99
   "representing the amount of time in seconds elapsed from start of test "
 
100
   "when report checkpoint(s) must be performed. Report checkpoints are off by "
 
101
   "default.", SB_ARG_TYPE_LIST, ""},
94
102
  {"test", "test to run", SB_ARG_TYPE_STRING, NULL},
95
103
  {"debug", "print more debugging info", SB_ARG_TYPE_FLAG, "off"},
96
104
  {"validate", "perform validation checks where possible", SB_ARG_TYPE_FLAG, "off"},
125
133
  if (sig == SIGALRM)
126
134
  {
127
135
    sb_timer_stop(&sb_globals.exec_timer);
 
136
    sb_timer_stop(&sb_globals.cumulative_timer1);
 
137
    sb_timer_stop(&sb_globals.cumulative_timer2);
128
138
    log_text(LOG_FATAL,
129
139
             "The --max-time limit has expired, forcing shutdown...");
130
140
    if (current_test && current_test->ops.print_stats)
337
347
             sb_globals.report_interval);
338
348
  }
339
349
 
 
350
  if (sb_globals.n_checkpoints > 0)
 
351
  {
 
352
    char         list_str[MAX_CHECKPOINTS * 12];
 
353
    char         *tmp = list_str;
 
354
    unsigned int i;
 
355
    int          n, size = sizeof(list_str);
 
356
 
 
357
    for (i = 0; i < sb_globals.n_checkpoints - 1; i++)
 
358
    {
 
359
      n = snprintf(tmp, size, "%u, ", sb_globals.checkpoints[i]);
 
360
      if (n >= size)
 
361
        break;
 
362
      tmp += n;
 
363
      size -= n;
 
364
    }
 
365
    if (i == sb_globals.n_checkpoints - 1)
 
366
      snprintf(tmp, size, "%u", sb_globals.checkpoints[i]);
 
367
    log_text(LOG_NOTICE, "Report checkpoint(s) at %s seconds",
 
368
             list_str);
 
369
  }
 
370
 
340
371
  if (sb_globals.debug)
341
372
    log_text(LOG_NOTICE, "Debug mode enabled.\n");
342
373
  
511
542
  return NULL;
512
543
}
513
544
 
 
545
/* Checkpoints reports thread */
 
546
 
 
547
static void *checkpoints_thread_proc(void *arg)
 
548
{
 
549
  unsigned long long       pause_ns;
 
550
  unsigned long long       next_ns;
 
551
  unsigned long long       curr_ns;
 
552
  unsigned int             i;
 
553
 
 
554
  (void)arg; /* unused */
 
555
 
 
556
  if (current_test->ops.print_stats == NULL)
 
557
  {
 
558
    log_text(LOG_DEBUG, "Reporting not supported by the current test, ",
 
559
             "terminating the reporting thread");
 
560
    return NULL;
 
561
  }
 
562
 
 
563
  log_text(LOG_DEBUG, "Checkpoints report thread started");
 
564
 
 
565
  pthread_mutex_lock(&thread_start_mutex);
 
566
  pthread_mutex_unlock(&thread_start_mutex);
 
567
 
 
568
  for (i = 0; i < sb_globals.n_checkpoints; i++)
 
569
  {
 
570
    next_ns = SEC2NS(sb_globals.checkpoints[i]);
 
571
    curr_ns = sb_timer_value(&sb_globals.exec_timer);
 
572
    if (next_ns <= curr_ns)
 
573
      continue;
 
574
 
 
575
    pause_ns = next_ns - curr_ns;
 
576
    usleep(pause_ns / 1000);
 
577
    /*
 
578
      Just to update elapsed time in timer which is alter used by
 
579
      log_timestamp.
 
580
    */
 
581
    curr_ns = sb_timer_value(&sb_globals.exec_timer);
 
582
 
 
583
    SB_THREAD_MUTEX_LOCK();
 
584
    log_timestamp(LOG_NOTICE, &sb_globals.exec_timer, "Checkpoint report:");
 
585
    current_test->ops.print_stats(SB_STAT_CUMULATIVE);
 
586
    print_global_stats();
 
587
    SB_THREAD_MUTEX_UNLOCK();
 
588
  }
 
589
 
 
590
  return NULL;
 
591
}
514
592
 
515
593
/* 
516
594
  Main test function. Start threads. 
522
600
  unsigned int i;
523
601
  int          err;
524
602
  pthread_t    report_thread;
 
603
  pthread_t    checkpoints_thread;
525
604
  int          report_thread_created = 0;
 
605
  int          checkpoints_thread_created = 0;
526
606
 
527
607
  /* initialize test */
528
608
  if (test->ops.init != NULL && test->ops.init() != 0)
533
613
 
534
614
  /* initialize and start timers */
535
615
  sb_timer_init(&sb_globals.exec_timer);
 
616
  sb_timer_init(&sb_globals.cumulative_timer1);
 
617
  sb_timer_init(&sb_globals.cumulative_timer2);
536
618
  for(i = 0; i < sb_globals.num_threads; i++)
537
619
  {
538
 
    sb_timer_init(&sb_globals.op_timers[i]);
539
620
    threads[i].id = i;
540
621
    threads[i].test = test;
541
622
  }    
575
656
    report_thread_created = 1;
576
657
  }
577
658
 
 
659
  if (sb_globals.n_checkpoints > 0)
 
660
  {
 
661
    /* Create a thread for checkpoint statistic reports */
 
662
    if ((err = pthread_create(&checkpoints_thread, &thread_attr,
 
663
                              &checkpoints_thread_proc, NULL)) != 0)
 
664
    {
 
665
      log_errno(LOG_FATAL, "pthread_create() for the checkpoint thread "
 
666
                "failed.");
 
667
      return 1;
 
668
    }
 
669
    checkpoints_thread_created = 1;
 
670
  }
 
671
 
578
672
  /* Starting the test threads */
579
673
  for(i = 0; i < sb_globals.num_threads; i++)
580
674
  {
589
683
  }
590
684
 
591
685
  sb_timer_start(&sb_globals.exec_timer); /* Start benchmark timer */
 
686
  sb_timer_start(&sb_globals.cumulative_timer1);
 
687
  sb_timer_start(&sb_globals.cumulative_timer2);
592
688
 
593
689
#ifdef HAVE_ALARM
594
690
  /* Set the alarm to force shutdown */
607
703
  }
608
704
 
609
705
  sb_timer_stop(&sb_globals.exec_timer);
 
706
  sb_timer_stop(&sb_globals.cumulative_timer1);
 
707
  sb_timer_stop(&sb_globals.cumulative_timer2);
610
708
 
611
709
  /* Silence periodic reports if they were on */
612
710
  sb_globals.report_interval = 0;
633
731
  if (test->ops.done != NULL)
634
732
    (*(test->ops.done))();
635
733
 
636
 
  /* Delay killing the reporting thread to avoid mutex lock leaks */
 
734
  /* Delay killing the reporting threads to avoid mutex lock leaks */
637
735
  if (report_thread_created)
638
736
  {
639
737
    if (pthread_cancel(report_thread) || pthread_join(report_thread, NULL))
640
738
      log_errno(LOG_FATAL, "Terminating the reporting thread failed.");
641
739
  }
 
740
  if (checkpoints_thread_created)
 
741
  {
 
742
    if (pthread_cancel(checkpoints_thread) ||
 
743
        pthread_join(checkpoints_thread, NULL))
 
744
      log_errno(LOG_FATAL, "Terminating the checkpoint thread failed.");
 
745
  }
642
746
 
643
747
  return sb_globals.error != 0;
644
748
}
660
764
}
661
765
 
662
766
 
 
767
static int checkpoint_cmp(const void *a_ptr, const void *b_ptr)
 
768
{
 
769
  const unsigned int a = *(const unsigned int *) a_ptr;
 
770
  const unsigned int b = *(const unsigned int *) b_ptr;
 
771
 
 
772
  return (int) (a - b);
 
773
}
 
774
 
 
775
 
663
776
static int init(void)
664
777
{
665
778
  option_t          *opt;
666
779
  char              *tmp;
 
780
  sb_list_t         *checkpoints_list;
 
781
  sb_list_item_t    *pos_val;
 
782
  value_t           *val;
 
783
  long              res;
667
784
 
668
785
  sb_globals.num_threads = sb_get_value_int("num-threads");
669
786
  if (sb_globals.num_threads <= 0)
703
820
    else
704
821
      sb_globals.force_shutdown = 0;
705
822
  }
706
 
  
707
 
  sb_globals.op_timers = (sb_timer_t *)malloc(sb_globals.num_threads * 
708
 
                                              sizeof(sb_timer_t));
 
823
 
709
824
  threads = (sb_thread_ctxt_t *)malloc(sb_globals.num_threads * 
710
825
                                       sizeof(sb_thread_ctxt_t));
711
 
  if (sb_globals.op_timers == NULL || threads == NULL)
 
826
  if (threads == NULL)
712
827
  {
713
828
    log_text(LOG_FATAL, "Memory allocation failure.\n");
714
829
    return 1;
740
855
  }
741
856
  sb_globals.tx_rate = sb_get_value_int("tx-rate");
742
857
  sb_globals.tx_jitter = sb_get_value_int("tx-jitter");
743
 
  sb_globals.report_interval =
744
 
    sb_get_value_int("report-interval");
745
 
  
 
858
  sb_globals.report_interval = sb_get_value_int("report-interval");
 
859
 
 
860
  sb_globals.n_checkpoints = 0;
 
861
  checkpoints_list = sb_get_value_list("report-checkpoints");
 
862
  SB_LIST_FOR_EACH(pos_val, checkpoints_list)
 
863
  {
 
864
    char *endptr;
 
865
 
 
866
    val = SB_LIST_ENTRY(pos_val, value_t, listitem);
 
867
    res = strtol(val->data, &endptr, 10);
 
868
    if (*endptr != '\0' || res < 0 || res > UINT_MAX)
 
869
    {
 
870
      log_text(LOG_FATAL, "Invalid value for --report-checkpoints: '%s'",
 
871
               val->data);
 
872
      return 1;
 
873
    }
 
874
    if (++sb_globals.n_checkpoints > MAX_CHECKPOINTS)
 
875
    {
 
876
      log_text(LOG_FATAL, "Too many checkpoints in --report-checkpoints "
 
877
               "(up to %d can be defined)", MAX_CHECKPOINTS);
 
878
      return 1;
 
879
    }
 
880
    sb_globals.checkpoints[sb_globals.n_checkpoints-1] = (unsigned int) res;
 
881
  }
 
882
 
 
883
  if (sb_globals.n_checkpoints > 0)
 
884
  {
 
885
    qsort(sb_globals.checkpoints, sb_globals.n_checkpoints,
 
886
          sizeof(unsigned int), checkpoint_cmp);
 
887
  }
 
888
 
746
889
  return 0;
747
890
}
748
891