C#中Stopwatch类实现精确代码执行时间测量的两种方案
C#中Stopwatch类实现精确代码执行时间测量
在C#开发中,精确测量代码执行时间对于性能优化和算法对比至关重要。本文将介绍如何使用System.Diagnostics.Stopwatch类实现高精度的执行时间测量,并提供基础用法和进阶实现两种方案。
基础Stopwatch用法
Stopwatch类提供了简单直接的时间测量方式,适用于单次操作耗时分析。
using System;
using System.Diagnostics;
class Program
{
static void Main()
{
var stopwatch = Stopwatch.StartNew();
// 模拟耗时操作
for (int i = 0; i < 1000000; i++) { }
stopwatch.Stop();
Console.WriteLine($"基础用法 - 执行时间: {stopwatch.ElapsedMilliseconds}ms");
Console.WriteLine($"精确时间: {stopwatch.Elapsed.TotalSeconds:F6}秒");
}
}关键API说明:
StartNew():创建并立即启动计时器Stop():停止计时ElapsedMilliseconds:获取毫秒级耗时Elapsed.TotalSeconds:获取精确到秒的小数
进阶计时器实现
对于需要多次测量和统计平均值的场景,可以封装CodeTimer类实现更复杂的功能。
using System;
using System.Collections.Generic;
using System.Diagnostics;
class CodeTimer
{
private Stopwatch _stopwatch = new Stopwatch();
private Queue<long> _timeRecords = new Queue<long>();
private long _totalTime;
private const int MaxRecords = 10;
public double AverageTimeMs => _timeRecords.Count > 0 ? _totalTime / (double)_timeRecords.Count : 0;
public void Start()
{
_stopwatch.Restart();
}
public void StopAndPrint(string operationName)
{
_stopwatch.Stop();
long elapsedMs = _stopwatch.ElapsedMilliseconds;
_timeRecords.Enqueue(elapsedMs);
_totalTime += elapsedMs;
if (_timeRecords.Count > MaxRecords)
{
_totalTime -= _timeRecords.Dequeue();
}
Console.WriteLine($"{operationName}: {elapsedMs}ms");
}
}进阶功能:
- 自动计算多次执行的平均时间
- 滑动窗口统计(默认保留最近10次记录)
- 方便的打印输出功能
两种方案对比
| 特性 | 基础方案 | 进阶方案 |
|---|---|---|
| 适用场景 | 单次操作耗时分析 | 多次执行统计/性能趋势分析 |
| 功能复杂度 | 低 | 高 |
| 内存占用 | 极低 | 中等(存储历史记录) |
| 输出信息 | 原始时间数据 | 格式化输出+统计值 |
最佳实践建议
- 测量环境准备:
- 关闭其他占用CPU的程序
- 在Release模式下运行
- 预热代码(首次运行可能较慢)
- 测量精度控制:
- 避免在测量代码中包含I/O操作
- 测量足够长的操作(>1ms)
- 多次测量取平均值
- 结果分析:
- 关注时间变化趋势而非绝对值
- 对比不同实现时使用相同测试环境
- 记录测试时的系统负载情况
以下内容为补充知识,需要的朋友拿去用。
C# 减少代码运行时间的7 个实战技巧
前言
想象一下,你正在一家忙碌的咖啡馆里工作,顾客络绎不绝,你不停地跑前跑后,累得直喘气。
如果你能同时准备几杯咖啡,效率是不是会大大提高?
这就是并发编程的魅力所在。
今天,我们就来聊聊 C# 中的 Task,看看它是如何帮助我们在代码中实现“多任务并行”的奇迹。
1. Task.Run:简单高效的启动方式
// 使用 Task.Run 来快速启动一个后台任务
Task.Run(() =>
{
Console.WriteLine($"任务运行在线程 {Thread.CurrentThread.ManagedThreadId}");
Thread.Sleep(1000); // 模拟耗时操作
Console.WriteLine("任务完成!");
});解释:这是最常用的启动异步任务的方法,适合执行一些不需要立即返回结果的操作。
2. Task.Factory.StartNew:灵活应对各种需求
// 使用 Task.Factory.StartNew 来处理长时间运行的任务
Task.Factory.StartNew(() =>
{
Console.WriteLine($"任务运行在线程 {Thread.CurrentThread.ManagedThreadId}");
// 模拟CPU密集型计算
for (int i = 0; i < 1000000; i++) {}
}, TaskCreationOptions.LongRunning); // 提示这是一个长任务提示:对于需要较长时间才能完成的任务,这种方式可以提供更多的控制选项。
3. new Task:手动管理任务
var task = new Task(() =>
{
Console.WriteLine($"任务运行在线程 {Thread.CurrentThread.ManagedThreadId}");
File.WriteAllText("test.txt", "Hello Task!");
});
task.Start(); // 需要手动启动任务注意:虽然这种方法提供了对任务生命周期的完全控制,但在大多数情况下,推荐使用更简便的方式。
4. 多任务并行处理
var tasks = new List<Task>();
for (int i = 0; i < 5; i++)
{
int taskId = i; // 避免闭包陷阱
tasks.Add(Task.Run(() =>
{
Console.WriteLine($"任务{taskId}开始执行");
Thread.Sleep(1000 * (taskId + 1));
Console.WriteLine($"任务{taskId}完成");
}));
}
await Task.WhenAll(tasks); // 等待所有任务完成
Console.WriteLine("所有任务都完成了!");小贴士:合理利用多任务并行处理,可以大幅缩短程序的执行时间。
5. 带返回值的任务
Task<int> fibonacciTask = Task.Run(() =>
{
int Fib(int n) => n <= 1 ? n : Fib(n - 1) + Fib(n - 2);
return Fib(35); // 计算斐波那契数列第35项
});
Console.WriteLine("正在拼命计算中...");
int result = await fibonacciTask;
Console.WriteLine($"计算结果: {result}");亮点:通过返回值,你可以轻松地在异步任务完成后获取其结果。
6. 任务链式调用
Task.Run(() =>
{
Console.WriteLine("第一阶段:数据准备");
return"原始数据";
})
.ContinueWith(previousTask =>
{
Console.WriteLine($"第二阶段:处理 {previousTask.Result}");
return$"处理后的-{previousTask.Result}";
})
.ContinueWith(previousTask =>
{
Console.WriteLine($"第三阶段:存储 {previousTask.Result}");
File.WriteAllText("data.txt", previousTask.Result);
});好处:链式调用不仅能让代码看起来更整洁,还能确保各阶段按顺序执行。
总结
恭喜你,现在你应该已经掌握了使用 Task 进行多线程编程的基础知识和一些高级技巧。
记住,实践是检验真理的唯一标准。
到此这篇关于C#中Stopwatch类实现精确代码执行时间测量的两种方案的文章就介绍到这了,更多相关C# Stopwatch类代码执行时间测量内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
C#使用Spire.Doc for .NET模板化生成Word文档的实践指南
在日常工作中,你是否曾被海量的Word文档处理任务所困扰,本文将深入探讨如何利用 Spire.Doc for .NET 这个利器实现Word文档自动化生成吧2026-01-01


最新评论