我在C#中写了一个天真的Parallel.For()循环,如下所示.我也使用常规for()循环来做同样的工作来比较单线程和多线程.每次运行它时,单线程版本大约需要五秒钟.并行版本最初花了大约三秒钟,但如果我运行它大约四次,它会急剧减速.大多数情况下大约需要30秒.有一次花了八十秒.如果我重新启动程序,并行版本将再次快速启动,但在三次或四次并行运行后减速.有时并行运行将再次加速到原来的三秒然后减速.
我编写了另一个用于计算Mandelbrot集合成员的Parallel.For()循环(丢弃结果)因为我认为问题可能与分配和操作大型数组的内存问题有关.第二个问题的Parallel.For()实现确实每次都比单线程版本执行得更快,并且时间也是一致的.
我应该了解哪些数据才能理解为什么我的第一个天真程序在经过多次运行后会变慢?Perfmon中有什么东西我应该看一下吗?我仍然怀疑它与内存有关,但我在定时器外部分配数组.我还在每次运行结束时尝试了一个GC.Collect(),但这似乎没有帮助,反正也不一致.可能是处理器某处的缓存对齐问题?我怎么知道这个?还有什么可能是原因吗?
JR
const int _meg = 1024 * 1024;
const int _len = 1024 * _meg;
private void ParallelArray() {
int[] stuff = new int[_meg];
System.Diagnostics.Stopwatch s = new System.Diagnostics.Stopwatch();
lblStart.Content = DateTime.Now.ToString();
s.Start();
Parallel.For(0,
_len,
i => {
stuff[i % _meg] = i;
}
);
s.Stop();
lblResult.Content = DateTime.Now.ToString();
lblDiff.Content = s.ElapsedMilliseconds.ToString();
}
Run Code Online (Sandbox Code Playgroud) 我们有一个内部开发的日志系统,我们希望获得log4net的好处,例如能够同时使用多个appender.我们决定将旧的日志记录系统转移到自定义的log4net appender中.当遗留系统配置正确时,这很有效,但遗留记录器实际上写入了WCF客户端(使得详细日志记录变慢,我们想要使用其他log4net appender的原因),最近WCF配置不是很好本来应该.当发生这种情况时,应用程序似乎运行正常,但显然遗留系统的自定义appender无法正常工作.其他appender工作正常,但自定义旧版appender没有输出,也没有错误消息表明存在问题.
处理"递归"日志记录的正确方法是什么,即从自定义log4net appender内部进行日志记录?我尝试了一个天真的解决方案:从静态对象抓取log4net并在appender中记录:
public class MyCustomAppender : AppenderSkeleton
{
protected override void Append(log4net.Core.LoggingEvent loggingEvent)
{
try
{
// something which throws here...
}
catch (Exception ex)
{
log4net.LogManager.GetLogger(this.GetType()).Error(this.GetType().ToString() + ": error during append", ex);
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个严重的失败,"System.Threading.LockRecursionException:在这种模式下不允许递归读取锁定." 很公平; 这是天真的解决方案.
我也尝试过:
this.ErrorHandler.Error(this.GetType().ToString() + ": error during append", ex);
Run Code Online (Sandbox Code Playgroud)
在异常处理程序中,因为它似乎可能是正确的.什么都不明显.
有没有办法在appender中通过log4net记录错误?或者我是否必须直接执行类似硬编码写入Windows事件日志的操作?显然存在无限递归下降的巨大危险,但我认为会有一些方法让操作员知道其中一个appender无法运行.
JR