存档

2014年4月 的存档

使用 O_DIRECT 需要注意的地方

2014年4月30日 没有评论

在之前的 open 使用标记里面, 我提到了 O_DIRECT 标志的使用, 使用 DMA 的方式,
数据不经过内核空间, 直接在用户空间和设备之间传输. 在文章的测试例子里面我放了一个
小错误, 在使用这个标志时读写文件时没有对相关的参数对齐.

实际上, 使用 O_DIRECT 打开的文件要求读写的 bufferbuffer_size 和读写偏移
都要做 I/O 对齐, 对齐的单位为 logical_block_size, 是存储设备能寻址的最小存储
单元, 可以用过下列指令查看该值:

# cat /sys/block/sda/queue/logical_block_size 
512

buffer_size 和偏移的对其都比较好处理, 但是 buffer 地址的对其不太方便, 不过
glibc 提供了 posix_memalign() 函数, 可以返回一个对齐后的 buffer.

下面是使用的小例子:

unsigned char buf[512] = "1234567890";
void *align_buf = NULL;
 
/* 假设 /sys/block/sda/queue/logical_block_size 为 512B */
if (posix_memalign(&align_buf, 512, sizeof(buf)) != 0) {
    perror("memalign failed");
    return;
}
int len = pwrite(fd, align_buf, sizeof(buf), offset);
/* ... ... */

分类: Linux 标签:

简单计算 PI 的方法

2014年4月6日 没有评论

这几天搞一个虚拟机自动迁移的测试, 为了满足在特定 CPU 条件下触发迁移的条件,
需要有进程不断的在消耗 CPU 资源, 这类程序当然可以随便乱写, 来个 for (;;;)
之类的就可以完全满足. 但是, 本着专业的精神, 我决定用计算 π 来达到消耗
CPU 资源的目的.

学过一点级数展开的都知道下面这个著名的 π 的莱布尼茨公式:

PI_Leibniz.png

下面是直接用这个代码的 C++ 测试程序, 当然, 由于我用一个浮点型来保存结果的,
精度不可能搞得离谱, 要获得更高的精度, 麻烦还是用一个大数组吧 🙂

#include <math.h>
#include <iostream>
#include <iomanip>
 
using namespace std;
 
/**
 * 使用传说中的计算 PI 的莱布尼茨公式:
 * pi/4 = 1 - 1/3 + 1/5 - 1/7 + 1/9 - ... + (-1)^n/(2n + 1)
 * 
 */
#define END 7                   /* 精确到小数点后 7 位 */
 
int main(int argc, char *argv[])
{
    double ret = 0;
    long long n = 0;
    int mark = 1;
    double precision = pow(10, -END - 1);
 
    while (1) {
        double f = (double)mark / (2 * n + 1);
        ret += f;
        if ((mark * f) < precision) { /* 计算精度 */
            break;
        }
        n += 1;
        mark = -mark;
    }
 
    cout << "PI ≈ " << setprecision(9) << ret * 4 << endl;
    return 0;
}

另外, 高中时候学过的最简单的:

tan(4/π) = 1
=> 4/π = arctan(1)
=> π = 4 * arctan(1)

所以可以利用 glibc 提供的 API 直接算 PI.

double pi = atan(1) * 4;

这还不是最简单, 最简单的算 π 的方法, 如果熟悉 linux 下 bc 的童鞋应该想到了,
在 bc 中, 用函数 a (x) 可以计算反正切, 设置变量 scale 为想要的精度, 于是用
bc 计算就如此之简单了:

$ echo "scale=10;4*a(1)"|bc -l
3.1415926532

想要消耗 CPU 资源, 你把 scale 设置为 100000 试试.

分类: Programming, Tools 标签: ,

Ceph 中的网络配置

2014年4月3日 没有评论

Ceph 是分布式的文件系统, 由于它是网络文件系统, 它的性能不仅仅受限于物理磁盘的
读写带宽(IOPS), 好的网络架构对发挥 Ceph 的性能也至关重要.

在这里, 我不去详细探讨 Ceph 内部的架构细节(在另外文章我会详细分析), 仅仅通过

Ceph 的配置文件和一些测试来简单研究一下 Ceph 的网络配置.

Ceph 里的数据同步

Ceph 里面的数据同步包括 Monitor 之间的增量同步配置(CRUSH啊这些), osd 之间
的数据冗余. 为了让 Ceph 的性能发挥到最好, 对于数据的传输, Ceph 定义了
public network 和 cluster network, public network 是外部访问用到的
网络(fuse client, rbd client), cluster network 为了 Ceph 内部组件的
数据同步(monitor, osd).

Ceph 的网络配置

前面说过, Ceph 区分外部访问的数据和内部集群使用的数据, 用两个不同的网络配置来
区分: public addrcluster addr.

一般来说, 生产环境中的服务器都有两块以上的网卡, 配置的时候, 一块网卡主要来跑
Ceph 的 对外的数据传输服务(保证足够的 IOPS), 另一块网卡来做集群内部的数据同步.

简单测试

这里的测试仅仅是为了测试上面说过的理论, 不涉及其它 Ceph 的内容. 为了方便计,
只用了一台机器同时跑 monitor 和 osd(这在生产环境中是非常不推荐的).

你可以用我之前的文章讲到的 Ceph 初体验 来搭建测试环境.

附上我的配置文件(注意我的 osd.0 的配置):

root@ceph1:~# cat /etc/ceph/ceph.conf 
[global]
fsid = 382f9965-75ad-403a-b063-4d1fa3e9fb52
mon_initial_members = ceph1
mon_host = 192.168.3.30
auth_supported = cephx
osd_journal_size = 1024
filestore_xattr_use_omap = true
 
[osd.0]
public_addr = 192.168.3.30
cluster_addr = 192.168.3.33

下面的图是该配置在 client 下用 iftop 截到的图, 可以看到数据的传输
走的是 192.168.3.33 这个网络.

ceph-iftop1

改变上面的 osd.0 配置为下面的内容

[osd.0]
public_addr = 192.168.3.33
cluster_addr = 192.168.3.30

用 iftop 可以看到, 数据传输的接口果然变了.

ceph-iftop2

总结

Ceph 的网络配置大体就这么两个参数, 当然使用上要比上面讲的灵活一点. 灵活配置
Ceph 的网络参数可以满足性能上的要求, 甚至在网络带宽远远小于磁盘的 I/O 带宽的
时候(在生产环境中比较少见), 可以给每一个 osd 配置一个网络出口达到最好的性能.

更多具体详细的讨论请参考 Ceph 官网上 网络配置文档.

分类: Storage 标签: ,

Emacs 中默认使用空格来缩进

2014年4月1日 没有评论

我讨厌 TAB, 在 QEMU 的开发中, python 代码的编写, 在和别人共同完成的项目中,
等等, 用 TAB 缩进就是一场灾难.

每次开始接触一种新语言的时候, 都要设置类似一堆

(add-hook 'ruby-mode-hook (lambda ()
                            (setq indent-tabs-mode nil)))

今天无意中在一个 elisp 代码文件里面看到有这么一个函数:

; Set the default value of variable VAR to VALUE.
(setq-default indent-tabs-mode nil)

这下, 妈妈再也不用担心我的缩进问题了.

分类: Emacs 标签: