- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在对一个 IIS 应用程序进行一些性能/可扩展性测试,该应用程序在生产环境中有时似乎会慢下来。我能够使用 NUnit 始终如一地重现缓慢。
CPU 和内存在测试期间或在生产中出现缓慢时不会出现峰值。我强烈怀疑应用程序正在遭受线程饥饿,因为它似乎不是 CPU、内存、I/O 或数据库访问导致瓶颈的原因。我确实看到了线程饥饿的迹象;似乎;例如,NLog 的异步日志文件写入往往会出现长时间的静默,然后是带有较旧时间戳的事件爆发(即,优先级较低的线程正在等待线程释放以便写入)。
我可以采取哪些步骤来明确确定应用程序确实线程匮乏,并且(假设是这种情况)查明导致问题的系统的确切区域?
编辑
我没有提到几乎所有代码都是同步的(这是一个遗留系统)。
最佳答案
根据 Sinatr 的评论,我阅读了 ThreadPool.SetMinThreads 和 TaskCreationOptions.LongRunning,包括对 When to use TaskCreationOptions.LongRunning? 的回答。
将 MinThreads 设置为更高的默认值对我的情况产生了巨大的影响。我创建了一个简单的后台进程,以查看 ThreadPool 中的可用线程在测试运行过程中是否发生了显着变化并超过了 MinThreads 值(确实如此)。
这是我用来诊断的一些代码。这不适用于生产用途,此处显示的线程使用情况报告只会在它们最初增加时才有意义。另请注意,定时器在结束时需要一个线程,因此也需要等待一个可用的线程。
静态变量:
private static Timer _timer;
private static int _lastActiveThreads;
private static int _lastAvailableThreads;
private static int _maxThreads;
private static int _minThreads;
启动时运行:
int completionPortThreads;
ThreadPool.GetMaxThreads(out _maxThreads, out completionPortThreads);
ThreadPool.GetMinThreads(out _minThreads, out completionPortThreads);
_timer = new Timer
{
AutoReset = true,
Interval = 500,
};
_timer.Elapsed += TimerElasped;
_timer.Start();
经过的方法:
private static void TimerElasped(object sender, ElapsedEventArgs e)
{
int minWorkerThreads;
int availWorkerThreads;
int completionPortThreads;
ThreadPool.GetMinThreads(out minWorkerThreads, out completionPortThreads);
ThreadPool.GetAvailableThreads(out availWorkerThreads, out completionPortThreads);
var activeThreads = _maxThreads - availWorkerThreads;
if (availWorkerThreads != _lastAvailableThreads)
{
_lastAvailableThreads = availWorkerThreads;
if (activeThreads > _lastActiveThreads)
{
_lastActiveThreads = activeThreads;
Logger.Log($"+++++ Active Threads is now: {activeThreads}");
if (activeThreads > _minThreads)
{
var diff = activeThreads - _minThreads;
Logger.Log($"+++++ Active threads is now {activeThreads}, which is {diff} more than minThread value of {_minThreads}. This may be causing delays.");
}
}
}
}
关于c# - 检测/诊断线程饥饿,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45036635/
考虑以下服务器: public class TestServer { public static void main(String[] args) { String ksName = "/so
我正在研究工作队列处理器的设计,其中 QueueProcessor 从队列中检索命令模式对象并在新线程中执行它。 我正在尝试解决嵌套命令可能导致死锁的潜在队列锁定场景。 例如 一个 FooComman
通过使用 UNIX 管道进行进程同步,我们是否会陷入饥饿?例如: void pipesem_wait(struct pipesem *sem) { char onebyte = 'A';
这是使用 Scala 2.8 Actors。我有一个可以并行化的长时间运行的工作。它由大约 650,000 个工作单元组成。我将它分成 2600 个不同的独立子任务,并为每个子任务创建一个新角色: a
回答问题:Task.Yield - real usages?我建议使用 Task.Yield 允许池线程被其他任务重用。在这样的模式中: CancellationTokenSource cts;
我是一名优秀的程序员,十分优秀!