昨天对“黑色n秒”问题的最终猜想以失败而告终,从而让我们结束了被动猜想阶段,进入了主动进攻阶段——出招。

今天出第一招——用C#写个小程序,让其在每个CPU核上运行一个线程,不让任何一个CPU核进入空闲(idle)状态,以进一步排除CPU idle引起的“黑色n秒”。

在这一招中,借助的最重要的武器是System.Diagnostics.ProcessThread.ProcessorAffinity。通过给ProcessorAffinity设置一个掩码,就可以指定当前线程运行于哪个CPU核上。

如上图,用哪个核就把那个核对应的二进制位置1,其他位保持0。

所以对于我们所用的8核CPU,从第1核到第8核对应的ProcessorAffinity分别是:1, 2, 4, 8, 16, 32, 64, 128。

需要注意的地方是ProcessThread.ProcessorAffinity针对的是Windows操作系统线程,而.NET线程并不是与操作系统线程一一对应的,一个.NET线程可以运行于多个操作系统线程。所以,如果仅仅指定ProcessThread.ProcessorAffinity,并不能保证.NET线程运行于指定的CPU核上。那怎么办呢?

微软提供了解决方案,在设置ProcessThread.ProcessorAffinity之前需要通过下面的代码将.NET线程固定在操作系统线程上:

Thread.BeginThreadAffinity();

还有一个需要解决的问题是如何让一个线程一直处于执行状态,从而不让其所在的CPU核进入idle状态。微软也提供了解决方案,调用非托管方法SetThreadExecutionState(),代码如下:

NativeMethods.SetThreadExecutionState(NativeMethods.ES_CONTINUOUS | NativeMethods.ES_SYSTEM_REQUIRED);

下面请看招式:

代码第1部分:

class Program
{
static void Main(string[] args)
{
var threads = new Thread[Environment.ProcessorCount];
Console.WriteLine("Processor Count:" + Environment.ProcessorCount);
for (int i = ; i < threads.Length; i++)
{
var coreNumber = i + ;
var threaName = "ThreadOnCPU" + coreNumber;
var start = new ThreadStart(() =>
{
Console.WriteLine(threaName + " is working...");
NativeMethods.SetThreadExecutionState(
NativeMethods.ES_CONTINUOUS | NativeMethods.ES_SYSTEM_REQUIRED);
});
var thread = new DistributedThread(start);
thread.ProcessorAffinity = (int)Math.Pow(, i);
thread.ManagedThread.Name = threaName;
thread.Start();
}
Console.ReadKey();
}
} internal static class NativeMethods
{
[DllImport("kernel32.dll")]
public static extern uint SetThreadExecutionState(uint esFlags);
public const uint ES_CONTINUOUS = 0x80000000;
public const uint ES_SYSTEM_REQUIRED = 0x00000001;
}

代码第2部分(来自Running .NET threads on selected processor cores):

class DistributedThread
{
[DllImport("kernel32.dll")]
public static extern int GetCurrentThreadId(); [DllImport("kernel32.dll")]
public static extern int GetCurrentProcessorNumber(); private ThreadStart threadStart; private ParameterizedThreadStart parameterizedThreadStart; private Thread thread; public int ProcessorAffinity { get; set; } public Thread ManagedThread
{
get
{
return thread;
}
} private DistributedThread()
{
thread = new Thread(DistributedThreadStart);
} public DistributedThread(ThreadStart threadStart)
: this()
{
this.threadStart = threadStart;
} public DistributedThread(ParameterizedThreadStart threadStart)
: this()
{
this.parameterizedThreadStart = threadStart;
} public void Start()
{
if (this.threadStart == null) throw new InvalidOperationException(); thread.Start(null);
} public void Start(object parameter)
{
if (this.parameterizedThreadStart == null) throw new InvalidOperationException(); thread.Start(parameter);
} private void DistributedThreadStart(object parameter)
{
try
{
// fix to OS thread
Thread.BeginThreadAffinity(); // set affinity
if (ProcessorAffinity != )
{
CurrentThread.ProcessorAffinity = new IntPtr(ProcessorAffinity);
} // call real thread
if (this.threadStart != null)
{
this.threadStart();
}
else if (this.parameterizedThreadStart != null)
{
this.parameterizedThreadStart(parameter);
}
else
{
throw new InvalidOperationException();
}
}
finally
{
// reset affinity
CurrentThread.ProcessorAffinity = new IntPtr(0xFFFF);
Thread.EndThreadAffinity();
}
} private ProcessThread CurrentThread
{
get
{
int id = GetCurrentThreadId();
return
(from ProcessThread th in Process.GetCurrentProcess().Threads
where th.Id == id
select th).Single();
}
}
}

DistributedThread

接下来,出招——KeepAllCpuCoresAlive!

结果。。。这一招以失败告终!

(上图是“黑色1秒”发生时性能监视器监测到的ASP.NET Requests/Sec为0的情况)

失败又如何,就如同代码编译不通过一般不值一提。那为什么还要写博客出来呢?分享的就是过程!

接下来呢?准备第二招。。。

【参考资料】

Running .NET threads on selected processor cores

Threading in C#

Keep Alive the Machine - No Sleep

云计算之路-阿里云上:消灭“黑色n秒”第一招——不让CPU空闲的更多相关文章

  1. 云计算之路-阿里云上:“黑色1秒”问题与2009年Xen一个补丁的故事

    在之前对“黑色1秒”问题的分析博文中,我们将最大嫌疑对象锁定在了Xen,在这篇博文我们将从Xen的角度进行分析.也许有人会问,为什么不知道天多高地多厚地去研究不属于自己范围的问题?只因我们对一个问题的 ...

  2. 云计算之路-阿里云上:“黑色1秒”最新线索——w3tp与w3dt

    向大家分享一下最近排查“黑色1秒”问题的进展,“黑色1秒”的问题表现详见什么是黑色1秒. 1. 发生在w3wp进程内 判断依据:“黑色1秒”期间,http.sys的HTTP Service Reque ...

  3. 云计算之路-阿里云上:从ASP.NET线程角度对“黑色30秒”问题的全新分析

    在这篇博文中,我们抛开对阿里云的怀疑,完全从ASP.NET的角度进行分析,看能不能找到针对问题现象的更合理的解释. “黑色30秒”问题现象的主要特征是:排队的请求(Requests Queued)突增 ...

  4. 云计算之路-阿里云上:Web服务器遭遇奇怪的“黑色30秒”问题

    今天下午访问高峰的时候,主站的Web服务器出现奇怪的问题,开始是2台8核8G的云服务器(ECS),后来又加了1台8核8G的云服务器,问题依旧. 而且3台服务器特地使用了不同的配置:1台是禁用了虚拟内存 ...

  5. 云计算之路-阿里云上:原来“黑色0.1秒”发生在socket读取数据时

    在昨天的博文(云计算之路-阿里云上:读取缓存时的“黑色0.1秒”)中我们犯了一个很低级的错误——把13ms算成了130ms(感谢陈硕发现这个错误!),从而对问题的原因作出了错误的推断,望大家谅解! 从 ...

  6. 云计算之路-阿里云上:SLB会话保持的一个坑

    冒着被大家厌烦的风险,今天再发一篇“云计算之路-阿里云上”.这是在前一篇发过之后真实发生的事情,我们觉得定位问题的过程值得分享.而且估计园子里不少朋友被这个问题骚扰过,我们有责任让大家知道问题的真正原 ...

  7. 云计算之路-阿里云上-容器难容:容器服务故障以及自建 docker swarm 集群故障

    3月21日,由于使用阿里云服务器自建 docker swarm 集群的不稳定,我们将自建 docker swarm 集群上的所有应用切换阿里云容器服务 swarm 版(非swarm mode). 3月 ...

  8. 云计算之路-阿里云上-新发现:又一种与虚拟内存有关的CPU波动情况

    在云上真是无奇不有,昨天偶然间发现在IIS的应用程序池回收设置中,仅仅设置了一下基于虚拟内存限制的回收,就引发了CPU有规律的波动.在这篇博文中,我们将向大家汇报一下云计算之路上的这个小发现. 在之前 ...

  9. 云计算之路-阿里云上:启用Windows虚拟内存引发的CPU 100%故障

    今天上午11:35~11:40左右,由于负载均衡中的两台云服务器CPU占用突然飚至100%,造成网站5分钟左右不能正常访问,请大家带来了麻烦,请谅解! (上图中红色曲线表示CPU占用) 经过分析,我们 ...

随机推荐

  1. BCM_GPIO驱动测试

    在写内核驱动的时候,最好先在uboot上,进行裸板测试,验证寄存器,再移植到内核中,这样可以熟悉寄存器,也排除内核中的一些干扰. /********************************** ...

  2. Spring RestTemplate 小结

    关于RestTemplate 首先,你可以把它理解为一个发起请求并接收响应的工具类(功能类似浏览器). 其次,它其实是一个壳,具体还是通过调用别的接口来实现(如jdk自带的连接,或者HttpClien ...

  3. Linux中vi的使用

    首先,如果vi中出现了方向键变成ABCD的情况,需要卸载默认的vim-common,再安装vim. sudo apt-get remove vim-common sudo apt-get instal ...

  4. MFC HTTP GET 请求

    //HTTP GET 下载文件 CInternetSession *pInetSession = new CInternetSession(AfxGetAppName(),1,PRE_CONFIG_I ...

  5. otunnel : 一个和lcx差不多的端口转发的工具

    项目地址 ooclab/otunnel 下载地址(内涵各大平台) http://dl.ooclab.com/otunnel/ otunnel 用法 前提: 1. 假设 server 的地址为 exam ...

  6. mysql数据库,什么是数据库的全备份?

    需求描述: 今天要做mysql数据库的全备份,那么就要弄清楚一个概念,到底什么是数据库的全备份呢. 概念解释: 数据库的全备份,就是在一个给定的时间点,对于mysql服务器管理的所有的数据进行备份. ...

  7. windows,cmd中查看当前目录下的文件及文件夹

    需求描述: 在使用cmd的过程中,有的时候需要查看当前目录下有哪些文件或者文件夹,类似linux下的ls命令 操作过程: 1.通过dir命令查看当前目录下有哪些的文件及文件夹 备注:通过dir命令,就 ...

  8. python--dict和set类型--4

    原创博文,转载请标明出处--周学伟http://www.cnblogs.com/zxouxuewei/ 一.什么是dict 我们已经知道,list 和 tuple 可以用来表示顺序集合,例如,班里同学 ...

  9. 用cocos2d 2.1制作一个过河小游戏(4): 游戏主逻辑BaseLayer设计

    前段时间一直在忙.没有时间更新博客.今天还是抽点时间把最后一小部分游戏的实现放上来吧. BaseLayer.h: #import <GameKit/GameKit.h> #import & ...

  10. PyQt4工具栏

    工具栏 菜单对程序中的所有命令进行分组防治,而工具栏则提供了快速执行最常用命令的方法. #!/usr/bin/python # -*- coding:utf-8 -*- import sys from ...