diff --git a/source/lib/bits.h b/source/lib/bits.h index be203cc8d9..094fa34496 100644 --- a/source/lib/bits.h +++ b/source/lib/bits.h @@ -152,6 +152,9 @@ inline bool is_pow2(T n) return (n & (n-1)) == 0; } +// as above; intended for use in static_assert +#define IS_POW2(n) (((n) != 0) && ((n) & ((n)-1)) == 0) + template inline T LeastSignificantBit(T x) { @@ -165,6 +168,7 @@ inline T ClearLeastSignificantBit(T x) return x & (x-1); } + /** * ceil(log2(x)) * @@ -186,6 +190,26 @@ inline size_t ceil_log2(T x) return log; } +// compile-time variant of the above +template +struct CeilLog2 +{ + enum { value = 1 + CeilLog2<(N+1)/2>::value }; +}; + +template<> +struct CeilLog2<1> +{ + enum { value = 0 }; +}; + +template<> +struct CeilLog2<0> +{ + enum { value = 0 }; +}; + + /** * floor(log2(f)) diff --git a/source/lib/file/io/io.h b/source/lib/file/io/io.h index 4510ca0a86..e0f68a9423 100644 --- a/source/lib/file/io/io.h +++ b/source/lib/file/io/io.h @@ -223,6 +223,10 @@ LIB_API Status WaitUntilComplete(aiocb& cb, size_t queueDepth); //----------------------------------------------------------------------------- // Run +#ifndef ENABLE_IO_STATS +#define ENABLE_IO_STATS 0 +#endif + // (hooks must be passed by const reference to allow passing rvalues. // functors with non-const member data can mark them as mutable.) template @@ -233,6 +237,11 @@ static inline Status Run(const Operation& op, const Parameters& p = Parameters() ControlBlockRingBuffer controlBlockRingBuffer(op, p); +#if ENABLE_IO_STATS + const double t0 = timer_Time(); + COMPILER_FENCE; +#endif + const off_t numBlocks = p.blockSize? (off_t)DivideRoundUp((u64)op.size, (u64)p.blockSize) : 1; for(off_t blocksIssued = 0, blocksCompleted = 0; blocksCompleted < numBlocks; blocksCompleted++) { @@ -256,6 +265,13 @@ static inline Status Run(const Operation& op, const Parameters& p = Parameters() RETURN_STATUS_FROM_CALLBACK(completedHook((u8*)cb.aio_buf, cb.aio_nbytes)); } +#if ENABLE_IO_STATS + COMPILER_FENCE; + const double t1 = timer_Time(); + const off_t totalSize = p.blockSize? numBlocks*p.blockSize : op.size; + debug_printf(L"IO: %.2f MB/s (%.2f)\n", totalSize/(t1-t0)/1e6, (t1-t0)*1e3); +#endif + return INFO::OK; }