mirror of https://github.com/CGAL/cgal
235 lines
6.7 KiB
C++
235 lines
6.7 KiB
C++
// Copyright (c) 1997 Tel-Aviv University (Israel).
|
|
// All rights reserved.
|
|
//
|
|
// This file is part of CGAL (www.cgal.org); you may redistribute it under
|
|
// the terms of the Q Public License version 1.0.
|
|
// See the file LICENSE.QPL distributed with CGAL.
|
|
//
|
|
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
|
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
|
//
|
|
// $URL$
|
|
// $Id$
|
|
//
|
|
//
|
|
// Author(s) : Efi Fogel <efif@post.tau.ac.il>
|
|
|
|
#ifndef CGAL_BENCH_HPP
|
|
#define CGAL_BENCH_HPP
|
|
|
|
#include <time.h>
|
|
#include <signal.h>
|
|
#include <stdio.h>
|
|
#include <string>
|
|
#include <iostream>
|
|
#include <iomanip>
|
|
|
|
#if !(defined _MSC_VER)
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
#include "CGAL/benchmark_basic.hpp"
|
|
|
|
CGAL_BENCHMARK_BEGIN_NAMESPACE
|
|
|
|
/*!
|
|
*/
|
|
class Bench_base {
|
|
public:
|
|
/*!
|
|
*/
|
|
static int get_name_length() { return m_name_length; }
|
|
static void set_name_length(int nameLength) { m_name_length = nameLength; }
|
|
|
|
/*!
|
|
*/
|
|
static void print_header()
|
|
{
|
|
std::cout << std::setw(m_name_length) << std::left << "Bench"
|
|
<< " Bench Ops Total Single Num Ops \n";
|
|
|
|
std::cout << std::setw(m_name_length) << std::left << " Name"
|
|
<< " Time Num Ops Time Op Time Per Sec\n";
|
|
|
|
std::cout << std::setw(m_name_length) << std::setfill('-') << ""
|
|
<< " -------- -------- -------- -------- --------\n"
|
|
<< std::setfill(' ');
|
|
}
|
|
|
|
protected:
|
|
#if (!defined _MSC_VER)
|
|
/*!
|
|
*/
|
|
static void process_signal(int sig) { m_got_signal = true; }
|
|
#endif
|
|
|
|
static bool m_got_signal;
|
|
static int m_name_length;
|
|
};
|
|
|
|
template <class Benchable>
|
|
class Bench : public Bench_base {
|
|
private:
|
|
typedef Bench<Benchable> Self;
|
|
|
|
public:
|
|
/*!
|
|
*/
|
|
Bench(std::string name = "", int seconds = 1, bool print_header = true) :
|
|
m_name(name),
|
|
m_print_header(print_header),
|
|
m_header_printed(false),
|
|
m_factor(1.0f), m_seconds(seconds),
|
|
m_samples(0), m_period(0.0f), m_iterations(0)
|
|
{}
|
|
|
|
virtual ~Bench() {}
|
|
|
|
int get_iterations() const { return m_iterations; }
|
|
int get_seconds() const { return m_seconds; }
|
|
int get_samples() const { return m_samples; }
|
|
|
|
void set_iterations(int iterations) { m_iterations = iterations; }
|
|
void set_seconds(int seconds) { m_seconds = seconds; }
|
|
void set_samples(int samples) { m_samples = samples; }
|
|
|
|
float get_period() const { return m_period; }
|
|
|
|
/*!
|
|
*/
|
|
void operator()()
|
|
{
|
|
if (m_benchable.init() < 0) return;
|
|
loop();
|
|
m_benchable.clean();
|
|
print_results();
|
|
}
|
|
|
|
/*!
|
|
*/
|
|
void loop()
|
|
{
|
|
int i;
|
|
time_t cycle_secs = UINT_MAX / CLOCKS_PER_SEC;
|
|
|
|
m_benchable.sync();
|
|
if (m_samples == 0) {
|
|
if (m_iterations != 0) {
|
|
time_t time_start_secs = time(0);
|
|
clock_t time_start_ticks = clock();
|
|
for (i = 0; i < m_iterations; i++) m_benchable.op();
|
|
m_benchable.sync();
|
|
clock_t time_end_ticks = clock();
|
|
time_t sec_end_secs = time(0);
|
|
|
|
clock_t time_interval_ticks = time_end_ticks - time_start_ticks;
|
|
time_t time_interval_secs = time_interval_ticks / CLOCKS_PER_SEC;
|
|
time_t time_interval_approx_secs = sec_end_secs - time_start_secs;
|
|
|
|
unsigned int num_cycles = time_interval_approx_secs / cycle_secs;
|
|
|
|
time_t time_interval_tmp = num_cycles * cycle_secs + time_interval_secs;
|
|
if (time_interval_tmp > time_interval_approx_secs) {
|
|
time_t diff = time_interval_tmp - time_interval_approx_secs;
|
|
if (diff > cycle_secs / 2)
|
|
num_cycles--;
|
|
} else {
|
|
time_t diff = time_interval_approx_secs - time_interval_tmp;
|
|
if (diff > cycle_secs / 2)
|
|
num_cycles++;
|
|
}
|
|
|
|
float time_interval = num_cycles * cycle_secs +
|
|
(float) time_interval_ticks / (float) CLOCKS_PER_SEC;
|
|
m_samples = (int) ((float) m_seconds / time_interval);
|
|
if (m_samples == 0) m_samples = 1;
|
|
m_samples *= m_iterations;
|
|
} else {
|
|
#if (defined _MSC_VER)
|
|
std::cerr << "signal() is not supported by windows!" << std::endl
|
|
<< "Set the number of iterations directly "
|
|
<< "or set the number of samples." << std::endl;
|
|
#else
|
|
m_got_signal = false;
|
|
|
|
signal(SIGALRM, &Self::process_signal);
|
|
alarm(m_seconds);
|
|
do {
|
|
m_benchable.op();
|
|
m_samples++;
|
|
} while (!m_got_signal);
|
|
#endif
|
|
}
|
|
} else {
|
|
m_seconds = 0;
|
|
}
|
|
|
|
m_benchable.sync();
|
|
time_t time_start_secs = time(0);
|
|
clock_t time_start_ticks = clock();
|
|
for (i = 0; i < m_samples; i++) m_benchable.op();
|
|
m_benchable.sync();
|
|
clock_t time_end_ticks = clock();
|
|
time_t sec_end_secs = time(0);
|
|
|
|
clock_t time_interval_ticks = time_end_ticks - time_start_ticks;
|
|
time_t time_interval_secs = time_interval_ticks / CLOCKS_PER_SEC;
|
|
time_t time_interval_approx_secs = sec_end_secs - time_start_secs;
|
|
unsigned int num_cycles = time_interval_approx_secs / cycle_secs;
|
|
time_t time_interval_tmp = num_cycles * cycle_secs + time_interval_secs;
|
|
if (time_interval_tmp > time_interval_approx_secs) {
|
|
time_t diff = time_interval_tmp - time_interval_approx_secs;
|
|
if (diff > cycle_secs / 2)
|
|
num_cycles--;
|
|
} else {
|
|
time_t diff = time_interval_approx_secs - time_interval_tmp;
|
|
if (diff > cycle_secs / 2)
|
|
num_cycles++;
|
|
}
|
|
m_period = num_cycles * cycle_secs +
|
|
(float) time_interval_ticks / (float) CLOCKS_PER_SEC;
|
|
|
|
// std::cout << m_samples << " iterations, " << m_period <<" seconds"
|
|
// << std::endl;
|
|
}
|
|
|
|
/*!
|
|
*/
|
|
virtual void print_results()
|
|
{
|
|
fflush(stdout);
|
|
if (!m_header_printed && m_print_header) print_header();
|
|
m_header_printed = true;
|
|
int count = (int) ((float) m_samples * m_factor);
|
|
std::cout << std::setw(m_name_length) << std::left
|
|
<< m_name.substr(0, m_name_length).c_str() << " "
|
|
<< std::setw(8) << std::right << m_seconds << " "
|
|
<< std::setw(8) << std::right << count << " "
|
|
<< std::setw(8) << std::right << std::setprecision(4)
|
|
<< std::fixed << m_period << " "
|
|
<< std::setw(8) << std::right << std::setprecision(4)
|
|
<< std::fixed << m_period / (float) count << " "
|
|
<< std::setw(8) << std::right << std::setprecision(4)
|
|
<< std::fixed << (float) count / m_period
|
|
<< std::endl;
|
|
}
|
|
|
|
Benchable & get_benchable() { return m_benchable; }
|
|
|
|
private:
|
|
Benchable m_benchable;
|
|
|
|
std::string m_name;
|
|
bool m_print_header;
|
|
bool m_header_printed;
|
|
float m_factor;
|
|
int m_seconds;
|
|
int m_samples;
|
|
float m_period;
|
|
int m_iterations;
|
|
};
|
|
|
|
CGAL_BENCHMARK_END_NAMESPACE
|
|
|
|
#endif
|