/// <summary> /// 使用多线程并发的方式执行 <paramref name="action"/>,并使用 <paramref name="output"/> 方法输出 : 方法的运行时间, Cpu 时钟周期, 各代垃圾收集的回收次数的统计. /// </summary> /// <param name="name">名称.</param> /// <param name="iteration">循环次数.</param> /// <param name="threadCount">线程的计数.</param> /// <param name="mockThinkTime">模拟思考的时间.</param> /// <param name="action">需要执行的方法体.</param> /// <param name="output">要写入的输出流.</param> /// <remarks>一个 <see cref="CodeTimerResult"/> 表示执行的结果.</remarks> static public List<CodeTimerResult> Time(String name, Int32 iteration, Int32 threadCount, Int32 mockThinkTime, Action action, Action<String> output) { if (name == null) name = String.Empty; if (mockThinkTime < 0) throw new ArgumentOutOfRangeException("thinkTime", CodeTimerString.MessageThan0); List<CodeTimerResult> results = new List<CodeTimerResult>(threadCount); CodeTimerResult totalResult = new CodeTimerResult(); ManualResetEvent manualResetEvent = new ManualResetEvent(true); // 主线程控制信号 ManualResetEvent threadResetEvent = new ManualResetEvent(true); // 子线程线程控制信号 Int32 currentThreadIndex; // 当前线程索引值 for (Int32 repeat = 0; repeat < iteration; repeat++) { manualResetEvent.Reset(); // 主线程进入阻止状态 threadResetEvent.Reset(); // 子线程进入阻止状态 currentThreadIndex = 0; for (Int32 i = 0; i < threadCount; i++) { Thread thread = new Thread( (threadIndex) => { CodeTimerResult TimeResult = new CodeTimerResult(); Interlocked.Increment(ref currentThreadIndex); if (currentThreadIndex < threadCount) { threadResetEvent.WaitOne(); // 等待所有线程创建完毕后同时执行测试 } else { threadResetEvent.Set(); // 最后一个线程创建完成,通知所有线程,开始执行测试 } // 执行测试,委托给 SingleThreadTime 方法来做. TimeResult = Time( String.Format( CodeTimerString.ChildThreadName, name, threadIndex, CodeTimerString.NameSuffix ), 1, action, null ); Interlocked.Decrement(ref currentThreadIndex); if (currentThreadIndex == 0) { results.Add(TimeResult); // 保存执行结果 manualResetEvent.Set(); //通知主线程继续 } else { results.Add(TimeResult); // 保存执行结果 } } ); thread.Start(i); } // 阻止主线程,等待子线程完成所有任务. manualResetEvent.WaitOne(); Thread.Sleep(mockThinkTime); } totalResult.Name = String.Format(CodeTimerString.MultiThreadName, name, CodeTimerString.NameSuffix); results.ForEach( (item) => { totalResult.TimeElapsed += item.TimeElapsed; totalResult.CPUCycles += item.CPUCycles; for (Int32 i = 0; i < totalResult.GenerationList.Length; i++) { totalResult.GenerationList[i] += item.GenerationList[i]; } } ); totalResult.ThreadCount = threadCount; totalResult.Iteration = iteration; Print(totalResult, output); // 释放资源 manualResetEvent.Close(); threadResetEvent.Close(); return results; }
public ICounterStopSpecification Do(Action action) { CodeTimer.Init(); _CodeTimerResult = CodeTimer.Time(_Name, _Iteration, action, null); return this; }
/// <summary> /// 使用单线程的方式执行 <paramref name="action"/>,并使用 <paramref name="output"/> 方法输出 : 方法的运行时间, Cpu 时钟周期, 各代垃圾收集的回收次数的统计. /// </summary> /// <param name="name">名称.</param> /// <param name="iteration">循环次数.</param> /// <param name="action">需要执行的方法体.</param> /// <param name="output">要写入的输出流.</param> /// <remarks>一个 <see cref="CodeTimerResult"/> 表示执行的结果.</remarks> static public CodeTimerResult Time(String name, Int32 iteration, Action action, Action<String> output) { if (name == null) name = String.Empty; if (action == null) { return null; } CodeTimerResult result = new CodeTimerResult(); #region 强制 GC 进行收集,并记录目前各代已经收集的次数. GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced); Int32[] gcCounts = new Int32[GC.MaxGeneration + 1]; for (Int32 i = 0; i <= GC.MaxGeneration; i++) { gcCounts[i] = GC.CollectionCount(i); } #endregion 强制 GC 进行收集,并记录目前各代已经收集的次数. #region 执行代码,记录下消耗的时间及 CPU 时钟周期. Stopwatch watch = new Stopwatch(); watch.Start(); UInt64 cycleCount = GetCycleCount(); for (Int32 i = 0; i < iteration; i++) { action(); } UInt64 cpuCycles = GetCycleCount() - cycleCount; watch.Stop(); #endregion 执行代码,记录下消耗的时间及 CPU 时钟周期. #region 收集数据 result.Name = String.Format(CodeTimerString.SingleThreadName, name, CodeTimerString.NameSuffix); result.TimeElapsed = watch.ElapsedMilliseconds; result.CPUCycles = cpuCycles; for (Int32 i = 0; i <= GC.MaxGeneration; i++) { Int32 count = GC.CollectionCount(i) - gcCounts[i]; result.GenerationList[i] = count; } result.ThreadCount = 1; result.Iteration = iteration; Print(result, output); #endregion 收集数据 return result; }