Archive

Archive for the ‘Linux’ Category

Lockless Memory Allocator试用记

December 14th, 2011 5 comments

原创文章,转载请注明: 转载自系统技术非业余研究

本文链接地址: Lockless Memory Allocator试用记

昨天@淘宝雕梁 同学推荐了无锁的内存分配器,上网站粗粗的了解了下,这家叫Lockless的公司主要有2个产品:
Lockless MPI 和 Lockless Memory Allocator, 我对内存分配器比较感兴趣,它对高性能服务器的影响还是非常大的,特别是mysql这样的服务器,看它的文档对性能的提升好像比较明显。

我们重点来了解下 Lockless Memory Allocator:

The Lockless Memory Allocator is downloadable under the GPL 3.0 License.

官网强调的特性:

Multithread Optimized
The Lockless memory allocator uses lock-free techniques to minimize latency and memory contention. This provides optimal scalability as the number of threads in your application increases. Per-thread data is used to reduce bus communication overhead. This results in thread-local allocations and frees not requiring any synchronization overhead in most cases.

官网做的和主流的几种分配器的性能比较:

详细的bechmark见这里,看上去让人挺印象深刻的。

代码在这里下载 http://locklessinc.com/downloads/, 支持32位和64位的Linux, 安装文档在这里

我们来尝鲜实验下:

$  wget http://locklessinc.com/downloads/lockless_allocator_src.tgz
$ tar xzf lockless_allocator_src.tgz 
$ cd lockless_allocator
$ gcc -v
Using built-in specs.
Target: x86_64-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --disable-libjava-multilib --with-ppl --with-cloog --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux
Thread model: posix
gcc version 4.4.5 20110214 (Red Hat 4.4.5-6) (GCC) 

$ make
/bin/sh -ec 'gcc -MM  ll_alloc.c | sed -n "H;$ {g;s@.*:\(.*\)@ll_alloc.c := \$\(wildcard\1\)\nll_alloc.o ll_alloc.c.d: $\(ll_alloc.c\)@;p}" > ll_alloc.c.d'
cc ll_alloc.c -fomit-frame-pointer -Wcast-qual -Wmissing-format-attribute -Wlogical-op -Wstrict-aliasing -Wsign-compare -Wdeclaration-after-statement -Wnested-externs -Wdisabled-optimization -Winline -Wundef -Wimplicit -Wunused -Wfloat-equal -Winit-self -Wformat=2 -Wswitch -Wsequence-point -Wparentheses -Wimplicit -Wchar-subscripts -Wredundant-decls -Wstrict-prototypes -Wbad-function-cast -Wpointer-arith -Wwrite-strings -Wno-long-long -Wmissing-declarations -Wmissing-prototypes -Wextra -Wall -pedantic -ggdb3 -std=gnu99 -O3  -fPIC -pthread -c -o libllalloc.o 
strip -g libllalloc.o
ar rcs libllalloc.a libllalloc.o
ranlib libllalloc.a
cc ll_alloc.c -fomit-frame-pointer -Wcast-qual -Wmissing-format-attribute -Wlogical-op -Wstrict-aliasing -Wsign-compare -Wdeclaration-after-statement -Wnested-externs -Wdisabled-optimization -Winline -Wundef -Wimplicit -Wunused -Wfloat-equal -Winit-self -Wformat=2 -Wswitch -Wsequence-point -Wparentheses -Wimplicit -Wchar-subscripts -Wredundant-decls -Wstrict-prototypes -Wbad-function-cast -Wpointer-arith -Wwrite-strings -Wno-long-long -Wmissing-declarations -Wmissing-prototypes -Wextra -Wall -pedantic -ggdb3 -std=gnu99 -O3  -shared -fpic -Wl,-soname,libllalloc.so.1.3 -Wl,-z,interpose -o libllalloc.so.1.3 
strip libllalloc.so.1.3

$ ls libllalloc.*
libllalloc.a  libllalloc.o  libllalloc.so.1.3

$ LD_PRELOAD=./libllalloc.so.1.3  erl
Erlang R14B04 (erts-5.8.5) [source] [64-bit] [smp:16:16] [rq:16] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.8.5  (abort with ^G)
1> 

#另外一个终端确认libllalloc.so.1.3在使用
$ lsof  -c beam.smp
COMMAND   PID           USER   FD      TYPE DEVICE     SIZE    NODE NAME
beam.smp 8458          chuba  txt       REG    8,5  2344032 3775338 /usr/local/lib/erlang/erts-5.8.5/bin/beam.smp
...
beam.smp 8458          chuba  mem       REG    8,6    40384  195304 /home/chuba/lockless_allocator/libllalloc.so.1.3
...

这里面有个问题: 编译的时候需要的gcc版本比较高,gcc version 4.1.2 20080704 (Red Hat 4.1.2-46)编译不过。
之前tcmalloc就没通过erl的使用,因为erlang内部的指针的后4位被用了,如果分配器不遵守16字节对齐,就会出问题。

看了代码实现的也很简单,代码质量也一般,不知道具体的性能如何,后续找个案例benchmark下!
未完待续!

祝玩得开心!

Post Footer automatically generated by wp-posturl plugin for wordpress.

调研内核调用栈方便的工具 kmalloc-top

December 14th, 2011 1 comment

原创文章,转载请注明: 转载自系统技术非业余研究

本文链接地址: 调研内核调用栈方便的工具 kmalloc-top

我们在研究内核的时候,看了内核代码后,就想着某个函数被谁谁调用。 调用路径有很多条,有热门的,有偏门的,但从代码不大容易看出。 如果我们能和gdb那样在函数上设个断点,看下内核函数的调用栈就清楚了。 但是如何统计热门路线呢?用systemtap就可以,参看这里这里

但是用systemtap写统计的时候,用到统计功能的话,如果你的采样点非常多,超过systemtap规定的上线,systemtap会选择罢工,直接推出,很不爽。

kmalloc-top就是为了解决这个问题写的一个perl脚本,原本用来调查内核中kmalloc的使用情况的,在一个繁忙的内核中,kmallo每秒会被调用成千上万次,明显会超过处理的上限。 所以kmalloc-top的方法是stap部分只负责收集堆栈信息,收集一个就写到标准输出一个,然后由perl脚本来进一步分析统计。

脚本位于:/usr/local/share/doc/systemtap/examples/memory/kmalloc-top
Read more…

Post Footer automatically generated by wp-posturl plugin for wordpress.

Categories: Linux, 工具介绍 Tags: ,

posix_fadvise清除缓存的误解和改进措施

December 11th, 2011 9 comments

原创文章,转载请注明: 转载自系统技术非业余研究

本文链接地址: posix_fadvise清除缓存的误解和改进措施

在典型的IO密集型的数据库服务器如MYSQL中,会涉及到大量的文件读写,通常这些文件都是通过buffer io来使用的,以便充分利用到Linux操作系统的page cache。

Buffer IO的特点是读的时候,先检查页缓存里面是否有需要的数据,如果没有就从设备读取,返回给用户的同时,加到缓存一份;写的时候,直接写到缓存去,再由后台的进程定期涮到磁盘去。这样的机制看起来非常的好,在实践中也效果很好。

但是如果你的IO非常密集,就会出现问题。首先由于pagesize是4K,内存的利用效率比较低。其次缓存的淘汰算法很简单,由操作系统自主进行,用户不大好参与。当你的写很多,超过系统内存的某个上限的时候,后台的进程(swapd)要出来回收页面,而且一旦回收的速度小于写入的速度,就会出现不可预期的行为。

这里面最大的问题是:当你使用的内存包括缓存,没超过操作系统规定的上限的时候,操作系统选择不作为,让用户充分使用缓存,从它的角度来看这样效率最高。但是正是由于这种策略在实践中会导致问题。

比如说MYSQL服务器,我们可以把数据直接走direct IO,但是它的日志是走bufferio的。因为走directio需要对写入文件的偏移和大小都要扇区对全,这对日志系统来讲太麻烦了。由于MYSQL是基于事务的,会涉及到大量的日志动作,频繁的写入,然后fsync. 日志一旦写入磁盘,buffer page就没用了,但是一直会在内存呆着,直到达到内存上限,引起操作系统突然大量回收
页面,出现IO柱塞或者内存交换等负面问题。

那么我们知道了困境在哪里,我们可以主动避免这个现象的发生。有二种方法:
1. 日志也走direct io,需要规模的修改MYSQL代码,如percona就这么做了,提供相应的patch。
2. 日志还是走buffer io, 但是定期清除无用page cache.

第一张方法不是我们要讨论的,我们重点讨论第二种如何做:

我们在程序里知道文件的句柄,是不是就可以很轻松的用:

int posix_fadvise(int fd, off_t offset, off_t len, int advice);
POSIX_FADV_DONTNEED
The specified data will not be accessed in the near future.

来解决问题呢?
比如写类似 posix_fadvise(fd, 0, len_of_file, POSIX_FADV_DONTNEED);这样的代码来清掉文件所属的缓存。

前面介绍的vmtouch就有这样的功能,清某个文件的缓存。
vmtouch -ve logfile 就可以试验,但是你会发现内存根本就没下来,原因呢?

我们从代码来看posix_fadvise如何运作的:
参看 mm/fadvise.c:
Read more…

Post Footer automatically generated by wp-posturl plugin for wordpress.

Flashcache新添加驱逐空闲脏页参数

December 10th, 2011 1 comment

原创文章,转载请注明: 转载自系统技术非业余研究

本文链接地址: Flashcache新添加驱逐空闲脏页参数

我在之前的博文提过Flashcache的cache是以set为单位管理的,每个set默认2M。 当单个set里面的脏页数量超过dirty_thresh_pct的时候,就会启动背景工作队列来把超过设置的脏页回写到后备磁盘去。 这里有别的同学对flashcache设计文档的翻译.

参看dirty_thresh_pct的文档解释:

dev.flashcache..dirty_thresh_pct = 20
Flashcache will attempt to keep the dirty blocks in each set
under this %. A lower dirty threshold increases disk writes,
and reduces block overwrites, but increases the blocks
available for read caching.

Flashcache之所以这样做的目的是当它在处理用户IO请求需要cache块的时候,保证马上可以拿的出来。因为读写的时候,如果需要的cache块不能满足的话,flashcache选择简单的绕过cache机制,直接走uncache io, 同时启动页面回收,一下子收回超过设置部分的页面,对性能有很大的损失。
特别是顺序写的时候,写一圈,再回绕在写的场合,性能特别差,就是这个原因。

那么如何保持一定量的可用cache块就很重要。通常cache数据都有冷热点,而且和时间很大关系。flashcache对冷热的判断是透过LRU类似的算法来判断的,这个是基于使用频度的维度。但是缺乏时间维度的判断。

新版本的flashcache引入了fallow_delay参数来解决这个问题,如果一个脏页超过fallow_delay秒,默认15分钟,都没有重新被访问到,那么数据就会被回写。 回写后,作为候选页面可以被新的cache重新利用。
Read more…

Post Footer automatically generated by wp-posturl plugin for wordpress.

vmtouch-系统pagecache查看和操纵器

December 8th, 2011 4 comments

原创文章,转载请注明: 转载自系统技术非业余研究

本文链接地址: vmtouch-系统pagecache查看和操纵器

今天看到dbanote这篇博文介绍的技术清单,里面列到了很多有意思的技术。其中提到了一个小工具vmtouch,主页见这里

vmtouch – the Virtual Memory Toucher
Portable file system cache diagnostics and control
vmtouch is a tool for learning about and controlling the file system cache of unix and unix-like systems. It is BSD licensed so you can basically do whatever you want with it.

我之前写过不少之类的博文,但是基本都是用systemtap,工具也零碎,现在vmtouch比较系统的把功能整合在一起,源码写的虽然简单,但是用到了还是挺管用的。

顺手贴了下vmtouch的使用:
Read more…

Post Footer automatically generated by wp-posturl plugin for wordpress.

Categories: Linux, 工具介绍 Tags: ,

关于ramdisk

December 5th, 2011 Comments off

原创文章,转载请注明: 转载自系统技术非业余研究

本文链接地址: 关于ramdisk

ramdisk是Linux内核带的一个以内存为后备的虚拟设备,以块设备方式提供。 具体功能参见Documentation/ramdisk.txt,代码参见drivers/block/brd.c.

内核在启动的时候会预设几个ramdisk, 初始大小通常为128K的块设备,方便有需要的用户。

$ uname -r
2.6.32-131.0.15.el6.x86_64
$ ls /dev/ram0 -al
brw-rw---- 1 root disk 1, 0 2011-12-02 11:41 /dev/ram0
$ sudo blockdev --getsize /dev/ram0
131072

在实践中ramdisk有如下几个用途:
1. ramdisk的代码写的非常简洁,很容易让你明白块设备如何编写。
Read more…

Post Footer automatically generated by wp-posturl plugin for wordpress.

Categories: Linux, 工具介绍 Tags:

lscpu – CPU architecture information查看器

December 5th, 2011 Comments off

原创文章,转载请注明: 转载自系统技术非业余研究

本文链接地址: lscpu – CPU architecture information查看器

很多时候我们要了解CPU的型号,NUMA架构, L1,L2,L3 Cache大小等信息, 为服务器程序的编写和设置做决策。
Linux下除了 /proc/cpuinfo提供的信息以外,还有intel自己的工具: 参间 CPU拓扑结构的调查: http://blog.yufeng.info/archives/666

但是这些都不是很方便, 同样来自util-linux-ng包的lscpu很清晰的告诉你上面的信息. RHEL 6.1 已经预先安装好了。

man lscpu

DESCRIPTION
lscpu gathers CPU architecture information like number of CPUs, threads, cores, sockets, NUMA nodes, information about CPU caches, CPU family,
model, bogoMIPS, byte order and stepping from sysfs and /proc/cpuinfo, and prints it in human-readable format. It supports both online and
offline CPUs. Alternatively, it can print out in parsable format including how different caches are shared by different CPUs, which can also be
fed to other programs.

我们来演示下:

$ uname -r
2.6.32-131.0.15.el6.x86_64
$ lscpu
Architecture:          x86_64
CPU op-mode(s):        32-bit, 64-bit
Byte Order:            Little Endian
CPU(s):                16
On-line CPU(s) list:   0-15
Thread(s) per core:    2
Core(s) per socket:    4
CPU socket(s):         2
NUMA node(s):          2
Vendor ID:             GenuineIntel
CPU family:            6
Model:                 44
Stepping:              2
CPU MHz:               2394.164
BogoMIPS:              4787.83
Virtualization:        VT-x
L1d cache:             32K
L1i cache:             32K
L2 cache:              256K
L3 cache:              12288K
NUMA node0 CPU(s):     0,2,4,6,8,10,12,14
NUMA node1 CPU(s):     1,3,5,7,9,11,13,15

numa什么的在那里分布很清晰,赞下!

祝玩得开心!

Post Footer automatically generated by wp-posturl plugin for wordpress.

Categories: Linux, 工具介绍 Tags: ,