昨天对“黑色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 = 0; i < threads.Length; i++){var coreNumber = i + 1;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(2, 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 affinityif (ProcessorAffinity != 0){CurrentThread.ProcessorAffinity = new IntPtr(ProcessorAffinity);}// call real threadif (this.threadStart != null){this.threadStart();}else if (this.parameterizedThreadStart != null){this.parameterizedThreadStart(parameter);}else{throw new InvalidOperationException();}}finally{// reset affinityCurrentThread.ProcessorAffinity = new IntPtr(0xFFFF);Thread.EndThreadAffinity();}}private ProcessThread CurrentThread{get{int id = GetCurrentThreadId();return(from ProcessThread th in Process.GetCurrentProcess().Threadswhere th.Id == idselect 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

转载于:https://www.cnblogs.com/cmt/p/csharp-processor-affinity.html

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

  1. 云计算之路-阿里云上-幸福总是很突然:“黑色1秒”问题解决啦

    云计算之路-阿里云上-幸福总是很突然:"黑色1秒"问题解决啦 参考文章: (1)云计算之路-阿里云上-幸福总是很突然:"黑色1秒"问题解决啦 (2)https: ...

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

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

  3. 云计算之路-阿里云上:超级奇怪的“黑色10秒钟”

    自从5月24日发布博文(云计算之路-阿里云上:两个重要突破)之后,情况有了明显改善.但是我们不但没有丝毫的放松,反而变得更加艰苦.我们被一个非常非常奇怪的问题所困扰,这段时间我们与阿里云一起在努力与之 ...

  4. 云计算之路-阿里云上:4000IOPS的RDS+16核CPU的负载均衡

    继续向大家汇报,上周在阿里云的帮助下我们重点解决的是以下两个问题: 1. 在专门跑博客站点的负载均衡中,如果单台云服务器处理的并发请求高(比如超过200 Get Requests/s),CPU有时会出 ...

  5. 云计算之路-阿里云上:愚人节被阿里云OCS愚

    2019独角兽企业重金招聘Python工程师标准>>> 今天是愚人节,而我们却被阿里云OCS愚,很多地方的缓存一直不过期,造成很多页面中的数据一直不更新.这篇博文将向您分享我们这两天 ...

  6. 云计算之路-阿里云上:在乌云中坚信蓝天

    继续向大家汇报阿里云上的天气变化情况.今天(5月8日)上午糟糕的天气(8:30~9:50,10:50~11:40)给大家逛园带来了很大的麻烦,请谅解! 早上8:30左右由于阿里云RDS出现突发故障(故 ...

  7. 云计算之路-阿里云上:攻击火上浇油,与云盾玩起了踢皮球

    2017年5月21日16:45开始,肆无忌惮.趾高气昂的攻击又嚣张而来,这次攻击了我们5个IP,除了1个IP只遭受2G流量的攻击,其他IP均遭受超过30G流量的攻击而被阿里云"云盾" ...

  8. 云计算之路-阿里云上:基于Xen的IO模型进一步分析“黑色0.1秒”问题

    在发现云服务器读取OCS缓存的"黑色0.1秒"是发生在socket读取数据时,而且是发生在读取开始的字节,甚至在socket写数据时(比如写入缓存key)也会出现超过50ms的情况 ...

  9. 云计算之路-阿里云上:2013年4月7日14:15~18:35服务器故障经过

    无地自容的道歉之后,向大家汇报一下故障的整个经过.在此再次向大家表示歉意,望大家能谅解! 14:15,有园友在闪存上说博客后台不能发布博文(见下图). 14:17左右,我们看到了这条闪存.立即进入博客 ...

最新文章

  1. (一)深入浅出图解Git,入门到精通(保姆级教程)
  2. python大数据分析实例-如何用Python分析大数据(以Twitter数据挖掘为例)
  3. C# 互通操作 (二)基础知识1
  4. java怎么使异常不起作用_java – @Test(expected = Exception.class)对我不起作用,我错过了什么?...
  5. [html] html和html5有什么区别呢?
  6. Attention Model
  7. 小米平板5或无缘MIUI 13:搭配骁龙870 预装MIUI 12.5系统
  8. 浅谈SQL Server identity列的操作方法
  9. python 生成器装饰器_对Python生成器、装饰器、递归的使用详解
  10. 字符变量赋值规则_第四章 变量
  11. 简述什么是 Cloud Native
  12. golang语言os.Stat()用法及功能
  13. Linux服务器中查询IP地址五个方法
  14. 单片机技术与c语言编程教学大纲,单片机原理及应用课程教学大纲
  15. C/S权限系统得到拼音和五笔的自定义函数(二)
  16. 如何让 ABAP 报表在后台作业的模式下运行
  17. codevs 1253 超级市场 DP 解题报告
  18. 几个著名的心理学实验
  19. 我的世界服务器披风文件在哪,关于我的世界国际版披风导入方法与详解(联机可用...
  20. 美丽田园ipo上市,它的底气从何而来?

热门文章

  1. 【深度学习】卷积神经网络速成
  2. 【深度学习入门到精通系列】Deep Q Network
  3. 永磁电机设计唐任远_新能源汽车的关键技术中钕铁硼永磁同步电机结构设计
  4. pid控制从入门到精通pdf_【应用指南】PID调节让流量/压力控制又快又稳
  5. python画笑脸步骤遇到的问题_用python绘制笑脸的基本步骤
  6. 网络营销专员表示网络营销中设置不当会影响蜘蛛爬虫对网站抓取
  7. 选择域名需注意什么才更有利于网站优化?
  8. 404页面设计技巧性分享不容错过!
  9. 网站建设之前需要先了解目标受众
  10. python opencv 边缘检测_opencv-python-学习笔记十四(Canny边缘检测)