Commit e0a0e2ae authored by Paal Kvamme's avatar Paal Kvamme
Browse files

Centralize the point where timers are enabled. Less code duplication.

parent 94b68f03
......@@ -102,7 +102,7 @@
#include "logger.h"
#include "compression.h"
#include "environment.h"
#include "timer.h"
#include "fancy_timers.h"
#include "../exception.h"
#include <algorithm>
......@@ -139,11 +139,6 @@ using namespace InternalZGY::ArrayOps;
using namespace InternalZGY::Formatters;
namespace {
static bool timers_on()
{
static int enable = Environment::getNumericEnv("OPENZGY_TIMERS", 0);
return enable > 0;
}
/**
* For testing only; might be removed. Apps should have no reason to
* reset this variable because it is unlikely that they have another
......@@ -371,9 +366,9 @@ ZgyInternalBulk::ZgyInternalBulk(
, _written_sample_min(std::numeric_limits<double>::infinity())
, _written_sample_max(-std::numeric_limits<double>::infinity())
, _loggerfn(logger ? logger : LoggerBase::standardCallback(LoggerBase::getVerboseFromEnv("OPENZGY_VERBOSE"), "openzgy-bulk:", ""))
, _ptimer_st(new SummaryPrintingTimer("writeAligned[S]"))
, _ptimer_mt(new SummaryPrintingTimer("writeAligned[M]"))
, _ststimer(new SummaryPrintingTimer("scaleToStorage"))
, _ptimer_st(new SummaryPrintingTimerEx("writeAligned[S]"))
, _ptimer_mt(new SummaryPrintingTimerEx("writeAligned[M]"))
, _ststimer(new SummaryPrintingTimerEx("scaleToStorage"))
{
}
......@@ -1605,7 +1600,7 @@ ZgyInternalBulk::_writeAlignedRegion(
std::int32_t lod,
const compressor_t& compressor)
{
SimpleTimer t1(*_ptimer_mt, timers_on());
SimpleTimerEx t1(*_ptimer_mt);
const double defaultstorage = this->_metadata->ih().defaultstorage();
const std::int64_t lodfactor = static_cast<std::int64_t>(1) << lod;
......@@ -1737,7 +1732,7 @@ ZgyInternalBulk::_writeAlignedRegion(
// very lightweight.
t1.stop();
SimpleTimer t2(*_ptimer_st, timers_on());
SimpleTimerEx t2(*_ptimer_st);
ErrorsWillCorruptFile watchdog(this);
for (const auto& it : const_queue)
if (it)
......@@ -1799,7 +1794,7 @@ ZgyInternalBulk::writeRegion(
// might save some time.
if (!is_storage) {
SimpleTimer t1(*_ststimer, timers_on());
SimpleTimerEx t1(*_ststimer);
data = _scaleDataToStorage(data);
}
......
......@@ -43,7 +43,7 @@ struct IJK;
struct LutInfoEx;
struct WriteBrickArgPack;
struct WriteNowArgPack;
class SummaryPrintingTimer;
class SummaryPrintingTimerEx;
/**
* Read or write bulk data. The meta data needs to have been read
......@@ -77,9 +77,9 @@ private:
double _written_sample_min;
double _written_sample_max;
LoggerFn _loggerfn;
std::shared_ptr<SummaryPrintingTimer> _ptimer_st;
std::shared_ptr<SummaryPrintingTimer> _ptimer_mt;
std::shared_ptr<SummaryPrintingTimer> _ststimer;
std::shared_ptr<SummaryPrintingTimerEx> _ptimer_st;
std::shared_ptr<SummaryPrintingTimerEx> _ptimer_mt;
std::shared_ptr<SummaryPrintingTimerEx> _ststimer;
public:
ZgyInternalBulk(
......
......@@ -15,7 +15,7 @@
#ifdef HAVE_ZFP // Entire file
#include "compression.h"
#include "timer.h"
#include "fancy_timers.h"
#include "environment.h"
#include "../exception.h"
......@@ -34,14 +34,6 @@ namespace InternalZGY {
}
#endif
namespace {
static bool timers_on()
{
static int enable = Environment::getNumericEnv("OPENZGY_TIMERS", 0);
return enable > 0;
}
}
/**
* \brief Implement ZFP compression.
* \details The methods in this class will called from a factory. \details
......@@ -83,8 +75,8 @@ public:
*/
static rawdata_t compress(const rawdata_t& data, const index3_t& shape, float snr)
{
static SummaryPrintingTimer timer("ZFP-compress");
SimpleTimer tt(timer, timers_on());
static SummaryPrintingTimerEx timer("ZFP-compress");
SimpleTimerEx tt(timer);
return _try_compress(data, shape, snr);
}
......@@ -99,8 +91,8 @@ public:
cdata.second < 4 ||
0 != std::strncmp((const char*)cdata.first.get(), "zfp", 3))
return rawdata_t{nullptr, 0}; // Not ours.
static SummaryPrintingTimer timer("ZFP-decompress");
SimpleTimer tt(timer, timers_on());
static SummaryPrintingTimerEx timer("ZFP-decompress");
SimpleTimerEx tt(timer);
// TODO-Worry: Is ZFP really handling byte swapping?
return _try_decompress(cdata, shape);
}
......
......@@ -16,7 +16,7 @@
#include "roundandclip.h"
#include "../exception.h"
#include "environment.h"
#include "timer.h"
#include "fancy_timers.h"
#include <cstdint>
#include <array>
......@@ -59,12 +59,6 @@ namespace {
return std::shared_ptr<T>(p, [](T* p){});
}
static bool timers_on()
{
static int enable = Environment::getNumericEnv("OPENZGY_TIMERS", 0);
return enable > 0;
}
/**
* \brief Instrumenting DataBufferNd for performance measurements.
*
......@@ -81,31 +75,31 @@ namespace {
* For slightly more advanced usage, a global cleartimers() can
* be called to output all collected details at that point.
*
* \details Thread safety: Safe because SummaryPrintingTimer is
* \details Thread safety: Safe because SummaryPrintingTimerEx is
* thread safe when used correctly.
*/
class AdHocTimers
{
public:
SummaryPrintingTimer ctor;
SummaryPrintingTimer allsame;
SummaryPrintingTimer fill;
SummaryPrintingTimer range;
SummaryPrintingTimer clone;
SummaryPrintingTimer scaletof;
SummaryPrintingTimer scaletos;
SummaryPrintingTimer copyscalar;
SummaryPrintingTimer copysubset;
SummaryPrintingTimerEx ctor;
SummaryPrintingTimerEx allsame;
SummaryPrintingTimerEx fill;
SummaryPrintingTimerEx range;
SummaryPrintingTimerEx clone;
SummaryPrintingTimerEx scaletof;
SummaryPrintingTimerEx scaletos;
SummaryPrintingTimerEx copyscalar;
SummaryPrintingTimerEx copysubset;
AdHocTimers()
: ctor ("DBNd::ctor")
, allsame ("DBNd::allsame")
, fill ("DBNd::fill")
, range ("DBNd::range")
, clone ("DBNd::clone")
, scaletof ("DBNd::scaletof")
, scaletos ("DBNd::scaletos")
, copyscalar("DBNd::copyscalar")
, copysubset("DBNd::copysubset")
: ctor ("DBNd.ctor")
, allsame ("DBNd.allsame")
, fill ("DBNd.fill")
, range ("DBNd.range")
, clone ("DBNd.clone")
, scaletof ("DBNd.scaletof")
, scaletos ("DBNd.scaletos")
, copyscalar("DBNd.copyscalar")
, copysubset("DBNd.copysubset")
{}
static AdHocTimers& instance()
{
......@@ -461,7 +455,7 @@ DataBufferNd<T,NDim>::DataBufferNd(const std::array<std::int64_t,NDim>& size)
, _data(std::shared_ptr<T>(new T[make_product(size)], std::default_delete<T[]>()))
, _ownsdata(true)
{
SimpleTimer tt(AdHocTimers::instance().ctor, timers_on());
SimpleTimerEx tt(AdHocTimers::instance().ctor);
check_stride(_size, _stride);
// TODO-Worry: Leaving the buffer not initialized might turn an easily
// reproducible bug into a heissenbug. But zeroing the buffers here
......@@ -479,7 +473,7 @@ DataBufferNd<T,NDim>::DataBufferNd(const std::array<std::int64_t,NDim>& size,
, _data(std::shared_ptr<T>(new T[make_allocsize(size, stride)], std::default_delete<T[]>()))
, _ownsdata(true)
{
SimpleTimer tt(AdHocTimers::instance().ctor, timers_on());
SimpleTimerEx tt(AdHocTimers::instance().ctor);
check_stride(_size, _stride);
memset(_data.get(), 0, make_product(size) * sizeof(T));
}
......@@ -791,7 +785,7 @@ template <typename T, int NDim>
void
DataBufferNd<T,NDim>::fill(double value)
{
SimpleTimer tt(AdHocTimers::instance().fill, timers_on());
SimpleTimerEx tt(AdHocTimers::instance().fill);
const T val = static_cast<T>(value);
if (isScalar())
_data.get()[0] = val;
......@@ -845,7 +839,7 @@ template <typename T, int NDim>
std::pair<double, double>
DataBufferNd<T,NDim>::range() const
{
SimpleTimer tt(AdHocTimers::instance().range, timers_on());
SimpleTimerEx tt(AdHocTimers::instance().range);
T min = std::numeric_limits<T>::max();
T max = std::numeric_limits<T>::lowest();
if (isScalar()) {
......@@ -886,7 +880,7 @@ template <typename T, int NDim>
bool
DataBufferNd<T,NDim>::isAllSame(const std::int64_t *used_in) const
{
SimpleTimer tt(AdHocTimers::instance().allsame, timers_on());
SimpleTimerEx tt(AdHocTimers::instance().allsame);
// TODO-Low yet another place I wish I hadn't templeted on NDim.
std::array<std::int64_t,NDim> used;
for (int dim=0; dim<NDim; ++dim)
......@@ -980,9 +974,9 @@ DataBufferNd<T,NDim>::copyFrom(const DataBuffer* src,
const std::int64_t *cpyorig,
const std::int64_t *cpysize)
{
SimpleTimer tt(src && src->isScalar() ?
AdHocTimers::instance().copyscalar :
AdHocTimers::instance().copysubset, timers_on());
SimpleTimerEx tt(src && src->isScalar() ?
AdHocTimers::instance().copyscalar :
AdHocTimers::instance().copysubset);
const self_type* source = dynamic_cast<const self_type*>(src);
if (!source) {
......@@ -1134,7 +1128,7 @@ template <typename T, int NDim>
std::shared_ptr<DataBuffer>
DataBufferNd<T,NDim>::scaleToFloat(const std::array<double,2>& factors)
{
SimpleTimer tt(AdHocTimers::instance().scaletof, timers_on());
SimpleTimerEx tt(AdHocTimers::instance().scaletof);
return s_scaleToFloat(this, factors);
}
......@@ -1143,7 +1137,7 @@ std::shared_ptr<DataBuffer>
DataBufferNd<T,NDim>::scaleToStorage(const std::array<double,2>& factors,
RawDataType dt)
{
SimpleTimer tt(AdHocTimers::instance().scaletos, timers_on());
SimpleTimerEx tt(AdHocTimers::instance().scaletos);
// A better way of converting an enum to a template argument would be welcome.
switch (dt) {
case RawDataType::SignedInt8: return DataBufferNd<std::int8_t,NDim>::s_scaleFromFloat(this, factors);
......@@ -1166,7 +1160,7 @@ template <typename T, int NDim>
std::shared_ptr<DataBuffer>
DataBufferNd<T,NDim>::clone() const
{
SimpleTimer tt(AdHocTimers::instance().clone, timers_on());
SimpleTimerEx tt(AdHocTimers::instance().clone);
std::shared_ptr<DataBufferNd<T,NDim>> result;
if (this->isScalar()) {
result.reset(new DataBufferNd<T,NDim>(this->scalarValue(), this->safesize()));
......
......@@ -14,6 +14,7 @@
#include "file.h"
#include "environment.h"
#include "fancy_timers.h"
#include "../exception.h"
#include <vector>
......@@ -221,8 +222,8 @@ FileCommon::FileCommon(const std::string& filename, OpenMode mode)
, _name(filename)
, _eof(0)
{
_rtimer.reset(new SummaryPrintingTimer("File::read"));
_wtimer.reset(new SummaryPrintingTimer("File::write"));
_rtimer.reset(new SummaryPrintingTimerEx(mode == OpenMode::ReadWrite || mode == OpenMode::Truncate ? "File.reread" : "File.read"));
_wtimer.reset(new SummaryPrintingTimerEx("File.write"));
}
/**
......
......@@ -59,7 +59,6 @@ using the regular read and write methods of the OS or to a cloud back-end.
#include <mutex>
#include "../declspec.h"
#include "timer.h"
namespace OpenZGY {
class IOContext;
......@@ -70,6 +69,8 @@ namespace InternalZGY {
}
#endif
class SummaryPrintingTimerEx;
enum class OpenMode
{
Closed = 0,
......@@ -268,8 +269,8 @@ protected:
* Thread safety: Synchronized by the per-file mutex.
*/
std::int64_t _eof;
std::shared_ptr<SummaryTimer> _rtimer; // Access is thread safe
std::shared_ptr<SummaryTimer> _wtimer; // Access is thread safe
std::shared_ptr<SummaryPrintingTimerEx> _rtimer; // Access is thread safe
std::shared_ptr<SummaryPrintingTimerEx> _wtimer; // Access is thread safe
public:
FileCommon(const std::string& filename, OpenMode mode);
......
......@@ -49,18 +49,6 @@ namespace InternalZGY {
* \brief Low level I/O, regular files.
*/
namespace {
/**
* \brief Check whether performance logging is enabled.
* \details Thread safety: Yes, locking handled by compiler.
*/
static bool timers_on()
{
static int enable = Environment::getNumericEnv("OPENZGY_TIMERS", 0);
return enable > 0;
}
}
/**
* Thread safety when used for reading:
* Designed to be thread safe as no internal data structures should change
......@@ -109,11 +97,6 @@ LocalFileLinux::LocalFileLinux(const std::string& filename, OpenMode mode, const
, _fd(-1)
, _mutex()
{
// Use the SummaryPrintingTimer extension that keeps track of bytes done.
// The instance allocated in the base class constructor is simply dropped.
_rtimer.reset(new SummaryPrintingTimerEx(mode == OpenMode::ReadWrite || mode == OpenMode::Truncate ? "File::reread" : "File::read"));
_wtimer.reset(new SummaryPrintingTimerEx("File::write"));
switch (mode) {
case OpenMode::ReadOnly:
_fd = ::open(filename.c_str(), O_RDONLY, 0666);
......@@ -234,10 +217,10 @@ LocalFileLinux::xx_iscloud() const
void
LocalFileLinux::xx_read(void *data, std::int64_t offset, std::int64_t size, UsageHint usagehint)
{
SimpleTimer tt(*_rtimer, timers_on());
SimpleTimerEx tt(*_rtimer);
_validate_read(data, offset, size, xx_eof(), _mode);
ssize_t nbytes = ::pread(_fd, data, size, offset);
static_cast<SummaryPrintingTimerEx*>(_rtimer.get())->addBytesRead(nbytes);
_rtimer->addBytesRead(nbytes);
_check_short_read(offset, size, nbytes);
}
......@@ -342,7 +325,7 @@ LocalFileLinux::xx_readv(const ReadList& requests, bool parallel_ok, bool immuta
void
LocalFileLinux::xx_write(const void* data, std::int64_t offset, std::int64_t size, UsageHint usagehint)
{
SimpleTimer tt(*_wtimer, timers_on());
SimpleTimerEx tt(*_wtimer);
_validate_write(data, offset, size, _mode);
if (false)
std::cout << "xx_write(*, " << std::hex
......@@ -351,7 +334,7 @@ LocalFileLinux::xx_write(const void* data, std::int64_t offset, std::int64_t siz
ssize_t nbytes = ::pwrite(_fd, data, size, offset);
if (nbytes < 0)
throw OpenZGY::Errors::ZgyIoError(_name, errno);
static_cast<SummaryPrintingTimerEx*>(_wtimer.get())->addBytesWritten(nbytes);
_wtimer->addBytesWritten(nbytes);
std::lock_guard<std::mutex> lk(_mutex); // protect _eof
_eof = std::max(_eof, offset + nbytes);
if (nbytes != size)
......
......@@ -32,6 +32,7 @@ namespace InternalZGY {
}
#endif
class Timer;
class SummaryTimer;
/**
......
......@@ -19,7 +19,7 @@
#include "file.h"
#include "../exception.h"
#include "timer.h"
#include "fancy_timers.h"
#include "environment.h"
#include <vector>
......@@ -48,18 +48,6 @@ namespace InternalZGY {
* \brief Low level I/O, regular files.
*/
namespace {
/**
* \brief Check whether performance logging is enabled.
* \details Thread safety: Yes, locking handled by compiler.
*/
static bool timers_on()
{
static int enable = Environment::getNumericEnv("OPENZGY_TIMERS", 0);
return enable > 0;
}
}
/**
* Thread safety when used for reading:
* Designed to be thread safe as no internal data structures should change
......@@ -224,7 +212,7 @@ LocalFileWindows::xx_iscloud() const
void
LocalFileWindows::xx_read(void *data, std::int64_t offset, std::int64_t size, UsageHint usagehint)
{
SimpleTimer tt(*_rtimer, timers_on());
SimpleTimerEx tt(*_rtimer);
_validate_read(data, offset, size, xx_eof(), _mode);
// On windows, _read deals with int32 size so the cast warning
// technically correct. In practice we never read that much in one go.
......@@ -262,7 +250,7 @@ LocalFileWindows::xx_readv(const ReadList& requests, bool parallel_ok, bool immu
void
LocalFileWindows::xx_write(const void* data, std::int64_t offset, std::int64_t size, UsageHint usagehint)
{
SimpleTimer tt(*_wtimer, timers_on());
SimpleTimerEx tt(*_wtimer);
_validate_write(data, offset, size, _mode);
// On windows, _write deals with int32 size so the compiler warning is
// technically correct. In practice we never read that much in one go.
......
......@@ -18,7 +18,7 @@
#include "lodsampling.h"
#include "roundandclip.h"
#include "databuffer.h"
#include "timer.h"
#include "fancy_timers.h"
#include "environment.h"
#include "../exception.h"
......@@ -36,14 +36,6 @@ namespace InternalZGY {
}
#endif
namespace {
static bool timers_on()
{
static int enable = Environment::getNumericEnv("OPENZGY_TIMERS", 0);
return enable > 0;
}
}
/**
* \brief Weighted arithmetic average of 8 neighboring samples.
*
......@@ -871,8 +863,8 @@ void createLodST(const std::shared_ptr<DataBuffer>& result,
double histogram_min,
double histogram_max)
{
static SummaryPrintingTimer timer("createLod");
SimpleTimer tt(timer, timers_on());
static SummaryPrintingTimerEx timer("createLod");
SimpleTimerEx tt(timer);
switch (result->datatype()) {
case RawDataType::SignedInt8: createLodT<std::int8_t> (result, input, algorithm, hist, bincount, histogram_min, histogram_max); break;
case RawDataType::UnsignedInt8: createLodT<std::uint8_t> (result, input, algorithm, hist, bincount, histogram_min, histogram_max); break;
......@@ -974,8 +966,8 @@ void createLodMT(const std::shared_ptr<DataBuffer>& result,
double histogram_min,
double histogram_max)
{
static SummaryPrintingTimer timerST("createLod[ST]");
static SummaryPrintingTimer timerMT("createLod[MT]");
static SummaryPrintingTimerEx timerST("createLod[ST]");
static SummaryPrintingTimerEx timerMT("createLod[MT]");
const auto isize = input->size3d();
const auto istride = input->stride3d();
const auto ostride = result->stride3d();
......@@ -992,7 +984,7 @@ void createLodMT(const std::shared_ptr<DataBuffer>& result,
// as updating a byte might be implemented as read/modify/write of
// 4 or 8 bytes. So, always slice the slowest dim.
if (input_slice_dim != -1 && input_slice_dim == output_slice_dim) {
SimpleTimer tt(timerMT, timers_on());
SimpleTimerEx tt(timerMT);
std::atomic<int> errors(0);
std::string first_error;
#pragma omp parallel
......@@ -1024,7 +1016,7 @@ void createLodMT(const std::shared_ptr<DataBuffer>& result,
throw OpenZGY::Errors::ZgyInternalError(first_error);
}
else {
SimpleTimer tt(timerST, timers_on());
SimpleTimerEx tt(timerST);
createLodST(result, input, algorithm,
hist, bincount, histogram_min, histogram_max);
}
......
......@@ -24,7 +24,7 @@
*/
#include "../api.h"
#include "../impl/timer.h"
#include "../impl/fancy_timers.h"
#include "../test/mock.h"
#include "../impl/environment.h"
#include "../iocontext.h"
......@@ -52,11 +52,8 @@
#undef HAVE_GETOPT
#endif
using InternalZGY::Timer;
using InternalZGY::PrintingTimer;
using InternalZGY::SummaryTimer;
using InternalZGY::SummaryPrintingTimer;
using InternalZGY::SimpleTimer;
using InternalZGY::SummaryPrintingTimerEx;
using InternalZGY::SimpleTimerEx;
using InternalZGY::Environment;
using OpenZGY::SeismicStoreIOContext;
......@@ -592,15 +589,16 @@ void copychunkT(
const std::array<std::int64_t,3>& chunksize,
const std::array<std::int64_t,3>& surveysize,
T *buffer,
SummaryTimer& rtimer, SummaryTimer& wtimer)
SummaryPrintingTimerEx& rtimer, SummaryPrintingTimerEx& wtimer)
{
const std::array<std::int64_t,3> realsize =
minimum(chunksize, sub(surveysize, pos));
if (realsize[0] > 0 && realsize[1] > 0 && realsize[2] > 0) {
//std::cout << "copying (" << pos[0] << "," << pos[1] << "," << pos[2] << ")\n";
{
SimpleTimer rt(rtimer);
SimpleTimerEx rt(rtimer);
r->read(pos, realsize, buffer, 0);
rtimer.addBytesRead(realsize[0]*realsize[1]*realsize[2]);
}
{
// OpenZGY will also use an exclusive lock for writes.
......@@ -609,8 +607,9 @@ void copychunkT(
// useful in the multithreaded case.
static std::mutex mutex;
std::lock_guard<std::mutex> lk(mutex);
SimpleTimer wt(wtimer);
SimpleTimerEx wt(wtimer);
w->write(pos, realsize, buffer);
wtimer.addBytesWritten(realsize[0]*realsize[1]*realsize[2]);
}
}
}
......@@ -622,7 +621,7 @@ void copychunk(
const std::array<std::int64_t,3>& chunksize,
const std::array<std::int64_t,3>& surveysize,
void *buffer, OpenZGY::SampleDataType dt,
SummaryTimer& rtimer, SummaryTimer& wtimer)
SummaryPrintingTimerEx& rtimer, SummaryPrintingTimerEx& wtimer)
{
switch (dt) {
case OpenZGY::SampleDataType::int8:
......@@ -695,7 +694,7 @@ suggestRange(float value, OpenZGY::SampleDataType dt, float *lo, float *hi)
}
void
copy(const Options& opt, SummaryPrintingTimer& rtimer, SummaryPrintingTimer& wtimer, SummaryPrintingTimer& rwtimer, SummaryPrintingTimer& ftimer, SummaryPrintingTimer& stimer)
copy(const Options& opt, SummaryPrintingTimerEx& rtimer, SummaryPrintingTimerEx& wtimer, SummaryPrintingTimerEx& rwtimer, SummaryPrintingTimerEx& ftimer, SummaryPrintingTimerEx& stimer)
{
using namespace OpenZGY;
ProgressWithDots p1, p2;
......@@ -838,7 +837,7 @@ copy(const Options& opt, SummaryPrintingTimer& rtimer, SummaryPrintingTimer& wti
std::atomic<int> errors(0);
std::string first_error;
SimpleTimer rwt(rwtimer);
SimpleTimerEx rwt(rwtimer);
#pragma omp parallel num_threads(opt.threads) if (opt.threads > 1)
{
if (opt.verbose >= 3 && omp_get_thread_num() == 0)
......@@ -901,7 +900,7 @@ copy(const Options& opt, SummaryPrintingTimer& rtimer, SummaryPrintingTimer& wti
r.reset();
if (opt.nolod) {
SimpleTimer ft(ftimer, !opt.output.empty());
SimpleTimerEx ft(ftimer);
w->close_incomplete();
}
else {
......@@ -913,7 +912,7 @@ copy(const Options& opt, SummaryPrintingTimer& rtimer, SummaryPrintingTimer& wti
// Don't report timing for finalizing a mocked output file.
// Yes it does actually have a (tiny) cost but the user won't
// expect to see finalize reported at all when discarding the output.
SimpleTimer ft(ftimer, !opt.output.empty());
SimpleTimerEx ft(ftimer);
w->finalize(opt.algorithm, std::ref(p2));
w->close();
// If Timer logging is also enabled inside OpenZGY there will now
......@@ -938,7 +937,7 @@ copy(const Options& opt, SummaryPrintingTimer& rtimer, SummaryPrintingTimer& wti
// trouble. A machine running benchmarks shouldn't have other
// activity anyway.
if (!opt.output.empty() && opt.output.substr(0,5) != "sd://") {
SimpleTimer stim(stimer);
SimpleTimerEx stim(stimer);
sync();
}
#endif
......@@ -1014,13 +1013,13 @@ int main(int argc, char **argv)
if (options.dropcache)
system("/usr/local/bin/dropcache");