Hi all, thanks for the many replies - it represents the Journey of discovery I've been on!
Okay..
[quote name='Álvaro' timestamp='1357144129' post='5016737']
What platform are you working with? Can you use C++11? How about Boost?
[/quote]
I'm running on an i586 netbook with Ubuntu, I have GNU libraries available, and I'm compiling with G++ and ICPC (no intel C++ libraries though)..
However I'm also compiling on my android phone with G++ + Bionic libc, which is apparently like a half-assed C++ library for Android from Google.
I'd prefer not to use boost, as I'd like to keep it as simple and unconvoluted and generic as possible - my code's already a bit messy and I'm running out of time before I have to give it in :/
I have no idea if I have C++ 11 - is there a pretty little macro or something to discover this?
I discovered CLOCK_MONOTONIC_RAW, which gives actual processor time not adjusted by ntpd (?)
Thread Interrupts!! Why did this not occur to me?
Heres the scruffy little wrapper I've thrown all my thinking into..
It's not too bad, though I'd like a floating point seconds value, So I can get minutes out of it.
I think because I'm testing some 600,000 unsigned long longs, it takes a while, and the long type of tv_nsecs isn't big enough maybe?
#pragma once
#include <time.h>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <fstream>
//Some help with timing
#ifdef CLOCK_MONOTONIC_RAW
#define USED_CLOCK CLOCK_MONOTONIC_RAW
#else
#define USED_CLOCK CLOCK_MONOTONIC
#endif
#define BILLION 1000000000 // 1E9 // ..for nano seconds to seconds
struct timestamp { // we will stack these in the vector
double mins;
time_t secs;
long nsecs;
std::string desc;
timestamp(double m, time_t s, long n, std::string d) {
mins = m; secs = s; nsecs = n;
desc = d;
}
};
// This learned from here
//http://www.guyrutenberg.com/2007/09/22/profiling-code-using-clock_gettime/
//
timespec diff(timespec start, timespec end) {
timespec tmp;
if( (end.tv_sec - start.tv_sec) < 0 ) {
tmp.tv_sec = end.tv_sec - start.tv_sec - 1;
tmp.tv_nsec = BILLION + end.tv_nsec - start.tv_nsec;
}
else {
tmp.tv_sec = end.tv_sec - start.tv_sec ;
tmp.tv_nsec = end.tv_nsec - start.tv_nsec ;
}
return tmp;
}
//
// TWO GLOBAL VECTORS! SORRY!
// Need all timers to report onto one list so they can be gotten to elsewhere
//
std::vector<timestamp*> g_nonthread_tests, g_threaded_tests;
std::vector<timestamp*>::iterator g_index;
class Timer
{
private:
timespec beg ;
timespec end ;
public:
std::string desc;
void start() {
clock_gettime( USED_CLOCK, &beg );
}
void stop( bool is_thr ) {
clock_gettime( USED_CLOCK, &end ) ;
long nsecs = diff( beg, end ).tv_nsec ;
time_t secs = diff( beg, end ).tv_sec ; // nsecs / BILLION;
double mins = 0 ;
if( secs > 60.0f ) mins = secs / 60.0f ;
std::cout << " took " << mins << "mins -> " << secs << "s" << std::endl ;
timestamp * t = new timestamp( mins, secs, nsecs, desc);
if( is_thr ) g_threaded_tests.push_back( t );
else g_nonthread_tests.push_back( t );
}
void PublishFinalReportToFile( std::string filename, bool thr )
{
std::fstream output;
output.open( filename.c_str(), std::ios::out | std::ios::trunc );
if( output.is_open() && output.good() )
{ int count = 0 ;
if( thr ) {
for ( g_index = g_threaded_tests.begin(); g_index != g_threaded_tests.end(); ++g_index, count++ )
{
output << "\n===============================================================";
output << "\n::\tTest:\t" << count ;
output << "\n::\tDesc:\t" << (*g_index)->desc ;
output << "\n::\tMins: " << (*g_index)->mins ;
output << "\n::\tSecs: " << (*g_index)->secs ;
output << "\n::\tNanoSecs: "<< (*g_index)->nsecs;
}
output << "\n===============================================================";
}
else {
for ( g_index = g_nonthread_tests.begin(); g_index != g_nonthread_tests.end(); ++g_index, count++ )
{
output << "\n===============================================================";
output << "\n::\tTest:\t" << count ;
output << "\n::\tDesc:\t" << (*g_index)->desc ;
output << "\n::\tMins: " << (*g_index)->mins ;
output << "\n::\tSecs: " << (*g_index)->secs ;
output << "\n::\tNanoSecs: "<< (*g_index)->nsecs;;
}
output << "\n===============================================================";
}
}
output.close();
}
};
[quote name='Trienco' timestamp='1357201424' post='5017013']
Using the regular realtime or monotonic clock will screw up your results, because of the above.
[/quote]
--B3comes change 1 - thing is I'm comparing threads to not-threads.. but I could work it into an if/else
[quote name='Bacterius' timestamp='1357191851' post='5016987']
If an operation is too quick (e.g. nanoseconds) you won't be able to get proper timing anyway because of processor interrupts, thread scheduling, etc.. why not run them lots of times and take the average?
[/quote]
Okay fair shout.. but it's a big array - 36MB! Read and write are much faster than search duplicates for example..