Fork me on GitHub

Take a look at Level source code

最近看了一点leveldb源码,了解一下实现机制。

之前也看过leveldb相关介绍以及别人的分析blog,已经有了一定了解。leveldb如其名,按照层级来组织数据,数据从内存到磁盘一层一层迁移。在内存中是通过skiplist来管理数据,而磁盘上则是一种名为SSTable(Sorted Strings Table)的结构来存储数据的。

阅读更多...

Makefile获取依赖的源文件

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
exclude="_test"
#exclude="___"
src=$(wildcard *[^$(exclude)].c ./subs/*.c)

files=$(notdir $(src))

obj=$(patsubst %.c,%.o,$(files) )

all:
@echo $(src)
@echo $(files)
@echo $(obj)
@echo "end"

wildcard通过通配符来匹配文件并将结果展开,第一个参数排除了_test.c的文件。
notdir去掉src中的目录,只保留文件名
patsubst进行替换,把.c换成.o
上面代码参考Makefile中的wildcard用法这篇blog,稍微修改了下。

UPDATE

上面的代码

1
2
3
exclude="_test"
#exclude="___"
src=$(wildcard *[^$(exclude)].c ./subs/*.c)

其实有点问题,*[^$test].c这个正则只能过滤.c之前是’‘,’t’,’e’,’s’这4个字符的文件名,达不到想要的目的。
需要修改一下,对src进行替换

$(patsubst %_test.c,, $(src))

这样就把文件列表中含_test.c的去掉了。修改后为

1
2
3
4
5
6
7
8
9
10
11
12
src :=$(wildcard *.c ./subs/*.c)
src :=$(patsubst %_test.c,,$(src))

files :=$(notdir $(src))

obj :=$(patsubst %.c,%.o,$(files) )

all:
@echo $(src)
@echo $(files)
@echo $(obj)
@echo "end"

C语言INT_MIN定义的问题

关于c语言INT_MIN定义的问题

最近看到一段代码

1
2
#define INT_MAX 2147483647
#define INT_MIN (-INT_MAX - 1)

INT_MIN的值应该为 -2147483648,为什么不直接定义呢?原因参考Jack47的blog:C语言中TMin的写法这篇文章。

个人理解为C语言在处理程序中常量时,符号-和后面的值是分开处理的,先处理字面值,然后将-作为一元运算符。处理字面值的时候会决定这个常量的类型,基本的规则是选能容纳字面值的最小类型。如32位系统,2147483648这个值决定为unsigned int,如果使用#define INT_MIN (-2147483648)这个定义,INT_MIN类型为unsigned int。

写了一段代码验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>

#define INT_MAX 2147483647
#define INT_MIN (-INT_MAX - 1)

// TMIN is unsigned int
#define TMIN (-2147483648)

int main(){
int i = 1;
if (i > TMIN)
printf("%d > tmin\n", i);
else
printf("%d < tmin\n", i);
if (i > INT_MIN)
printf("%d >INT_MIN\n", i);
printf("%d\n",sizeof(TMIN));
}

运行结果为

1 < tmin
1 >INT_MIN
4

补充:

CSAPP的补充材料waside-tmin.pdf

上面的例子说明了不同格式字面值在C90和C99下面的类型确定的规则,C90 32位下类型为unsigned,就会产生上面程序的结果。

对于这种会产生不同行为的代码最好避免.

Notes About Kafka

consumer offset commit

使用kafka的python api时遇到了offset回滚的问题,因为最初使用了autocommit参数,发现有时会重复取记录,发现autocommit是批量提交,并且有offset回滚的问题,具体原因未发现,解决方法是手动调用commit函数提交,经过测试手动调用没有出现offset回滚的问题。

partition

一开始为了简单只使用了一个分区,consumer都从一个leader取数据,请求压力都在一台机器。使用不同分区策略可以分散topic的leader,还可以灵活处理不同数据。

fetch msg

MaxWaitTime 请求最大等待时间,MinBytes 请求消息的最小字节数,通过这2个参数可以调整你获取数据时的等待策略,最简单的做法就是不等待,没数据直接返回。

zookeeper

由于硬盘限制,把kafka和zookeeper的日志目录放在了同一个磁盘,而且磁盘的性能不是很好,造成了kafka写数据效率低下,每次写数据只有几百k。zookeeper网站上对这2个配置有Notes说不要把他们放在繁忙的磁盘设备上,会影响其他程序写磁盘的性能,最好这2个目录都分开存放不同设备。简单看了一下,dataDir下存的是snapshot文件,dataLogDir存的是log文件,应该是zookeeper把内存数据持久化到这2种文件中了,而且持久化操作很频繁且写的数据很少,会影响kafka写日志。

磁盘参数

在排查磁盘io高的问题时用到了iostat -d -x命令,在排查时主要关注w/s、wkB/s、rkB/s,对于扇区没怎么关注,rsec/s wsec/s avgrq-sz这几个参数反应磁盘操作扇区的情况,当磁盘利用率高且iowait高,而平均扇区低也就意味着磁盘把大量时间用于磁盘寻道,你可能需要考虑是不是有大量随机写磁盘的操作。

重入与线程安全

在stackoverflow上看的的关于可重入与线程安全的区别:

These functions are not reentrant. They are thread-safe. There’s a big difference. Functions that are reentrant are automatically thread-safe, but thread-safe functions can still deadlock (or worse) if called again from the same thread they’re already running in (for example from a signal handler).

函数可重入很自然会觉得该函数是线程安全的,既然能被其他流程中断并可调用自身也就可以被多个线程同时调用。但是线程安全是不是可重入有点模糊,上面说了一种情况,当重复调用一个线程安全的函数,并且函数中有锁就有可能发生死锁,表明线程安全不一定可重入。看来重入的要求比线程安全要更严格一点。

附带查了查关于Posix的标准io操作,Posix标准要求操作字符流的函数实现为可重入,但是各个实现为了性能方面的考虑都没有实现为可重入的,这些函数有潜在不安全。但是又说明:

all standard I/O functions that reference character streams shall behave as if they use flockfile() and funlockfile() internally to obtain ownership of the character streams

表明它们应该是线程安全的。

  • © 2015-2024 RivenZoo
  • Powered by Hexo Theme Ayer
  • PV: UV:

请我喝杯咖啡吧~

支付宝
微信