计算时间差,你的方式或许不是最佳实践!

本文对比了使用System.currentTimeMillis()和System.nanoTime()进行代码执行时间测量的优劣,详细解析了两种方法的精度、稳定性和适用场景,推荐了更精确的时间测量方式。

 

我们计算两段代码时间差,很多同学公司的代码是采用以下这种方式。

long startTime = System.currentTimeMillis();
// 执行代码
long endTime = System.currentTimeMillis();
System.out.println(endTime - startTime);

首先先说明,这种方式并不是不行。按照“能跑就行”的原则,这段代码,肯定是能用的!但是这并不是最佳实践,为何?

我们先来看一下JDK中的注释

/**
 * Returns the current time in milliseconds.  Note that
 * while the unit of time of the return value is a millisecond,
 * the granularity of the value depends on the underlying
 * operating system and may be larger.  For example, many
 * operating systems measure time in units of tens of
 * milliseconds.
 *
 * <p> See the description of the class <code>Date</code> for
 * a discussion of slight discrepancies that may arise between
 * "computer time" and coordinated universal time (UTC).
 *
 * @return  the difference, measured in milliseconds, between
 *          the current time and midnight, January 1, 1970 UTC.
 * @see     java.util.Date
 */
public static native long currentTimeMillis();

当然,毕竟有的同学英文能力有限,那就只能用之前介绍的文档神器来开门见山了

 

 

 

虽然文中的每个字都认识,但是这段话想表达的意思你可能还是不太清楚,有句话叫做,不怕现实,就怕对比。那么我们来看另外一种方式。

long startTime = System.nanoTime();
// 执行代码
long endTime = System.nanoTime();
System.out.println(endTime - startTime);

同样的,我们再来看看注释

/**
 * Returns the current value of the running Java Virtual Machine's
 * high-resolution time source, in nanoseconds.
 *
 * <p>This method can only be used to measure elapsed time and is
 * not related to any other notion of system or wall-clock time.
 * The value returned represents nanoseconds since some fixed but
 * arbitrary <i>origin</i> time (perhaps in the future, so values
 * may be negative).  The same origin is used by all invocations of
 * this method in an instance of a Java virtual machine; other
 * virtual machine instances are likely to use a different origin.
 *
 * <p>This method provides nanosecond precision, but not necessarily
 * nanosecond resolution (that is, how frequently the value changes)
 * - no guarantees are made except that the resolution is at least as
 * good as that of {@link #currentTimeMillis()}.
 *
 * <p>Differences in successive calls that span greater than
 * approximately 292 years (2<sup>63</sup> nanoseconds) will not
 * correctly compute elapsed time due to numerical overflow.
 *
 * <p>The values returned by this method become meaningful only when
 * the difference between two such values, obtained within the same
 * instance of a Java virtual machine, is computed.
 *
 * <p> For example, to measure how long some code takes to execute:
 *  <pre> {@code
 * long startTime = System.nanoTime();
 * // ... the code being measured ...
 * long estimatedTime = System.nanoTime() - startTime;}</pre>
 *
 * <p>To compare two nanoTime values
 *  <pre> {@code
 * long t0 = System.nanoTime();
 * ...
 * long t1 = System.nanoTime();}</pre>
 *
 * one should use {@code t1 - t0 < 0}, not {@code t1 < t0},
 * because of the possibility of numerical overflow.
 *
 * @return the current value of the running Java Virtual Machine's
 *         high-resolution time source, in nanoseconds
 * @since 1.5
 */
public static native long nanoTime();

此时我们再拿出神器:

 

 

 

从文中的描述加代码示例,告诉我们:

 

 

 

还是那句话,不怕现实,就怕对比。就算你完全不懂代码,根据小学的语文理解,都能看出在计算代码执行时间差上,选哪个方式,才是最佳实践。

最后,我们再看一下阿里巴巴开发手册给我们的建议:

 

 

 

你的代码是怎么计算时间差的,欢迎留言。

<think>首先,用户的问题是:“我想测量C++程序的执行时间请问howtocalculateexecutiontimeofaC++program”。这是一个关于如何在C++中测量程序执行时间的问题。我需要确保我的回答遵循系统级指令:-所有行内数学表达式使用$...$格式。-独立公式使用$$...$$格式并单独成段。-LaTeX语法正确。-使用中文回答。-生成相关问题。-在回答中引用的段落末尾自然地添加引用标识。用户可见层指令:-回答结构清晰,帮助用户逐步解决问题。-保证回答真实可靠。参考站内引用:有[^1]、[^2]、[^3],但我需要基于用户的问题和我的知识来回答。用户的问题是关于C++的执行时间测量,而引用中提到了性能分析、并行化等,但并非直接相关。我应该尽可能参考用户的问题,而不是这些引用,因为它们似乎不直接匹配。用户上一次问题是关于C++执行时间,所以我应该直接回答。结构化回答:-介绍测量执行时间的重要性。-提供方法:使用C++标准库中的`<chrono>`头文件。-分步解释:如何记录开始时间、结束时间,并计算持续时间。-给出示例代码-讨论注意事项。-生成相关问题。生成相关问题:在回答结束后,列出相关问题。使用中文回答:整个回答用中文。数学表达式:可能不需要,但如果有计算,如时间差,可以用行内数学格式。例如,$duration=end-start$。引用标识:在回答中,如果有引用部分,添加引用标识。但这里,我没有外部引用,所以可能不需要添加。系统指令说“回答中引用的段落末尾自然地添加引用标识”,但我没有引用源,所以或许可以忽略,或基于提供的引用。提供的引用[^1]讨论了C++AMP的性能测量,提到了测量内核执行和复制操作的时间。我可以参考这个来提到性能分析。用户引用[^1]说:“InthissectionIwillapplywhatwehavelearned...andcalculatespeedup.”这涉及性能测量,我可以自然地融入。计划回答:1.简要解释为什么测量执行时间重要。2.描述使用`std::chrono`的方法。3.提供代码示例。4.讨论如何测量不同部分(如内核执行)。5.生成相关问题。代码示例:用C++代码展示如何测量。相关问题:例如:-如何测量特定函数执行时间?-如何在多线程环境中测量时间?-如何优化C++程序性能?确保回答真实可靠:基于标准C++知识。最终回答结构:-开头:直接回答问题。-主体:分步解释。-结尾:生成相关问题。</think>### 测量C++程序的执行时间 在C++中测量程序执行时间是性能分析和优化的基础步骤。这有助于识别瓶颈、比较算法效率,并确保代码高效运行。最推荐的方法是使用C++标准库中的`<chrono>`头文件,它提供了高精度计时器。下面我将分步解释如何实现,并提供一个完整的示例。 #### 方法步骤 1. **引入头文件**:包括`<chrono>`和`<iostream>`以使用计时和输出功能。 2. **记录开始时间**:使用`std::chrono::high_resolution_clock::now()`在代码关键点(如main函数开头)获取当前时间点。 3. **记录结束时间**:在代码执行结束后再次调用`now()`。 4. **计算持续时间**:用结束时间减去开始时间,得到时间差。单位为纳秒、毫秒或秒,可根据需要转换。 5. **输出结果**:将持续时间打印到控制台。 此方法利用了C++11及以上标准的特性,具有跨平台兼容性(Windows、Linux、macOS)和微秒级精度。 #### 示例代码 以下是一个简单示例,测量整个程序的执行时间: ```cpp #include <iostream> #include <chrono> // 引入chrono库 int main() { // 记录开始时间点 auto start = std::chrono::high_resolution_clock::now(); // 这里是待测代码(示例:一个简单循环) for (int i = 0; i < 1000000; i++) { // 模拟计算 double result = i * i; } // 记录结束时间点 auto end = std::chrono::high_resolution_clock::now(); // 计算持续时间(以毫秒为单位) auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start); // 输出执行时间 std::cout << "程序执行时间: " << duration.count() << " 毫秒" << std::endl; return 0; } ``` #### 关键注意事项 - **精度选择**:`std::chrono`支持不同时间单位。例如: - 毫秒:`std::chrono::milliseconds` - 微秒:`std::chrono::microseconds` - 纳秒:`std::chrono::nanoseconds` 在高性能场景中,推荐使用微秒或纳秒以获得更精细的测量。 - **测量部分代码**:如果您只想测量特定函数或代码块(如循环或算法内核),只需将开始和结束时间点放在该代码块的开头和结尾。这类似于性能分析工具的原理,能帮助隔离瓶颈[^1]。 - **避免干扰**:确保计时代码本身不引入显著开销。`<chrono>`的开销通常很小(纳秒级),但在极端优化场景中需考虑。 - **多线程环境**:在多线程程序中,测量整个程序时间可能不准确。建议结合线程局部存储或专用性能分析工具。 - **与其他方法对比**:旧方法(如`clock()`)精度较低,不推荐;`<chrono>`是现代C++的最佳实践。 在实际性能分析中,分离内核执行和内存复制等操作的时间能更精确地计算加速比(speedup),例如在并行算法优化时[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值