使用 SCons 轻松建造程序

前言

make 这个工具自上个世纪 70 年代 Stuart Feldman 在贝尔实验室开发出以来,就一直是类 UNIX 程序员的最爱之一。通过检查文件的修改时间,make 工具可以知道编译目标文件所要依赖的其他文件。在复杂的项目中,如果只有少数几个文件修改过,make 工具知道仅仅需要对哪些文件重新编译就可以确保目标程序被正确的编译链接。这样做的好处就是在编译中,不仅可以节省大量的重复输入,还可以确保程序可以被正确的链接,缩短编译的时间。虽然如此,但是为 make 工具编写建造规则却不是一件容易的事。它复杂的配置规则,即使是有经验的开发者也望而生畏。make 工具的许多替代品便因此而诞生,SCons 就是是其中之一。SCons 是一个用 Python 语言编写的类似于 make 工具的程序。与 make 工具相比较,SCons 的配置文件更加简单清晰明了,除此之外,它还有许多的优点。

SCons 简介

SCons 是一个开放源代码、以 Python 语言编写的下一代的程序建造工具。它最初的名字是 ScCons, 基于由 perl 语言编写的 Cons 软件开发而成,它在 2000 年 8 月获得了由 Software Carpentry 举办的 SC 建造比赛的大奖。现在 ScCons 已经被改名为 SCons,目的是为了表示不再与 Software Carpentry 有联系,当然,还有一个目的,就是为了更方便的输入。

作为下一代的软件建造工具,SCons 的设计目标就是让开发人员更容易、更可靠和更快速的建造软件。与传统的 make 工具比较,SCons 具有以下优点:

  • 使用 Python 脚本做为配置文件
  • 对于 C,C++ 和 Fortran, 内建支持可靠自动依赖分析 . 不用像 make 工具那样需要 执行"make depends"和"make clean"就可以获得所有的依赖关系。
  • 内建支持 C, C++, D, Java, Fortran, Yacc, Lex, Qt,SWIG 以及 Tex/Latex。 用户还可以根据自己的需要进行扩展以获得对需要编程语言的支持。
  • 支持 make -j 风格的并行建造。相比 make -j, SCons 可以同时运行 N 个工作,而 不用担心代码的层次结构。
  • 使用 Autoconf 风格查找头文件,函数库,函数和类型定义。
  • 良好的夸平台性。SCons 可以运行在 Linux, AIX, BSD, HP/UX, IRIX, Solaris, Windows, Mac OS X 和 OS/2 上。

安装 SCons

SCons 支持多种操作系统平台,并为各个系统制作了易于安装的文件,因此在各个系统平台上的安装方法不尽相同,在 SCons 的官方网站上可以查每个平台的具体安装方法。 如果 SCons 没有为你的系统制作相应的安装包,你也可以下载 SCons 的源代码,直接进行安装。 首先,从 SCons 的网站上下载最新的 SCons 源代码包(目前 SCons 的最新版本是 2.0.1)。 其次,解压下载的源代码。视下载的源代码包的格式不同而有不同的方法,在 Windows 平台上,可是使用 winzip 或者其他类似的工具解压。在 Linux 平台上,对于 tar 包,使用 tar 命令进行解压,如:

1
$ tar -zxf scons-2.0.1.tar.gz

然后切换进入解压后的目录进行安装,如

1
2
$ cd scons-2.0.1
$ sudo python setup.py install

命令执行如果没有错误,那么 scons 就被安装到系统上了。对于 Linux 来说,scons 会默认安装到 /usr/loca/bin 目录下,而在 Windows 平台上,则会被安装到 C:\Python25\Scripts 下。

使用 SCons

在 SCons 安装完成后,我们就可以使用 SCons 来建造我们的程序或者项目了。像很多编程书籍那样,在这里我们也通过一个简单的 helloscons 例子来说明如何使用 SCons。例子 helloscons 包含两个文件 :

1
2
$ ls helloscons
helloscons.c  SConstruct

其中 helloscons.c 是程序的源文件,SConstruct 是 scons 的配置文件,类似使用 make 工具时的 Makefile 文件,因此,为了编译你的项目,需要手工创建一个 SConstruct 文件(注意:文件名是大小写敏感的)。不过,在编译的时候不需要指定它。 要编译这个例子,切换到 helloscons 的目录下,运行 scons 命令,如下:

1
2
3
4
5
6
7
8
$ cd helloscons/
$ scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
gcc -o helloscons.o -c helloscons.c
gcc -o helloscons helloscons.o
scons: done building targets.

来查看一下运行 scons 命令后得到的结果 :

1
2
$ ls
helloscons  helloscons.c  helloscons.o  SConstruct

建造结束后,得到了二进制文件 helloscons 以及编译的过程中产生的一些以 .o 结尾的目标文件。试运行 helloscons 一下 , 会得到 :

1
2
$ ./helloscons
Hello, SCons!

现在让我们回过头来解析一下 helloscons 这个例子 . helloscons.c 是这个例子里的唯一一个源代码文件,它所做的事就是在控制台上输出一行简单的"Hello,SCons", 它的源代码如下:

清单 1. helloscons.c
1
2
3
4
5
6
7
8
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[])
{
       printf("Hello, SCons!\n");
       return 0;
}

作为项目建造规则的配置文件 SConstruct 的内容如下 :

清单 2. SConstruct 文件
1
Program('helloscons.c')

你可能很惊讶 SConstruct 的内容只有一行,然而事实确实如此,它比传统的 Makefile 简单很多。SConstruct 以 Python 脚本的语法编写,你可以像编写 Python 脚本一样来编写它。其中的 Program 是编译的类型,说明你准备想要建造一个可执行的二进制程序,它由 helloscons.c 文件来生成。在这里,没有指定生成的可执行程序的名字。不过不用担心,SCons 会把源代码文件名字的后缀去掉,用来作为可执行文件的名字。在这里,我们甚至不需要像 Makefile 那样指定清理的动作,就可以执行清理任务。在 SCons 中,执行清理任务由参数 -c 指定,如下 :

1
2
3
4
5
6
7
8
9
10
$ scons -c
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Cleaning targets ...
Removed helloscons.o
Removed helloscons
scons: done cleaning targets.
$ ls
helloscons.c  SConstruct

如果你不想直接编译可执行的二进制文件,那也没有关系。SCons 支持多种编译类型,你可以根据自己的需要,任意选用其中的一种。SCons 支持的编译类型有:

  • Program: 编译成可执行程序(在 Windows 平台上即是 exe 文件),这是最常用的一种编译类型。
  • Object: 只编译成目标文件。使用这种类型,编译结束后,只会产生目标文件。在 POSIX 系统中,目标文件以 .o 结尾,在 Windows 平台上以 .OBJ 结尾。
  • Library: 编译成库文件。SCons 默认编译的库是指静态链接库。
  • StaticLibrary: 显示的编译成静态链接库,与上面的 Library 效果一样。
  • SharedLibrary: 在 POSIX 系统上编译动态链接库,在 Windows 平台上编译 DLL。

这个简单的 SConstruct 的配置文件从一个侧面说明了使用 SCons 来建造程序是多么的简单。 在实际的项目开发中,程序的建造规则远比 helloscons 这个例子复杂。不过,这些都不是问题,你可以像扩展你自己的 Python 脚本文件那样去扩展 SConstruct. 如果你不想使用 SConstruct 为你设置的默认可执行文件的名字,而是选择你自己喜欢的名字,如 myscons,可以把 SConstruct 的内容修改为 :

1
Program('myscons, 'helloscons.c')

其中 myscons 就是你想要的可执行文件的名字,你可以把它换成任意你喜欢的名字, 不过有点注意的是,这个名字必须放在第一位。 然后在 helloscons 目录下运行 scons 命令,就会得到 myscons 这个可执行文件,如 下:

1
2
3
$ scons -Q
gcc -o helloscons.o -c helloscons.c
gcc -o myscons helloscons.o

其中的 -Q 参数是减少编译时的由 scons 产生的冗余信息。 如果你的项目由多个源文件组成,而且你想指定一些编译的宏定义,以及显式的指定使用某些库,这些对于 SCons 来说,都是非常简单的事情。我们的另外一个例子 helloscons2 很好的说明这种情况。 helloscons2 由 3 个源文件组成 , 它们是 helloscon2.c, file1.c, file2.c,另外指定了编译的选项,同时还指定了使用哪些具体的库。让我们来看一下 helloscons2 的 SConstruct 文件 :

1
2
3
4
Program('helloscons2', ['helloscons2.c', 'file1.c', 'file2.c'],
       LIBS = 'm',
       LIBPATH = ['/usr/lib', '/usr/local/lib'],
       CCFLAGS = '-DHELLOSCONS')

正如你想像的那样,这样一个配置文件并不复杂 . 该 SConstruct 文件指出,它将生成一个名叫 helloscons2 的可执行程序,该可执行程序由 helloscons2.c, file1.c 和 file2.c 组成。注意,多个源文件需要放在一个 Python 列表中。如果你的源程序代码文件很多,有十几个甚至上百个,那不要一个个的将他们都列出来,你可以使用 glob('*.c') 来代替源代码列表。如下 :

1
Program('helloscons2', Glob('*.c')

配置文件中 LIBS,LIBAPTH 和 CCFLAGS 是 SCons 内置的关键字,它们的作用如下:

  • LIBS: 显示的指明要在链接过程中使用的库,如果有多个库,应该把它们放在一个列表里面。这个例子里,我们使用一个称为 m 的库。
  • LIBPATH: 链接库的搜索路径,多个搜索路径放在一个列表中。这个例子里,库的搜索路径是 /usr/lib 和 /usr/local/lib。
  • CCFLAGS: 编译选项,可以指定需要的任意编译选项,如果有多个选项,应该放在一个列表中。这个例子里,编译选项是通过 -D 这个 gcc 的选项定义了一个宏 HELLOSCONS。

运行 scons 命令的时候,可以看到这些变量如何被使用的,让我们执行一下 scons 命令 :

1
2
3
4
5
$ scons -Q
gcc -o file1.o -c -DHELLOSCONS file1.c
gcc -o file2.o -c -DHELLOSCONS file2.c
gcc -o helloscons2.o -c -DHELLOSCONS helloscons2.c
gcc -o helloscons2 helloscons2.o file1.o file2.o -L/usr/lib -L/usr/local/lib -lm

scons 命令的输出显示了可执行程序 helloscons2 如何由多个源文件而生成,以及在 SConstruct 中定义的 LIBS,LIBPATH 和 CCFLAGS 如何被使用。 可见,即使对于复杂的项目,SCons 的编译配置文件也很简单。除此之外,SCons 也提供了很多功能以适应不同的需要,如果读者想更深入的了解如何使用 SCons,可以参考 SCons 的帮助手册。

总结

本文简单介绍了 SCons 的特点,如何安装 SCons,以及通过例子来说明如何在项目中使用 SCons。 作为下一代的软件建造工具,SCons 使用 Python 语言作为配置文件,不但功能强大,而且简单易用,对于跨平台的项目,非常适合。 如果你厌烦了 make 工具的那种复杂的编写规则,尝试一下新鲜的 SCons 吧。

HAProxy

HAProxy是什么

HAProxy是一个免费的负载均衡软件,可以运行于大部分主流的Linux操作系统上。

HAProxy提供了L4(TCP)和L7(HTTP)两种负载均衡能力,具备丰富的功能。HAProxy的社区非常活跃,版本更新快速(最新稳定版1.7.2于2017/01/13推出)。最关键的是,HAProxy具备媲美商用负载均衡器的性能和稳定性。

因为HAProxy的上述优点,它当前不仅仅是免费负载均衡软件的首选,更几乎成为了唯一选择。

HAProxy的核心能力和关键特性

HAProxy的核心功能

  • 负载均衡:L4和L7两种模式,支持RR/静态RR/LC/IP Hash/URI Hash/URL_PARAM Hash/HTTP_HEADER Hash等丰富的负载均衡算法
  • 健康检查:支持TCP和HTTP两种健康检查模式
  • 会话保持:对于未实现会话共享的应用集群,可通过Insert Cookie/Rewrite Cookie/Prefix Cookie,以及上述的多种Hash方式实现会话保持
  • SSL:HAProxy可以解析HTTPS协议,并能够将请求解密为HTTP后向后端传输
  • HTTP请求重写与重定向
  • 监控与统计:HAProxy提供了基于Web的统计信息页面,展现健康状态和流量数据。基于此功能,使用者可以开发监控程序来监控HAProxy的状态

HAProxy的关键特性

性能

  • 采用单线程、事件驱动、非阻塞模型,减少上下文切换的消耗,能在1ms内处理数百个请求。并且每个会话只占用数KB的内存。
  • 大量精细的性能优化,如O(1)复杂度的事件检查器、延迟更新技术、Single-buffereing、Zero-copy forwarding等等,这些技术使得HAProxy在中等负载下只占用极低的CPU资源。
  • HAProxy大量利用操作系统本身的功能特性,使得其在处理请求时能发挥极高的性能,通常情况下,HAProxy自身只占用15%的处理时间,剩余的85%都是在系统内核层完成的。
  • HAProxy作者在8年前(2009)年使用1.4版本进行了一次测试,单个HAProxy进程的处理能力突破了10万请求/秒,并轻松占满了10Gbps的网络带宽。

稳定性

作为建议以单进程模式运行的程序,HAProxy对稳定性的要求是十分严苛的。按照作者的说法,HAProxy在13年间从未出现过一个会导致其崩溃的BUG,HAProxy一旦成功启动,除非操作系统或硬件故障,否则就不会崩溃(我觉得可能多少还是有夸大的成分)。

在上文中提到过,HAProxy的大部分工作都是在操作系统内核完成的,所以HAProxy的稳定性主要依赖于操作系统,作者建议使用2.6或3.x的Linux内核,对sysctls参数进行精细的优化,并且确保主机有足够的内存。这样HAProxy就能够持续满负载稳定运行数年之久。

个人的建议:

  • 使用3.x内核的Linux操作系统运行HAProxy
  • 运行HAProxy的主机上不要部署其他的应用,确保HAProxy独占资源,同时避免其他应用引发操作系统或主机的故障
  • 至少为HAProxy配备一台备机,以应对主机硬件故障、断电等突发情况(搭建双活HAProxy的方法在后文中有描述)
  • sysctl的建议配置(并不是万用配置,仍然需要针对具体情况进行更精细的调整,但可以作为首次使用HAProxy的初始配置使用):
net.ipv4.tcp_tw_reuse = 1
net.ipv4.ip_local_port_range = 1024 65023
net.ipv4.tcp_max_syn_backlog = 10240
net.ipv4.tcp_max_tw_buckets = 400000
net.ipv4.tcp_max_orphans = 60000
net.ipv4.tcp_synack_retries = 3
net.core.somaxconn = 10000

作者:kelgon
链接:https://www.jianshu.com/p/c9f6d55288c0
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

关于Linux交换空间

加里·西姆斯

Linux将其物理RAM(随机存取存储器)划分为称为页面的内存块。交换是将一页内存复制到硬盘上的预配置空间(称为交换空间)以释放该内存页面的过程。物理内存和交换空间的组合大小是可用的虚拟内存量。

交换是必要的,原因有两个。首先,当系统需要的内存大于物理上可用的内存时,内核会交换较少使用的页面,并为需要内存的当前应用程序(进程)提供内存。其次,应用程序在其启动阶段使用的大量页面可能仅用于初始化,然后再也不会再使用。系统可以换出这些页面并释放内存用于其他应用程序甚至磁盘缓存。

但是,交换确实有缺点。与内存相比,磁盘速度非常慢。内存速度可以以纳秒为单位测量,而磁盘以毫秒为单位进行测量,因此访问磁盘的速度比访问物理内存要慢几万倍。发生的交换越多,系统就越慢。有时,在页面被换出然后很快交换然后再次换出等等时会发生过度交换或颠簸。在这种情况下,系统正在努力寻找可用内存并保持应用程序同时运行。在这种情况下,只添加更多RAM将有所帮助。

Linux有两种形式的交换空间:交换分区和交换文件。交换分区是硬盘的独立部分,仅用于交换; 没有其他文件可以驻留在那里。交换文件是文件系统中的一个特殊文件,位于系统和数据文件中。

要查看您拥有的交换空间,请使用命令swapon -s。输出看起来像这样:

文件名类型大小使用优先级
/ dev / sda5 partition 859436 0 -1

每行列出系统使用的单独交换空间。这里,'Type'字段表示这个交换空间是一个分区而不是一个文件,从'Filename'我们看到它在磁盘sda5上。'Size'以千字节为单位,'Used'字段告诉我们使用了多少千字节的交换空间(在本例中为none)。'优先级'告诉Linux首先使用哪个交换空间。关于Linux交换子系统的一个好处是,如果你安装两个(或更多)交换空间(最好是在两个不同的设备上)具有相同的优先级,Linux将交换它们之间的交换活动,这可以大大提高交换性能。

要向系统添加额外的交换分区,首先需要准备它。第一步是确保将分区标记为交换分区,第二步是制作交换文件系统。要检查分区是否标记为swap,请以root身份运行:

fdisk -l / dev / hdb

将/ dev / hdb替换为系统上具有交换分区的硬盘设备。您应该看到如下所示的输出:

设备启动开始结束块ID系统
/ dev / hdb1 2328 2434 859446 82 Linux swap / Solaris

如果分区未标记为交换,则需要通过运行fdisk并使用“t”菜单选项来更改它。使用分区时要小心 - 您不希望错误地删除重要分区,或者将系统分区的ID更改为错误交换。交换分区上的所有数据都将丢失,因此请仔细检查您所做的每项更改。另请注意,Solaris为其分区使用与Linux交换空间相同的ID,因此请注意不要错误地终止Solaris分区。

将分区标记为swap后,需要使用mkswap(make swap)命令以root身份进行准备:

mkswap / dev / hdb1

如果您没有看到任何错误,则可以使用交换空间。要立即激活它,请键入:

swapon / dev / hdb1

您可以通过运行swapon -s来验证它是否正在使用。要在引导时自动挂载交换空间,必须在/ etc / fstab文件中添加一个条目,该文件包含需要在引导时挂载的文件系统和交换空间的列表。每行的格式是:

由于交换空间是一种特殊类型的文件系统,因此许多参数不适用。对于交换空间,请添加:

/ dev / hdb1 none swap sw 0 0

其中/ dev / hdb1是交换分区。它没有特定的挂载点,因此没有。它的类型为swap,选项为sw,最后两个参数未使用,因此输入为0。

要检查交换空间是否自动挂载而不必重新启动,可以运行swapoff -a命令(关闭所有交换空间),然后执行swapon -a(挂载/ etc / fstab文件中列出的所有交换空间) )然后用swapon -s检查它。

交换文件

除交换分区外,Linux还支持交换文件,您可以以类似于交换分区的方式创建,准备和装载。交换文件的优点是您不需要查找空分区或重新分区磁盘以添加额外的交换空间。

要创建交换文件,请使用dd命令创建空文件。要创建1GB文件,请键入:

dd if = / dev / zero of = / swapfile bs = 1024 count = 1048576

/ swapfile是交换文件的名称,计数1048576是以千字节为单位的大小(即1GB)。

使用mkswap准备交换文件就像分区一样,但这次使用交换文件的名称:

mkswap / swapfile

同样,使用swapon命令安装它:swapon / swapfile。

交换文件的/ etc / fstab条目如下所示:

/ swapfile none swap sw 0 0

我的交换空间应该有多大?

可以在没有交换空间的情况下运行Linux系统,如果你有大量的内存,系统将运行良好 - 但是如果你的物理内存耗尽,那么系统将崩溃,因为它没有别的东西可以do,所以建议有一个交换空间,特别是因为磁盘空间相对便宜。

关键问题是多少钱?较旧版本的Unix类型操作系统(例如Sun OS和Ultrix)要求交换空间是物理内存的两到三倍。现代实现(例如Linux)不需要那么多,但是如果你配置它们就可以使用它。经验法则如下:1)对于桌面系统,使用双系统内存的交换空间,因为它将允许您运行大量应用程序(其中许多应用程序可能空闲且易于交换),更多RAM可用于活动应用程序; 2)对于服务器,可用的交换量较小(比如物理内存的一半),这样您在需要时可以灵活地进行交换,但监控所使用的交换空间量并在必要时升级RAM; 3)对于较旧的台式机(仅说128MB),

Linux 2.6内核添加了一个名为swappiness的新内核参数,让管理员可以调整Linux交换的方式。它是一个从0到100的数字。本质上,较高的值会导致更多页面被交换,较低的值会导致更多的应用程序保留在内存中,即使它们处于空闲状态。内核维护者安德鲁莫顿说他运行他的桌面机器的吞吐量为100,说明“我的观点是减少内核交换东西的倾向是错误的。你真的不希望数百兆字节的BloatyApp不受影响内存在机器中浮动。在磁盘上取出它,使用内存来获取有用的东西。“

Morton的想法的一个缺点是,如果内存换得太快,那么应用程序响应时间会下降,因为当单击应用程序的窗口时,系统必须将应用程序交换回内存,这会让它感觉很慢。

swappiness的默认值为60.您可以通过键入root来临时更改它(直到下次重新引导):

echo 50> / proc / sys / vm / swappiness

如果要永久更改它,则需要更改/etc/sysctl.conf文件中的vm.swappiness参数。

结论

管理交换空间是系统管理的一个重要方面。通过良好的规划和正确使用交换可以提供许多好处。不要害怕尝试,并始终监控您的系统,以确保您获得所需的结果。

 

Better Linux Disk Caching & Performance with vm.dirty_ratio & vm.dirty_background_ratio

This is post #16 in my December 2013 series about Linux Virtual Machine Performance Tuning. For more, please see the tag “Linux VM Performance Tuning.”

In previous posts on vm.swappiness and using RAM disks we talked about how the memory on a Linux guest is used for the OS itself (the kernel, buffers, etc.), applications, and also for file cache. File caching is an important performance improvement, and read caching is a clear win in most cases, balanced against applications using the RAM directly. Write caching is trickier. The Linux kernel stages disk writes into cache, and over time asynchronously flushes them to disk. This has a nice effect of speeding disk I/O but it is risky. When data isn’t written to disk there is an increased chance of losing it.

There is also the chance that a lot of I/O will overwhelm the cache, too. Ever written a lot of data to disk all at once, and seen large pauses on the system while it tries to deal with all that data? Those pauses are a result of the cache deciding that there’s too much data to be written asynchronously (as a non-blocking background operation, letting the application process continue), and switches to writing synchronously (blocking and making the process wait until the I/O is committed to disk). Of course, a filesystem also has to preserve write order, so when it starts writing synchronously it first has to destage the cache. Hence the long pause.

The nice thing is that these are controllable options, and based on your workloads & data you can decide how you want to set them up. Let’s take a look:

$ sysctl -a | grep dirty
 vm.dirty_background_ratio = 10
 vm.dirty_background_bytes = 0
 vm.dirty_ratio = 20
 vm.dirty_bytes = 0
 vm.dirty_writeback_centisecs = 500
 vm.dirty_expire_centisecs = 3000

vm.dirty_background_ratio is the percentage of system memory that can be filled with “dirty” pages — memory pages that still need to be written to disk — before the pdflush/flush/kdmflush background processes kick in to write it to disk. My example is 10%, so if my virtual server has 32 GB of memory that’s 3.2 GB of data that can be sitting in RAM before something is done.

vm.dirty_ratio is the absolute maximum amount of system memory that can be filled with dirty pages before everything must get committed to disk. When the system gets to this point all new I/O blocks until dirty pages have been written to disk. This is often the source of long I/O pauses, but is a safeguard against too much data being cached unsafely in memory.

vm.dirty_background_bytes and vm.dirty_bytes are another way to specify these parameters. If you set the _bytes version the _ratio version will become 0, and vice-versa.

vm.dirty_expire_centisecs is how long something can be in cache before it needs to be written. In this case it’s 30 seconds. When the pdflush/flush/kdmflush processes kick in they will check to see how old a dirty page is, and if it’s older than this value it’ll be written asynchronously to disk. Since holding a dirty page in memory is unsafe this is also a safeguard against data loss.

vm.dirty_writeback_centisecs is how often the pdflush/flush/kdmflush processes wake up and check to see if work needs to be done.

You can also see statistics on the page cache in /proc/vmstat:

$ cat /proc/vmstat | egrep "dirty|writeback"
 nr_dirty 878
 nr_writeback 0
 nr_writeback_temp 0

In my case I have 878 dirty pages waiting to be written to disk.

Approach 1: Decreasing the Cache

As with most things in the computer world, how you adjust these depends on what you’re trying to do. In many cases we have fast disk subsystems with their own big, battery-backed NVRAM caches, so keeping things in the OS page cache is risky. Let’s try to send I/O to the array in a more timely fashion and reduce the chance our local OS will, to borrow a phrase from the service industry, be “in the weeds.” To do this we lower vm.dirty_background_ratio and vm.dirty_ratio by adding new numbers to /etc/sysctl.conf and reloading with “sysctl –p”:

vm.dirty_background_ratio = 5
vm.dirty_ratio = 10

This is a typical approach on virtual machines, as well as Linux-based hypervisors. I wouldn’t suggest setting these parameters to zero, as some background I/O is nice to decouple application performance from short periods of higher latency on your disk array & SAN (“spikes”).

Approach 2: Increasing the Cache

There are scenarios where raising the cache dramatically has positive effects on performance. These situations are where the data contained on a Linux guest isn’t critical and can be lost, and usually where an application is writing to the same files repeatedly or in repeatable bursts. In theory, by allowing more dirty pages to exist in memory you’ll rewrite the same blocks over and over in cache, and just need to do one write every so often to the actual disk. To do this we raise the parameters:

vm.dirty_background_ratio = 50
vm.dirty_ratio = 80

Sometimes folks also increase the vm.dirty_expire_centisecs parameter to allow more time in cache. Beyond the increased risk of data loss, you also run the risk of long I/O pauses if that cache gets full and needs to destage, because on large VMs there will be a lot of data in cache.

Approach 3: Both Ways

There are also scenarios where a system has to deal with infrequent, bursty traffic to slow disk (batch jobs at the top of the hour, midnight, writing to an SD card on a Raspberry Pi, etc.). In that case an approach might be to allow all that write I/O to be deposited in the cache so that the background flush operations can deal with it asynchronously over time:

vm.dirty_background_ratio = 5
vm.dirty_ratio = 80

Here the background processes will start writing right away when it hits that 5% ceiling but the system won’t force synchronous I/O until it gets to 80% full. From there you just size your system RAM and vm.dirty_ratio to be able to consume all the written data. Again, there are tradeoffs with data consistency on disk, which translates into risk to data. Buy a UPS and make sure you can destage cache before the UPS runs out of power. 🙂

No matter the route you choose you should always be gathering hard data to support your changes and help you determine if you are improving things or making them worse. In this case you can get data from many different places, including the application itself, /proc/vmstat, /proc/meminfo, iostat, vmstat, and many of the things in /proc/sys/vm. Good luck!

 

Better Linux Disk Caching & Performance with vm.dirty_ratio & vm.dirty_background_ratio

 

 

性能优化:Swap调优

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/tenfyguo/article/details/50185915

目标:解决大量Log写入占用大量的File Cache,内容利用不充分导致swap

基本原则:尽量使用内存,减少swap,同时,尽早flush到外存,早点释放内存给写cache使用。---特别在持续的写入操作中,此优化非常有效。

调优措施:

vm.swapiness :60 改成 10

vm.dirty_ratio:90 改成 10

vm.dirty_background_ratio:60 改成 5

vm.dirty_expire_centisecs:3000改成500

vm.vfs_cache_pressure:100 改成 500

 

下面重点解释一下各个配置的含义:

一,vm.swappiness优化:

swappiness的值的大小对如何使用swap分区是有着很大的联系的。swappiness=0的时候表示最大限度使用物理内存,然后才是 swap空间,swappiness=100的时候表示积极的使用swap分区,并且把内存上的数据及时的搬运到swap空间里面。linux的基本默认设置为60,具体如下:

cat /proc/sys/vm/swappiness

60

也就是说,你的内存在使用到100-60=40%的时候,就开始出现有交换分区的使用。大家知道,内存的速度会比磁盘快很多,这样子会加大系统io,同时造的成大量页的换进换出,严重影响系统的性能,所以我们在操作系统层面,要尽可能使用内存,对该参数进行调整。

临时调整的方法如下,我们调成10:

sysctl vm.swappiness=10

vm.swappiness = 10

cat /proc/sys/vm/swappiness

10

这只是临时调整的方法,重启后会回到默认设置的

要想永久调整的话,需要将在/etc/sysctl.conf修改,加上:

cat /etc/sysctl.conf

vm.swappiness=10

 

二,vm.dirty_ratio: 同步刷脏页,会阻塞应用程序

这个参数控制文件系统的同步写写缓冲区的大小,单位是百分比,表示当写缓冲使用到系统内存多少的时候(即指定了当文件系统缓存脏页数量达到系统内存百分之多少时(如10%),),开始向磁盘写出数据,即系统不得不开始处理缓存脏页(因为此时脏页数量已经比较多,为了避免数据丢失需要将一定脏页刷入外存),在此过程中很多应用进程可能会因为系统转而处理文件IO而阻塞。

增大之会使用更多系统内存用于磁盘写缓冲,也可以极大提高系统的写性能。但是,当你需要持续、恒定的写入场合时,应该降低其数值,一般启动上缺省是 10。

 

三,vm.dirty_background_ratio:异步刷脏页,不会阻塞应用程序

这个参数控制文件系统的后台进程,在何时刷新磁盘。单位是百分比,表示系统内存的百分比,意思是当写缓冲使用到系统内存多少的时候,就会触发pdflush/flush/kdmflush等后台回写进程运行,将一定缓存的脏页异步地刷入外存。增大之会使用更多系统内存用于磁盘写缓冲,也可以极大提高系统的写性能。但是,当你需要持续、恒定的写入场合时,应该降低其数值,一般启动上缺省是 5。

注意:如果dirty_ratio设置比dirty_background_ratio大,可能认为dirty_ratio的触发条件不可能达到,因为每次肯定会先达到vm.dirty_background_ratio的条件,然而,确实是先达到vm.dirty_background_ratio的条件然后触发flush进程进行异步的回写操作,但是这一过程中应用进程仍然可以进行写操作,如果多个应用进程写入的量大于flush进程刷出的量那自然会达到vm.dirty_ratio这个参数所设定的坎,此时操作系统会转入同步地处理脏页的过程,阻塞应用进程。

 

四,vm.dirty_expire_centisecs:

这个参数声明Linux内核写缓冲区里面的数据多“旧”了之后,pdflush进程就开始考虑写到磁盘中去。单位是 1/100。缺省是 3000,也就是 30 秒的数据就算旧了,将会刷新磁盘。对于特别重载的写操作来说,这个值适当缩小也是好的,但也不能缩小太多,因为缩小太多也会导致IO提高太快。建议设置为 1500,也就是15秒算旧。当然,如果你的系统内存比较大,并且写入模式是间歇式的,并且每次写入的数据不大(比如几十M),那么这个值还是大些的好。

 

五,Vm.dirty_writeback_centisecs:

这个参数控制内核的脏数据刷新进程pdflush的运行间隔。单位是 1/100 。缺省数值是500,也就是 5 秒。如果你的系统是持续地写入动作,那么实际上还是降低这个数值比较好,这样可以把尖峰的写操作削平成多次写操作。设置方法如下:

echo "200" > /proc/sys/vm/dirty_writeback_centisecs

如果你的系统是短期地尖峰式的写操作,并且写入数据不大(几十M/次)且内存有比较多富裕,那么应该增大此数值:

 

六,Vm.vfs_cache_pressure:

增大这个参数设置了虚拟内存回收directory和inode缓冲的倾向,这个值越大。越易回收

该文件表示内核回收用于directory和inode cache内存的倾向;缺省值100表示内核将根据pagecache和swapcache,把directory和inode cache保持在一个合理的百分比;降低该值低于100,将导致内核倾向于保留directory和inode cache;增加该值超过100,将导致内核倾向于回收directory和inode cache。

This variable controls the tendency of the kernel to reclaim thememory which is used for caching of VFS caches, versus pagecache and swap.Increasing this value increases the rate at which VFS caches are reclaimed.Itis difficult to know when this should be changed, other than byexperimentation. The slabtop command (part of the package procps) shows topmemory objects used by the kernel. The vfs caches are the "dentry"and the "*_inode_cache" objects. If these are consuming a largeamount of memory in relation to pagecache, it may be worth trying to increasepressure. Could also help to reduce swapping. The default value is 100.