Saturday, February 16, 2013

[Linux] Linux上NUMA相关的命令

查看NUMA的memory设置等

$ cat /sys/devices/system/node/node*/meminfo 
Node 0 MemTotal:       16777216 kB
Node 0 MemFree:           14312 kB
Node 0 MemUsed:        16762904 kB
...
Node 0 HugePages_Total:  1000
Node 0 HugePages_Free:    744
Node 0 HugePages_Surp:      0
Node 1 MemTotal:       16763940 kB
Node 1 MemFree:         5289568 kB
Node 1 MemUsed:        11474372 kB
...
Node 1 HugePages_Total:  1000
Node 1 HugePages_Free:   1000
Node 1 HugePages_Surp:      0

查看NUMA统计数据

比如多少local node reference, 多少foreign node reference
$ cat /sys/devices/system/node/node*/numastat
numa_hit 759046092
numa_miss 333483705
numa_foreign 236930883
interleave_hit 12690
local_node 746065583
other_node 346464214
numa_hit 506048971
numa_miss 236930883
numa_foreign 333483705
interleave_hit 12713
local_node 507619074
other_node 235360780

使用numactl设置task的numa属性

prefer(并非强制)使用numa node0来执行my_app
$ numactl --preferred=0 ./my_app arg1 arg2
强制使用numa node0 的local cpu和local memory来执行my_app
$ numactl --cpubind=0 --membind=0 ./my_app arg1 arg2

Saturday, February 02, 2013

[Latex] 编辑文档的tips

watermark

有时候我们需要在每一页打上一个水印, 这时候可以使用draftwatermark这个package.
\usepackage{draftwatermark}
\SetWatermarkText{this is a draft}
\SetWatermarkScale{0.5}
更多的参数可见 http://texblog.org/tag/draftwatermark/还有一个叫draftcopy的package也是可以做类似的事情, 但是似乎在我这里有问题

Friday, January 18, 2013

[Latex] 修补Rubber

Rubber停更很久了,所以已经从我的Latex编译好帮手,堕落为了pain of ass.


bibtex 问题



比如编译tex文件的时候会出现如下错误导致bib文件不能正确的编译出来:
running post-compilation scripts...
running BibTeX on paper...
There were errors making the bibliography.
There were errors compiling paper.
这是因为, rubber是这样调用bibtex的
Popen(['bibtex /your/path/to/tex/file'])
而在新的bibtex中, 不能接受绝对路径作为输入参数

解决方法: 在bibtex.py(如果你的rubber是使用brew安装的话, 其路径为/usr/local/Cellar/rubber/20100306/share/rubber/rubber/latex_modules/bibtex.py)中修改run这个函数, 在调用Popen前加上:
cmd = ["bibtex", "-min-crossrefs=1000", msg.simplify(self.base)]
process = Popen(cmd, stdout=PIPE, stderr=PIPE)

Thursday, September 27, 2012

[Linux] Bash tips

bang bang


$ !!
执行上一个命令
$ !x
执行上一个以"x"开头的命令
$ !xyz
执行上一个以"xyz"开头的命令

bang dollar

$ cat ~git/repository/foo.git/hooks/post-receive
$ vi !$
!$会被扩展为上一个命令的最后一个argument
类似的!*会被扩展为上一个命令的所有argument

dollar bang

$ ./exe_something &
$ LAST_PID= $!
$!为上一个命令的PID

dollar question-mark

$ ./exe_something 
$ echo $?
$?为上一个命令的exit状态

Sunday, August 12, 2012

[Linux] backtrace

使用gdb可以在断点处停下来从而允许我们查看call strack. 可是有时候我们希望在程序里自动的显示当前的call stack --- 比如在异常的时候写到log当中.这时候就需要使用backtrace:
1 使用backtrace
http://www.gnu.org/software/libc/manual/html_node/Backtraces.html
显示出当前call stack 的backtrace: 每一行为一个frame对应的binary和在binary中的地址

Obtained 7 stack frames.
/home/foo/bench_cache() [0x4050f5]
/home/foo/bench_cache() [0x405f4e]
/home/foo/bench_cache() [0x407d8d]
/home/foo/bench_cache() [0x40283a]
/home/foo/bench_cache() [0x402e13]
/lib/libc.so.6(__libc_start_main+0xfe) [0x7fad2481dd8e]
/home/foo/bench_cache() [0x401eb9]
2 使用addrline
addr2line将binary的相对offset地址转化为对应的文件以及行数
$ addr2line -e bench_cache -f 0x4050f5
print_backtrace
/home/foo/bench_util.h:28
参数:
  • -e binary, 指定对应的binary
  • -f, 显示对应的function名称

gmail advanced search tips

http://support.google.com/mail/bin/answer.py?hl=en&answer=7190&topic=1668965&ctx=topic

Saturday, August 11, 2012

Raspberry Pi

下载并解压, 得到 2012-07-15-wheezy-raspbian.img 你需要把这个img考到你的SD卡当中. 在MacOS中:
$ diskutil list
比如你的SD是/dev/disk1的话
$ diskutil unmountDisk /dev/disk1
$ sudo dd if=2012-07-15-wheezy-raspbian.img of=/dev/disk1
可能会比较久--比如我class 4的一张SD卡考了足足有40来分钟

用Resperberry Pi跑DNS服务


用Resperberry Pi上跑unblock youku服务


$ sudo apt-get install node.js npm #安装node.js和npm
$ sudo npm install -g ub.uku.js #安装unblock youku的server程序
$ ub.uku.js #运行unblock youku的server

把服务blah (比如unblock youku)添加到开机服务中


使用update-rc
$ update-rc.d blah defaults

http://www.debian-administration.org/articles/28

Tuesday, July 10, 2012

建立/使用gitotlite来搭建自己的git 服务器


建立Gitolite服务器


我使用了gitolite来建立自己的git server http://wiki.dreamhost.com/Gitolite

在Gitolite服务器上添加一个新的repository


gitolite的admin操作不在服务器本机上进行. 相反, 你需要先把gitolite的admin相关repo给clone下来, 在你本地修改以后, push回去
$ git clone git@my_git_server_address:gitolite-admin
然后修改conf/gitolite.conf这个文件, 比如我的这个文件内容为
repo gitolite-admin
    RW+     =   apc999

repo my_fav_repo
    RW+     =   apc999
然后把改变给push回去
$ git add conf/gitolite.conf
$ git commit . -m "add a new project"
$ git push

把本地文件导入


$ cd /your/path/to/push
$ git init
$ git add .
$ git commit -m "init import"
$ git remote add origin git@my_server:my_fav_repo.git
$ git push origin master

Saturday, July 07, 2012

Git: funny ref

使用git的时候发现了这样的错误:
$git pull
error: * Ignoring funny ref 'refs/remotes/origin/master (sourcery's conflicted copy 2012-05-30)' locally
开始以为是我git的local copy有问题, 后来发现问题出在server端. 实际上在server的repositories/myrepo.git/refs/heads目录下发现一个叫master (sourcery's conflicted copy 2012-05-30)的文件. 于是把此文件删除后, client端就恢复正常了.

Tuesday, June 19, 2012

[Python] with语句

with statement in Python

http://effbot.org/zone/python-with-statement.htm
with open("foo.txt") as f:
    for line in f:
        print line
        # do sth else
使用with来打开文件的好处是, 不用在调用f.close()

Friday, June 15, 2012

Libevent笔记

参考
Libevent源码分析
libevent源码深度剖析
libevent的man

一个最简单的例子
/* 初始化libevent系统. */
event_init();

/* 准备ev_foo这个事件, 这个事件监听my_fd这个file descriptor, 当my_fd上出现EV_READ这个事件时候, 触发on_foo这个函数 */
event_set(&ev_foo, my_fd, EV_READ|EV_PERSIST, on_foo, NULL);
/* schedule这个事件 */
event_add(&ev_foo, NULL);

/* 进入event循环. */
event_dispatch();

Wednesday, June 06, 2012

YCSB notes

参数


requestdistribution: 可以为uniform(默认),zipf,latest等. 这几种(特别是zipf和latest的区别参见这里. 大体上说,latest和zipf的区别是zipf的popular key可能是任意的呃;而latest的popular key是最近insert的.

使用例子


生成load phase的trace,用来初始化被测试的数据库
${YCSB_HOME}/bin/ycsb load basic -P ${YCSB_HOME}/workloads/workloada -P ./my-workloads-setting.dat
生成exec phase的trace,正真用于测试的trace
${YCSB_HOME}/bin/ycsb run basic -P ${YCSB_HOME}/workloads/workloada -P ./my-workloads-setting.dat

参考


YCSB Core Properties

Thursday, May 31, 2012

[Linux]那些真心烦人的GCC error/warning

众所周知, GCC不喜欢说人话. 很多warning/error message非常的confusing. 这里笔记一下我常常遇到的几个问题.
参考: GCC Warnings

no previous prototype for ‘foo’ [-Werror=missing-prototypes]
如果一个函数仅仅在一个文件中使用,函数定义时请使用static关键字修饰使其只能在本文件中可见,避免和namespace中其他文件定义的同名函数冲突. 如果会在多个文件中会被用到, 请将其函数原型放进一个.h文件中---这是最常见的C的用法.
注意如果foo这个函数没有输入参数, 在prototype里,请写成比如int foo(void)这样. 不然gcc会不认为int foo()是prototype

implicit declaration of function ‘foo’ [-Werror=implicit-function-declaration]
出现这个报错是由于你使用了一个函数,但是gcc不知道哪里去找这个函数declaration.
通常是由于没有include对正确的.h文件. 也有可能.h文件是正确的, 但是没有enable正确的宏. 比如在Linux上要使用CPU_SET这个宏, 除去include sched.h外, 还必须定义__USE_GNU这个宏.
#define __USE_GNU
#include <sched.h>

‘foo’ defined but not used [-Werror=unused-function]
有时候在调试程序过程中, 会暂时屏蔽一些函数的调用,从而得到如上的错误而防止编译. 为了"骗过"GCC, 你可以加上如下function attributes.
static __attribute__ ((unused)) void foo(){
...
}

Thursday, May 10, 2012

[Linux]优化网卡性能

参考
Tuning 10Gb network cards on Linux
Setting IRQ Affinity for Red Hat Summit 10G Ethernet Tuning
1 设定网卡IRQ affinity.
设置IRQ affinity就是将同一设备的IRQ绑定到同一个(组)CPU上.
比如你可以通过mpstat这个命令来查看当前CPU处理IRQ的分配. 比如查看所有CPU, 每隔5秒刷新一次:
$ mpstat -P ALL 5
如果要改变某个IRQ的CPU affinity, 可以通过写相关IRQ/proc/irq/路径来实现. 比如
$ echo 80 > /proc/irq/177/smp_affinity
这个命令将IRQ 177的affinity掩码改为0x80
一个实例:
eth5为一个10G网卡,所以系统会对这块网卡产生N个TxRx队列,N为core数目.所以我当前机器上有24个core,所以有24个队列.我希望将每个队列的mask均为0x00ffffff,也就是所有的core都可能处理eth5产生的IRQ.有时候我们希望讲同一个设备的IRQ绑定在同一个(组)core上,从而提高cache的性能. 这里附上一个寻找并显示某个网卡设备(比如eth0, eth5)相关的IRQ以及其smp_affinity mask的脚本
#!/usr/bin/python

import os
import sys 

names = []

args = sys.argv[1:]
while args:
    names.append(args[0])
    args = args[1:]

for dir_name in os.listdir('/proc/irq/'):
    if not os.path.isdir('/proc/irq/%s' % dir_name):
        continue
    for file_name in os.listdir('/proc/irq/%s' % dir_name):
        found = False
        for idx, name in enumerate(names):
            if file_name.startswith(name):
                found = True
        if not found: continue
        path = '/proc/irq/%s/smp_affinity' % dir_name
        print path, file_name
        print 'mask = %s' % (open(path).read().strip())
        break
运行这个脚本:
$ sudo ./get_smp_affinity.py eth5
/proc/irq/127/smp_affinity eth5:lsc
mask = 00ffffff
/proc/irq/126/smp_affinity eth5-TxRx-23
mask = 00ffffff
...
...
/proc/irq/103/smp_affinity eth5-TxRx-0
mask = 00ffffff
这里我还有一篇post介绍如何在C当中设定CPU affinity.[Linux]使用C设置线程的CPU affinity. 在一个试验中, 我用如上方法把一个24-core的CPU中core0到core5设定为处理10Gb网卡的IRQ, 而把我的程序线程绑定在core6以上,从而取得了最大的throughput.

2 Ethernet Interrupt coalescing
这篇"Interrupt coalescing"解释了什么是Interrupt coalescing. ethtool 是用来显示以及修改网卡的设定的工具. ethtool -c选项可以用来显示网卡的Interrupt coalescing参数. 比如要显示eth0的参数:
sudo ethtool -c eth0
Coalesce parameters for eth0:
Adaptive RX: off  TX: off
stats-block-usecs: 999936
sample-interval: 0
pkt-rate-low: 0
pkt-rate-high: 0

rx-usecs: 18
rx-frames: 12
rx-usecs-irq: 18
rx-frames-irq: 2

tx-usecs: 80
tx-frames: 20
tx-usecs-irq: 18
tx-frames-irq: 2

rx-usecs-low: 0
rx-frame-low: 0
tx-usecs-low: 0
tx-frame-low: 0

rx-usecs-high: 0
rx-frame-high: 0
tx-usecs-high: 0
tx-frame-high: 0
参数解释
rx-usecs和rx-frames控制每一个RX DMA channel的RX interrupt速率. 每当累计接收到rx-frames这么多个,或者rx-usecs这么长时间过后, 一个RX interrupt就会被产生. 对于low latency要求的application, 尽量将rx-usecs设置小. 而对于bulk traffic, 设置大.
rx-frames-irq 控制最多一个RX interrupt可以处理多少个RX packets
将eth0的rx queue的timer设为1000 us
sudo ethtool -C eth0 rx-usecs 1000

3 TCP/UDP parameter tuning
(待续...)

Sunday, May 06, 2012

msgpack笔记

简介

msgpack官方网站
msgpack 类似于protocol buffer, 是一个把object serialize的库.
msgpack + msgpack-rpc 类似于 thrift

安装

MacOS上安装C++的msgpack, msgpack-rpc
$ brew install msgpack
$ brew install msgpack-rpc
MacOS上安装GO的msgpack-go, msgpack-rpc
$ go get github.com/msgpack/msgpack-go
$ go get github.com/msgpack/msgpack-rpc/go/rpc

Friday, May 04, 2012

[Linux]使用C设置线程的CPU affinity

随着多核机器的越来越普及. 对线程设置CPU affinity变得对性能越来越重要.linux提供的affinity设置功能可以将一个线程绑定到一个CPU的集合上(该集合可以包括一个或者多个CPU), 使得这个线程只被调度在属于给定CPU集合中的CPU上执行.
与CPU集合描述有关的几个宏:
  • CPU_ZERO():清空一个cpu_set_t类型的集合
  • CPU_SET()与CPU_CLR(): 将某个特定CPU加到某个集合或者从一个集合中删除.
  • CPU_ISSET(): 返回一个给定CPU是否在一个给定集合中.
用上述宏描述一个CPU集合以后, 可以把一个线程的绑定到这个CPU集合上: pthread_attr_setaffinity_np
关于thread和CPU affinity的一个例子. 这个程序里面函数cpunum得到当前机器cpu数目
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <sched.h>
#include <pthread.h>

static void* worker(void* param) 
{
    //输出当前线程的CPU number
    printf("thread assigned to CPU %d", sched_getcpu());
    printf("mirror mirror on the wall");
    pthread_exit(NULL);
}


//返回当前CPU的core数目: 最多到32
static int cpunum()
{
    cpu_set_t cpuset;
    CPU_ZERO(&cpuset);
    sched_getaffinity(0, sizeof(cpuset), &cpuset);
    int num = 0;
    for (int i = 0; i < 32; i++)
    {
        if (CPU_ISSET(i, &cpuset))
            num++;
    }
    printf("%d cores on this machine");
    return num;
}

int main(int argc, char** argv) 
{
    cpu_set_t cpuset;
    pthread_t threads[10];
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

    for(int i = 0; i < 10; i++) {
        //将第i个线程绑定至第i个core上执行
        CPU_ZERO(&cpuset);
        CPU_SET(i, &cpuset);
        pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpuset);

        int rc = pthread_create(&threads[i], &attr, worker, NULL);
        if (rc) {
            exit(-1);
        }
    }

    pthread_attr_destroy(&attr);

    /* 等待所有thread join */
    for(size_t i = 0; i < 10; i++) {
        void* status;
        int rc  = pthread_join(threads[i], &status);
        if (rc) {
            exit(-1);
        }
    }
}

Wednesday, April 11, 2012

[Emacs] Emacs server 和client

如果已经打开了一个Eamcs的GUI, 想在命令行里让这个Emacs打开某个文件, 可以使用Emacs Server 的功能 在Emacs里键入
M-x server-start
或者在.emacs文件中加入
(server-start)
然后在命令行里就可以使用
emacsclient your-target-file
使得Emacs打开你要的文件. 不过这个命令会blocking(等待从Emacs返回). 如果需要其立即返回, 可以
emacsclient -n your-target-file
参考 Using emacs as server

Saturday, April 07, 2012

[Linux] 使用huge page

Linux在x86下默认的page size是4KB. 但是对很多应用(特别是很多数据库方面的应用)来说,这个page size值过小导致了很多TLB miss, 从而降低了系统的性能.所以这个时候我们希望使用hugepage来减少TLB miss. x86下典型的hugepage可以达到2MB. 查看当前系统hugepage的大小和使用情况
$ cat /proc/meminfo |grep Huge
HugePages_Total: 0
HugePages_Free:  0
HugePages_Rsvd:  0
HugePages_Surp:  0
Hugepagesize: 2048 kB
查看当前hugepage的数目
$ cat /proc/sys/vm/nr_hugepages 
0
#或者使用sysctl工具
$ sysctl vm.nr_hugepages 
0
设置可以使用的hugepage的数目为512 (这样你可以使用总共为1G大小的hugepage memory)
$ echo 512 > /proc/sys/vm/nr_hugepages 
#或者使用sysctl工具
$ sysctl -w vm.nr_hugepages= 512
这时候再看一下hugepage的使用情况
$ cat /proc/meminfo |grep Huge
HugePages_Total: 512
HugePages_Free:  512
HugePages_Rsvd:  0
HugePages_Surp:  0
Hugepagesize: 2048 kB
Ref: http://linuxgazette.net/155/krishnakumar.html

Memcached笔记

编译:

$ ./autogen.sh
$ ./configure
$ make
运行server
$ ./memcached -p 9527
这样memcached会在server上监听9527这个端口, 你也可以制定一个其他端口 (默认是11211) 如果需要看到多一些输出信息, 可以加上参数 -v -vv 或者-vvv
-p 端口号使用的TCP端口。默认为11211
-U 端口号使用的UDP端口。默认为11211
-m 内存大小(MB)最大内存大小。默认为64M
-t 线程数目使用多少个工作线程. 默认为4
-v,-vv,-vvv用very vrebose模式启动,调试信息和错误输出到控制台
-d作为daemon在后台启动

测试:

在本机用telnet运行client


$ telnet localhost 9527
set key1 14 0 1
a
STORED
get key1
VALUE key1 14 1
a
END
一些内部机制:

内存管理:

memcached将内存划分成1MB大小的单位,称作slab. 每个slab划分成许多相同大小的slot来存储key-value pair. 但是每个slab可能有不同的等级--根据这个等级,slot的大小不同.
图片来源:http://nosql.mypopescu.com/post/13506116892/memcached-internals-memory-allocation-eviction

LRU算法:

memcached 使用 LRU per slab class, not globally.

item:

每一个key-value pair的metadata存储在一个item结构当中
  • it_flags: 可以是如下几个标志的组合
    • ITEM_LINKED: 此item加入了LRU list
    • ITEM_CAS: 我暂时还不知到...
    • ITEM_FETCHED: 此item被access过
    • ITEM_SLABBED: 此item已经被free了
  • next, prev: per-slab LRU是用一个双向链表来实现的, 这两个指针就指向链表中前后item
  • h_next: 指针, 指向每个item在hashtable中下一个item(该hashtable使用chaining来实现)
  • time: 最近一次访问时间(用于检查该item是否expire)
  • exptime: expire时间(记住memcached是一个cache)
参考

memcached全面剖析–PDF总结篇
memcached源码分析(一): memcached.c主函数分析
memcached源码分析(二): settings结构体分析
memcached源码分析(三):socket建立过程分析
memcached源码分析(四):事件状态机分析
memcached源码分析(五):数据保存及内存管理
memcached源码分析(六):总结几个小点 Memcached internals

Thursday, March 01, 2012

[Python]一些数的进制转换

整数和其binary形式的string相互转换:
>>>bin(4)
'0b100'
>>>int('0b100', 2)
4
整数和其hex形式的sting相互转换:
>>>hex(14)
'0xe'
>>> int('0xe', 16)
14