int CInsertBuffer::Read(char* pBuf)
{
// TIMER NOTES: Avg Execution Time = ~1 ms
Timer timer("BufferRead");
: :
return -1;
}
输出示例:
Timer Precision = 418.0095 ps
=== Item Trials Ttl Time Avg Time Mean Time StdDev ===
AddTrade 500 7 ms 14 us 12 us 24 us
BufferRead 511 1:19.25 0.16 s 621 ns 2.48 s
BufferWrite 516 511 us 991 ns 482 ns 11 us
ImportPos Loop 1002 18.62 s 19 ms 77 us 0.51 s
ImportPosition 2 18.75 s 9.38 s 16.17 s 13.59 s
Insert 515 4.26 s 8 ms 5 ms 27 ms
recv 101 18.54 s 0.18 s 2603 ns 1.63 s
namespace std
{
/* ---
Formatted Print
template<class C>
int strprintf(basic_string<C>* pString, const C* pFmt, ...);
template<class C>
int vstrprintf(basic_string<C>* pString, const C* pFmt, va_list args);
Returns :
# characters printed to output
Effects :
Writes formatted data to a string. strprintf() works exactly the same as sprintf(); see your
documentation for sprintf() for details of peration. vstrprintf() also works the same as sprintf(),
but instead of accepting a variable paramater list it accepts a va_list argument.
Requires :
pString is a pointer to a basic_string<>
--- */
template<class char_type> int vprintf_generic(char_type* buffer, size_t bufferSize, const char_type* format, va_list argptr);
template<> inline int vprintf_generic<char>(char* buffer, size_t bufferSize, const char* format, va_list argptr)
{
# ifdef SECURE_VSPRINTF
return _vsnprintf_s(buffer, bufferSize-1, _TRUNCATE, format, argptr);
# else
return _vsnprintf(buffer, bufferSize-1, format, argptr);
# endif
}
template<> inline int vprintf_generic<wchar_t>(wchar_t* buffer, size_t bufferSize, const wchar_t* format, va_list argptr)
{
# ifdef SECURE_VSPRINTF
return _vsnwprintf_s(buffer, bufferSize-1, _TRUNCATE, format, argptr);
# else
return _vsnwprintf(buffer, bufferSize-1, format, argptr);
# endif
}
template<class Type, class Traits>
inline int vstringprintf(basic_string<Type,Traits> & outStr, const Type* format, va_list args)
{
// prologue
static const size_t ChunkSize = 1024;
size_t curBufSize = 0;
outStr.erase();
if( !format )
{
return 0;
}
// keep trying to write the string to an ever-increasing buffer until
// either we get the string written or we run out of memory
while( bool cont = true )
{
// allocate a local buffer
curBufSize += ChunkSize;
std::ref_ptr<Type> localBuffer = new Type[curBufSize];
if( localBuffer.get() == 0 )
{
// we ran out of memory -- nice goin'!
return -1;
}
// format output to local buffer
int i = vprintf_generic(localBuffer.get(), curBufSize * sizeof(Type), format, args);
if( -1 == i )
{
// the buffer wasn't big enough -- try again
continue;
}
else if( i < 0 )
{
// something wierd happened -- bail
return i;
}
// if we get to this point the string was written completely -- stop looping
outStr.assign(localBuffer.get(),i);
return i;
}
// unreachable code
return -1;
};
// provided for backward-compatibility
template<class Type, class Traits>
inline int vstrprintf(basic_string<Type,Traits> * outStr, const Type* format, va_list args)
{
return vstringprintf(*outStr, format, args);
}
template<class Char, class Traits>
inline int stringprintf(std::basic_string<Char, Traits> & outString, const Char* format, ...)
{
va_list args;
va_start(args, format);
int retval = vstringprintf(outString, format, args);
va_end(args);
return retval;
}
// old function provided for backward-compatibility
template<class Char, class Traits>
inline int strprintf(std::basic_string<Char, Traits> * outString, const Char* format, ...)
{
va_list args;
va_start(args, format);
int retval = vstringprintf(*outString, format, args);
va_end(args);
return retval;
}
/* ---
Inline Formatted Print
string strprintf(const char* Format, ...);
Returns :
Formatted string
Effects :
Writes formatted data to a string. formatstr() works the same as sprintf(); see your
documentation for sprintf() for details of operation.
--- */
template<class Char>
inline std::basic_string<Char> formatstr(const Char * format, ...)
{
std::string outString;
va_list args;
va_start(args, format);
vstringprintf(outString, format, args);
va_end(args);
return outString;
}
};
文件algorithmext.h(提供transform_if()函数):
/* ---
Transform
25.2.3
template<class InputIterator, class OutputIterator, class UnaryOperation, class Predicate>
OutputIterator transform_if(InputIterator first, InputIterator last, OutputIterator result, UnaryOperation op, Predicate pred)
template<class InputIterator1, class InputIterator2, class OutputIterator, class BinaryOperation, class Predicate>
OutputIterator transform_if(InputIterator first, InputIterator last, OutputIterator result, BinaryOperation binary_op, Predicate pred)
Requires:
T is of type EqualityComparable (20.1.1)
op and binary_op have no side effects
Effects :
Assigns through every iterator i in the range [result, result + (last1-first1)) a new corresponding value equal to one of:
1: op( *(first1 + (i - result))
2: binary_op( *(first1 + (i - result), *(first2 + (i - result))
Returns :
result + (last1 - first1)
Complexity :
At most last1 - first1 applications of op or binary_op
--- */
template<class InputIterator, class OutputIterator, class UnaryFunction, class Predicate>
OutputIterator transform_if(InputIterator first,
InputIterator last,
OutputIterator result,
UnaryFunction f,
Predicate pred)
{
for (; first != last; ++first)
{
if( pred(*first) )
*result++ = f(*first);
}
return result;
}
template<class InputIterator1, class InputIterator2, class OutputIterator, class BinaryOperation, class Predicate>
OutputIterator transform_if(InputIterator1 first1,
InputIterator1 last1,
InputIterator2 first2,
OutputIterator result,
BinaryOperation binary_op,
Predicate pred)
{
for (; first1 != last1 ; ++first1, ++first2)
{
if( pred(*first1) )
*result++ = binary_op(*first1,*first2);
}
return result;
}
#include <iostream>
#include <chrono>
int main() {
auto const t0 = std::chrono::steady_clock::now();
std::cout << "Hello world" << std::endl;
auto const t1 = std::chrono::steady_clock::now();
auto const us = std::chrono::duration_cast<std::chrono::microseconds>(t1-t0);
auto const ms = std::chrono::duration_cast<std::chrono::milliseconds>(t1-t0);
auto const s = std::chrono::duration_cast<std::chrono::seconds>(t1-t0);
std::cout << "time taken in s " << s.count() << std::endl;
std::cout << "time taken in ms " << ms.count() << std::endl;
std::cout << "time taken in us " << us.count() << std::endl;
}
输出:
Hello world
time taken in s 0
time taken in ms 0
time taken in us 30
8条答案
按热度按时间ef1yzkbh1#
这种方法有一些局限性,但我仍然觉得它很有用。我会把限制(我知道的)列在前面,让任何想使用它的人自己承担风险。
1.我发布的原始版本过多地报告了递归调用所花费的时间(正如对答案的评论中所指出的那样)。
1.它不是线程安全的,在我添加代码来忽略递归之前,它不是线程安全的,现在它更不安全了。
1.虽然如果调用多次(数百万次),它会非常有效,但它将对结果产生可测量的影响,因此您测量的范围将比您不测量的范围花费更长的时间。
当手头的问题不能证明分析我所有的代码是正确的,或者我从分析器中得到一些想要验证的数据时,我使用这个类。基本上,它总结了您在特定块中花费的时间,并在程序结束时将其输出到调试流(可以使用DbgView查看),包括代码执行的次数(当然还有平均花费的时间)。
vi4fp9gy2#
我通过创建两个类来创建配置文件:
cProfile
和cProfileManager
。cProfileManager
将保存从cProfile
产生的所有数据。cProfile
具有以下要求:cProfile
有一个初始化当前时间的构造函数。cProfile
有一个解构器,它将类的总存活时间发送给cProfileManager
为了使用这些配置文件类,我首先创建一个
cProfileManager
示例。然后,我将要分析的代码块放在花括号内。在花括号内,我创建了一个cProfile
示例。当代码块结束时,cProfile
会将代码块完成所用的时间发送给cProfileManager
。示例代码以下是代码示例(简化):
要使用
cProfile
,我会这样做:或者这个:
技术说明
这段代码实际上是对C++中作用域、构造函数和解构函数工作方式的滥用。
cProfile
只存在于块作用域(我们要测试的代码块)中。一旦程序离开块作用域,cProfile
就会记录结果。其他增强功能
示例:
define START_PROFILE cProfile Profile();{ #define END_PROFILE }
cProfileManager
可以检查一个代码块被调用了多少次。但是您需要代码块的标识符。第一增强可以帮助识别块。这在您想要分析的代码位于循环内部的情况下非常有用(如上面的第二个示例)。您还可以添加代码块所用的平均、最快和最长执行时间。t0ybt7op3#
请注意,以下内容都是专门为Windows编写的。
我还编写了一个计时器类来进行快速分析,它使用QueryPerformanceCounter()来获得高精度计时,但略有不同。当Timer对象福尔斯作用域时,我的timer类不会转储经过的时间。相反,它将经过的时间累积到一个集合中。我添加了一个静态成员函数Dump(),它创建了一个运行时间表,按计时类别(在Timer的构造函数中指定为字符串)排序沿着一些统计分析,如平均运行时间、标准差、最大值和最小值。我还添加了一个Clear()静态成员函数,它可以清除集合&让您重新开始。
如何使用Timer类(psudocode):
输出示例:
文件Timer.inl:
文件stringext.h(提供formatstr()函数):
文件algorithmext.h(提供transform_if()函数):
plicqrtu4#
我有两段代码。在pseudocode中,它们看起来像(这是一个简化版本,我实际上使用的是QueryPerformanceFrequency):
第一个片段:
第二段:
一点热键功夫,我可以说这段代码从我的CPU上偷走了多少时间。
cwxwcias5#
文章 Code profiler and optimizations 有很多关于C++代码分析的信息,还有一个免费的程序/类下载链接,可以向您展示不同代码路径/方法的图形演示。
pkln4tw66#
我有一个快速而肮脏的分析类,即使在最紧密的内部循环中也可以使用它进行分析。重点是极轻的重量和简单的代码。该类分配一个固定大小的二维数组。然后我在所有地方添加“检查点”呼叫。当检查点M之后立即到达检查点N时,我将经过的时间(以微秒为单位)添加到数组项[M,N]中。由于这是为了分析紧密循环而设计的,所以我还调用了“迭代开始”来重置“最后一个检查点”变量。在测试结束时,
dumpResults()
调用生成所有检查点对的列表,以及已考虑和未考虑的总时间。j8ag8udp7#
为此,我编写了一个简单的跨平台类nanotimer。目标是尽可能的轻量级,以便不会通过添加太多指令来干扰实际代码性能,从而影响指令缓存。它能够在windows、mac和linux(可能还有一些unix变种)上获得微秒级的精度。
基本用法:
start()也会在必要时重新启动计时器。“暂停”计时器可以通过存储经过的时间来实现,然后在“取消暂停”时重新启动计时器,并在下次检查经过的时间时添加到存储的结果中。
drnojrws8#
在C++11中,chrono头文件提供了许多有用的定时函数。因此,您可以度量代码的特定部分并将其转换为适当的度量,例如。秒或毫秒。
输出: