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

Wednesday, February 01, 2012

BCD

You can change your BCD configuration (parameters used by bootmgr, boot applications, and winload) by BCDedit in command line or editing the registry (if not changeable by BCDedit)

1 Show all entries in a BCD store
bcdedit -enum all

2 Enable debug
bcdedit -bootdebug {bootmgr} on  //enable debugging of Windows Boot Manager
bcdedit -bootdebug on            //enable debugging of boot loader
Bcdedit -debug on                //enable debugging of operating system

3 Enable bootlog (cause windows to write a log of the boot to %SystemRoot%\Ntbtlog.txt In your VM, edit registry (HKLV\System\CurrentControlSet\Control\) Change value of "SystemStartOptions" 4 Turn off driver verification
bcdedit -set loadoptions DDISABLE_INTEGRITY_CHECKS
bcdedit -set TESTSIGNING ON


configure for other BCD files

(1) check the for "Windows Boot Loader"
bcdedit /store c:\winpe_amd64\ISO\boot\BCD -enum all
(2) turn the debug option on (see output in WinDbg), is sth like {7619dcc8-fafe-11d9-b411-000476eba25f} in your "Windows Boot Loader" session
bcdedit /store c:\winpe_amd64\ISO\boot\BCD -set  debug on
(3) turn the bootdebug option on (break in WinDbg during boot), is sth like {7619dcc8-fafe-11d9-b411-000476eba25f} in your "Windows Boot Loader" session
bcdedit /store c:\winpe_amd64\ISO\boot\BCD -set  bootdebug on
Boot Options in Windows Vista and Later: http://msdn.microsoft.com/en-us/library/windows/hardware/ff542273(v=vs.85).aspx BCD Boot Options Reference: http://msdn.microsoft.com/en-us/library/windows/hardware/ff542205(v=vs.85).aspx

Sunday, January 29, 2012

WinSock Kernel

Winsock Kernel http://msdn.microsoft.com/en-us/library/windows/hardware/ff571084(v=vs.85).aspx Sample code: http://www.rohitab.com/discuss/topic/37876-winsock-kernel/ http://hi.baidu.com/kernelkit/blog/item/e8a93060e1ad6a41eaf8f856.html

Monday, January 02, 2012

[Linux]静态库,动态库

.o, .a, .so 这些的区别
Static, Shared Dynamic and Loadable Linux Libraries
Shared libraries and static libraries
Creating a shared and static library with the gnu compiler [gcc]

创建静态库(.a)
比如为了把foo1.o, foo2.o这两个obj文件打包成一个静态库叫做foo.a
$ gcc -Wall -c foo1.c foo2.c
$ ar -cvq libfoo.a foo1.o foo2.o
创建动态库(.so)
首先用-fPIC选项告诉gcc生成position independant code的.o文件
$ gcc -Wall -fPIC -c foo1.c foo2.c
接着使用-shared选项生成.so文件
$ gcc -shared -Wl,-soname,libfoo.so.1 -o libfoo.so.1.0.1  foo1.o foo2.o
使用库(.a,.so)
假设生成的libfoo.a或者libfoo.so都在/path/to/libfoo这个路径下,可以通过"-L/path/to/libfoo"这个选项告诉gcc去这个路径下去寻找需要的库.此外再通过-lfoo这个选项告诉gcc去寻找libfoo.a或者libfoo.so.
$ gcc -Wall -L/path/to/libfoo your-program.c -lfoo -o your-program
默认情况下/usr/lib, /usr/local/lib这个几个路径一般会被首先查找.如果需要gcc去其他默认路径下查找(比如/path/to/libfoo),也可以通过把/path/to/libfoo添加LD_LIBRARY_PATH环境变量中
强制使用静态库(.a)
如果在/path/to/libfoo下同时存在libfoo.a和libfoo.so, libfoo.so会被优先使用.可以用-static选项强制gcc避免使用动态库
$ gcc -Wall -static -L/path/to/libfoo your-program.c -lfoo -o your-program
libtool
configure关于静态动态库的参数
  • --enable-shared: 编译动态库(默认为yes)
  • --enable-static: 编译静态库(默认为no)
有时"--enable-static"会以尝试静态的方式编译所有dependent的库,产生undefined reference这样的错误.
$ ./configure --enable-static
warning: Using 'dlopen' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
/usr/lib/gcc/x86_64-linux-gnu/4.6.1/../../../x86_64-linux-gnu/libcrypto.a(c_zlib.o): In function `bio_zlib_free':
(.text+0x4f): undefined reference to `inflateEnd'
可以以--enable-static=libfoo这样的方式指定gcc只以static的方式编译libfoo.其他依赖的库还是以默认的shared方式编译(http://sourceware.org/autobook/autobook/autobook_85.html)
$ ./configure --enable-static=libfoo
libtool在link模式下有选项:
  • -shared
  • -static
  • -all-static