多核下绑定硬件进程到不一样CPU

     硬件中断发生频繁,是件很消耗 CPU 资源的事情,在多核 CPU 条件下若是有办法把大量硬件中断分配给不一样的 CPU (core) 处理显然能很好的平衡性能。如今的服务器上动不动就是多 CPU 多核、多网卡、多硬盘,若是能让网卡中断独占1个 CPU (core)、磁盘 IO 中断独占1个 CPU 的话将会大大减轻单一 CPU 的负担、提升总体处理效率。我前天收到一位网友的邮件提到了 SMP IRQ Affinity,引起了今天的话题。如下操做在 SUN FIre X2100 M2 服务器+ 64位版本 CentOS 5.5 + Linux 2.6.18-194.3.1.el5 上执行。linux


  什么是中断算法

  中文教材上对 “中断” 的定义太生硬了,简单的说就是,每一个硬件设备(如:硬盘、网卡等)都须要和 CPU 有某种形式的通讯以便 CPU 及时知道发生了什么事情,这样 CPU 可能就会放下手中的事情去处理应急事件,硬件设备主动打扰 CPU 的现象就可称为硬件中断,就像你正在工做的时候受到 QQ 干扰同样,一次 QQ 摇头就能够被称为中断。数据库


  中断是一种比较好的 CPU 和硬件沟通的方式,还有一种方式叫作轮询(polling),就是让 CPU 定时对硬件状态进行查询而后作相应处理,就好像你每隔5分钟去检查一下 QQ 看看有没有人找你同样,这种方式是否是很浪费你(CPU)的时间?因此中断是硬件主动的方式,比轮询(CPU 主动)更有效一些。编程


  好了,这里又有了一个问题,每一个硬件设备都中断,那么如何区分不一样硬件呢?不一样设备同时中断如何知道哪一个中断是来自硬盘、哪一个来自网卡呢?这个很容易,不是每一个 QQ 号码都不相同吗?一样的,系统上的每一个硬件设备都会被分配一个 IRQ 号,经过这个惟一的 IRQ 号就能区别张三和李四了。性能优化


  在计算机里,中断是一种电信号,由硬件产生,并直接送到中断控制器(如 8259A)上,而后再由中断控制器向 CPU 发送信号,CPU 检测到该信号后,就中断当前的工做转而去处理中断。而后,处理器会通知操做系统已经产生中断,这样操做系统就会对这个中断进行适当的处理。如今来看一下中断控制器,常见的中断控制器有两种:可编程中断控制器 8259A 和高级可编程中断控制器(APIC),中断控制器应该在大学的硬件接口和计算机体系结构的相关课程中都学过。传统的 8259A 只适合单 CPU 的状况,如今都是多 CPU 多核的 SMP 体系,因此为了充分利用 SMP 体系结构、把中断传递给系统上的每一个 CPU 以便更好实现并行和提升性能,Intel 引入了高级可编程中断控制器(APIC)。服务器


  光有高级可编程中断控制器的硬件支持还不够,linux 内核还必须能利用到这些硬件特质,因此只有 kernel 2.4 之后的版本才支持把不一样的硬件中断请求(IRQs)分配到特定的 CPU 上,这个绑定技术被称为 SMP IRQ Affinity. 更多介绍请参看 Linux 内核源代码自带的文档:linux-2.6.31.8/Documentation/IRQ-affinity.txt网络


  如何使用oracle

  先看看系统上的中断是怎么分配在 CPU 上的,很显然 CPU0 上处理的中断多一些:ide

  # cat /proc/interrupts工具

  CPU0 CPU1

  0: 918926335 0 IO-APIC-edge timer

  1: 2 0 IO-APIC-edge i8042

  8: 0 0 IO-APIC-edge rtc

  9: 0 0 IO-APIC-level acpi

  12: 4 0 IO-APIC-edge i8042

  14: 8248017 0 IO-APIC-edge ide0

  50: 194 0 IO-APIC-level ohci_hcd:usb2

  58: 31673 0 IO-APIC-level sata_nv

  90: 1070374 0 PCI-MSI eth0

  233: 10 0 IO-APIC-level ehci_hcd:usb1

  NMI: 5077 2032

  LOC: 918809969 918809894

  ERR: 0

  MIS: 0

  为了避免让 CPU0 很累怎么把部分中断转移到 CPU1 上呢?或者说如何把 eth0 网卡的中断转到 CPU1 上呢?先查看一下 IRQ 90 中断的 smp affinity,看看当前中断是怎么分配在不一样 CPU 上的(ffffffff 意味着分配在全部可用 CPU 上):

  # cat /proc/irq/90/smp_affinity

  7fffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff

  在进一步动手以前咱们须要先停掉 IRQ 自动调节的服务进程,这样才能手动绑定 IRQ 到不一样 CPU,不然本身手动绑定作的更改将会被自动调节进程给覆盖掉。若是想修改 IRQ 90 的中断处理,绑定到第2个 CPU(CPU1):

  # /etc/init.d/irqbalance stop

  # echo "2" > /proc/irq/90/smp_affinity

  过段时间在看 /proc/interrupts,是否是 90:eth0 在 CPU1 上的中断增长了(145)、在 CPU0 上的中断没变?不断打印 /proc/interrupts 就会发现 eth0 在 CPU0 上的中断数始终保持不变,而在 CPU1 上的中断数是持续增长的,这正是咱们想要的结果:

  # cat /proc/interrupts

  CPU0 CPU1

  0: 922506515 0 IO-APIC-edge timer

  1: 2 0 IO-APIC-edge i8042

  8: 0 0 IO-APIC-edge rtc

  9: 0 0 IO-APIC-level acpi

  12: 4 0 IO-APIC-edge i8042

  14: 8280147 0 IO-APIC-edge ide0

  50: 194 0 IO-APIC-level ohci_hcd:usb2

  58: 31907 0 IO-APIC-level sata_nv

  90: 1073399 145 PCI-MSI eth0

  233: 10 0 IO-APIC-level ehci_hcd:usb1

  NMI: 5093 2043

  LOC: 922389696 922389621

  ERR: 0

  MIS: 0

  有什么用

  在网络很是 heavy 的状况下,对于文件服务器、高流量 Web 服务器这样的应用来讲,把不一样的网卡 IRQ 均衡绑定到不一样的 CPU 上将会减轻某个 CPU 的负担,提升多个 CPU 总体处理中断的能力;对于数据库服务器这样的应用来讲,把磁盘控制器绑到一个 CPU、把网卡绑定到另外一个 CPU 将会提升数据库的响应时间、优化性能。合理的根据本身的生产环境和应用的特色来平衡 IRQ 中断有助于提升系统的总体吞吐能力和性能。


  本人常常收到网友来信问到如何优化 Linux、优化 VPS、这个问题不太好回答,要记住的是性能优化是一个过程而不是结果,不是看了些文档改了改参数就叫优化了,后面还须要大量的测试、监测以及持续的观察和改进。


  绑定进程到不一样CPU

  介绍了在 Linux 多核下如何绑定硬件中断到不一样 CPU,其实也能够用相似的作法把进程手动分配到特定的 CPU 上,平时在 Linux 上运行的各类进程都是由 Linux 内核统一分配和管理的,由进程调度算法来决定哪一个进程能够开始使用 CPU、哪一个进程须要睡眠或等待、哪一个进程运行在哪一个 CPU 上等。若是你对操做系统的内核和进程调度程序感兴趣的话,不妨看看那本经典的 Operating Systems Design and Implementation(Linus Torvalds 就是看了这本书受到启发写出了 Linux),从简单的 Minix 入手,hack 内核是件颇有意思的事情,本人之前修改过 Minix 内核的进程调度,学到了内核方面的不少东西。另外推荐一本课外读物:Just for Fun,Linus Torvalds 写的一本自传。


  Linux 给咱们提供了方便的工具用来手动分配进程到不一样的 CPU 上(CPU Affinity),这样咱们能够按照服务器和应用的特性来安排特定的进程到特定的 CPU 上,好比 Oracle 要消耗大量 CPU 和 I/O 资源,若是咱们能分配 oracle 进程到某个或多个 CPU 上并由这些 CPU 专门处理 Oracle 的话会毫无疑问的提升应用程序的响应和性能。还有一些特殊状况是必须绑定应用程序到某个 CPU 上的,好比某个软件的受权是单 CPU 的,若是想运行在多 CPU 机器上的话就必须限制这个软件到某一个 CPU 上。


  安装 schedutils

  在 CentOS/Fedora 下安装 schedutils:

  # yum install schedutils

  在 Debian/Ubuntu 下安装 schedutils:

  # apt-get install schedutils

  若是正在使用 CentOS/Fedora/Debian/Ubuntu 的最新版本的话,schedutils/util-linux 这个软件包可能已经装上了。

  计算 CPU Affinity 和计算 SMP IRQ Affinity 差很少:

  0x00000001 (CPU0)

  0x00000002 (CPU1)

  0x00000003 (CPU0+CPU1)

  0x00000004 (CPU2)

  ...

  使用 schedutils

  若是想设置进程号(PID)为 12212 的进程到 CPU0 上的话:

  # taskset 0x00000001 -p 12212

相关文章
相关标签/搜索