位置: 文档库 > C#(.NET) > 文档下载预览

《C#测试代码执行时间的方法.doc》

1. 下载的文档为doc格式,下载后可用word或者wps进行编辑;

2. 将本文以doc文档格式下载到电脑,方便收藏和打印;

3. 下载后的文档,内容与下面显示的完全一致,下载之前请确认下面内容是否您想要的,是否完整.

点击下载文档

C#测试代码执行时间的方法.doc

《C#测试代码执行时间的方法》

在C#开发中,性能优化是提升软件质量的关键环节。无论是算法优化、数据库查询调优还是第三方库的选择,都需要准确测量代码段的执行时间。本文将系统介绍C#中测试代码执行时间的多种方法,涵盖从基础到进阶的实用技术,帮助开发者快速定位性能瓶颈。

一、基础计时方法:Stopwatch类

System.Diagnostics.Stopwatch是.NET Framework中最常用的高精度计时工具,其核心优势在于:

  • 基于系统高分辨率性能计数器
  • 精度可达微秒级(取决于硬件)
  • 跨平台支持(.NET Core/.NET 5+)

1.1 基本用法

using System.Diagnostics;

var stopwatch = Stopwatch.StartNew();
// 待测试代码
for (int i = 0; i 

关键点说明:

  • StartNew()静态方法直接创建并启动计时器
  • ElapsedMilliseconds返回长整型毫秒数
  • Elapsed.TotalMilliseconds返回双精度浮点数,包含小数部分

1.2 高级用法

// 重置计时器
stopwatch.Reset();

// 手动控制启停
stopwatch.Start();
// 代码段1
stopwatch.Stop();

stopwatch.Restart(); // 相当于Reset()+Start()
// 代码段2
stopwatch.Stop();

// 获取刻度数(不受系统时间调整影响)
long ticks = stopwatch.ElapsedTicks;
const long ticksPerMs = Stopwatch.Frequency / 1000;
double ms = (double)ticks / ticksPerMs;

二、性能分析工具集成

对于复杂场景,Stopwatch可与Visual Studio性能分析器结合使用:

2.1 使用Performance Profiler

步骤:

  1. VS菜单:调试 > 性能分析器
  2. 选择"CPU使用率"分析
  3. 在代码中插入Stopwatch标记
[MethodImpl(MethodImplOptions.NoInlining)]
public static void BenchmarkMethod() {
    var sw = Stopwatch.StartNew();
    // 待测试逻辑
    sw.Stop();
    Debug.WriteLine($"Method耗时: {sw.ElapsedMilliseconds}ms");
}

2.2 诊断源API(.NET Core 3.0+)

using System.Diagnostics;
using System.Diagnostics.Tracing;

public class CodeTimer : EventSource {
    public static CodeTimer Log = new CodeTimer();
    
    [Event(1, Level = EventLevel.Informational)]
    public void CodeExecuted(string methodName, long elapsedMs) {
        WriteEvent(1, methodName, elapsedMs);
    }
}

// 使用示例
var sw = Stopwatch.StartNew();
// 测试代码
sw.Stop();
CodeTimer.Log.CodeExecuted("MyMethod", sw.ElapsedMilliseconds);

三、基准测试框架:BenchmarkDotNet

对于专业级性能测试,BenchmarkDotNet是行业标杆工具,提供:

  • 自动预热(JIT优化)
  • 多次运行取统计值
  • 内存分配分析
  • 多平台支持

3.1 基础配置

// 安装NuGet包:BenchmarkDotNet
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;

[MemoryDiagnoser]
public class StringConcatBenchmark {
    [Benchmark]
    public string PlusOperator() {
        string result = "";
        for (int i = 0; i ();
    }
}

3.2 高级配置

[Config(typeof(CustomConfig))]
public class AdvancedBenchmark {
    // 测试方法...
}

public class CustomConfig : ManualConfig {
    public CustomConfig() {
        Add(Job.MediumRun
            .WithLaunchCount(3)
            .WithWarmupCount(5)
            .WithTargetCount(10));
        
        Add(DefaultColumnProviders.Instance);
        Add(StatisticColumn.OperationsPerSecond);
    }
}

四、异步代码测试方法

测试async/await代码需要特殊处理:

4.1 Stopwatch的异步用法

public async Task AsyncOperation() {
    await Task.Delay(100);
    return 42;
}

[Fact]
public async Task MeasureAsyncMethod() {
    var sw = Stopwatch.StartNew();
    var result = await AsyncOperation();
    sw.Stop();
    
    Assert.True(sw.ElapsedMilliseconds >= 100);
}

4.2 BenchmarkDotNet的异步支持

[MemoryDiagnoser]
public class AsyncBenchmark {
    [Benchmark]
    public async Task AsyncMethod() {
        await Task.Delay(10);
        return "Done";
    }
    
    [Benchmark]
    public string SyncMethod() {
        Thread.Sleep(10);
        return "Done";
    }
}

五、多线程环境下的计时

在并发场景中需要注意:

5.1 线程安全计时

public class ConcurrentTimer {
    private readonly Stopwatch _stopwatch = Stopwatch.StartNew();
    private long _elapsedTicks;
    
    public void Record() {
        long current = _stopwatch.ElapsedTicks;
        Interlocked.Add(ref _elapsedTicks, current);
        _stopwatch.Restart();
    }
    
    public TimeSpan TotalElapsed => 
        TimeSpan.FromTicks(Interlocked.Read(ref _elapsedTicks));
}

5.2 Parallel.For的计时

var sw = Stopwatch.StartNew();
Parallel.For(0, 100000, i => {
    // 并行任务
});
sw.Stop();
Console.WriteLine($"并行耗时: {sw.ElapsedMilliseconds}ms");

六、实时性能监控

对于长期运行的服务,需要持续监控性能:

6.1 使用PerformanceCounter

using System.Diagnostics;

var pc = new PerformanceCounter(
    "Process", 
    "% Processor Time", 
    Process.GetCurrentProcess().ProcessName);

while (true) {
    float cpu = pc.NextValue();
    Console.WriteLine($"CPU使用率: {cpu}%");
    Thread.Sleep(1000);
}

6.2 自定义ETW事件

[EventSource(Name = "MyCompany-MyApp-Performance")]
public sealed class PerformanceEventSource : EventSource {
    public static PerformanceEventSource Log = new PerformanceEventSource();
    
    [Event(1, Message = "方法 {0} 执行耗时 {1}ms", Level = EventLevel.Informational)]
    public void MethodExecuted(string methodName, long elapsedMs) {
        WriteEvent(1, methodName, elapsedMs);
    }
}

// 使用
var sw = Stopwatch.StartNew();
// 测试代码
sw.Stop();
PerformanceEventSource.Log.MethodExecuted("CriticalPath", sw.ElapsedMilliseconds);

七、常见误区与最佳实践

1. 避免在计时循环中包含首次运行(JIT编译)

// 错误示例
var sw = Stopwatch.StartNew();
for (int i = 0; i 

2. 注意系统时钟调整影响

  • DateTime.Now可能受系统时间修改影响
  • 优先使用Stopwatch的ElapsedTicks

3. 内存分配影响

[MemoryDiagnoser]
public class MemoryBenchmark {
    [Benchmark]
    public void AllocateMany() {
        var list = new List();
        for (int i = 0; i 

八、跨平台计时方案

.NET Core/.NET 5+在不同操作系统上的计时实现:

8.1 Linux/macOS注意事项

  • Stopwatch依赖monotonic clock
  • 高精度取决于系统配置

8.2 容器环境中的计时

// 检查时钟源(Linux)
// cat /sys/devices/system/clocksource/clocksource0/current_clocksource

// 容器中建议使用环境变量控制
if (Environment.GetEnvironmentVariable("DOTNET_SYSTEM_TIMING") == "highres") {
    // 启用高精度模式
}

九、历史方法回顾与对比

1. DateTime结构体(不推荐)

var start = DateTime.Now;
// 测试代码
var end = DateTime.Now;
var elapsed = (end - start).TotalMilliseconds;
// 问题:精度只有约15ms,受系统时间调整影响

2. Environment.TickCount(32位)

int start = Environment.TickCount;
// 测试代码
int end = Environment.TickCount;
int elapsed = end - start;
// 问题:32位溢出风险,精度约15ms

3. System.Diagnostics.Process类

var proc = Process.GetCurrentProcess();
long start = proc.TotalProcessorTime.Ticks;
// 测试代码
long end = proc.TotalProcessorTime.Ticks;
// 测量的是CPU时间而非实际时间

十、完整示例:综合性能测试

using System;
using System.Diagnostics;
using System.Threading.Tasks;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;

public class ComprehensiveBenchmark {
    // Stopwatch基础测试
    public static long StopwatchTest() {
        var sw = Stopwatch.StartNew();
        Parallel.For(0, 10000, i => {
            var _ = Math.Sqrt(i);
        });
        sw.Stop();
        return sw.ElapsedMilliseconds;
    }

    // 异步测试
    public static async Task AsyncTest() {
        var sw = Stopwatch.StartNew();
        await Task.WhenAll(Enumerable.Range(0, 10)
            .Select(_ => Task.Run(() => {
                for (int i = 0; i  AsyncCalculation() {
            return await Task.Run(() => {
                int sum = 0;
                for (int i = 0; i ();
    }
}

关键词:C#性能测试、Stopwatch类、BenchmarkDotNet、异步代码计时、多线程计时、ETW事件、PerformanceCounter、跨平台计时、性能分析

简介:本文全面介绍C#中测试代码执行时间的多种方法,涵盖基础Stopwatch使用、BenchmarkDotNet高级框架、异步代码测试、多线程环境计时等场景,提供从简单到专业的完整解决方案,帮助开发者准确测量和优化代码性能。

《C#测试代码执行时间的方法.doc》
将本文以doc文档格式下载到电脑,方便收藏和打印
推荐度:
点击下载文档