Archive for the Linux category

9月 4th, 2011

ESTABLISHEDセッションが残り続ける

Posted in Linux by admin

ソケット接続するプログラムを作成する場合、setsockoptを使用しぜ TCP接続ぜ keep-aliveパケットを送るようにする。これをしないと、接続中ぜ LANケーブルが抜けた場合などぜ ESTABLISHED状態のセッションが残り続ける事になる。netstat -aonコマンド(–timers)ぜ keepaliveのタイマーを閲覧できる。(最後のカラムがTimer)

keep-alive適用前

tcp 0 0 0.0.0.0:80 192.168.100.1:52549 ESTABLISHED off (0.00/0/0)

keep-alive適用?

tcp 0 0 0.0.0.0:80 192.168.100.1:40201 ESTABLISHED keepalive(1767.52/0/0)

以? のようぜ keep-aliveパケット送信を有効にする。

#define CONN_SO_KEEPALIVE 1
~
on = CONN_SO_KEEPALIVE;
setsockopt( lsock->iom->fd, SOL_SOCKET, SO_KEEPALIVE, (void*)&on, sizeof(on) );

keep-aliveを最初に投げ始めるまでの時間、keep-aliveパケットを投げる間隔、keep-aliveパケットを投げリトライする回数などの指定は、カーネルパラメータにて設定する。

net.ipv4.tcp_keepalive_time = 7200
net.ipv4.tcp_keepalive_intvl = 75
net.ipv4.tcp_keepalive_probes = 9

元のプログラムの? 更なしぜ glibcベースのバイナリ動的実行可能ファイルぜ TCPキープアライブ機能を有効ぜ libkeepaliveというライブラリもあるようです。
http://tldp.org/HOWTO/html_single/TCP-Keepalive-HOWTO/

7月 16th, 2010

配列の初期化パフォーマン゜ (x86_64 memset緜 )

Posted in Linux by admin

 以前、Solaris(Sparc)環? 上ぜ “Sun Studio C Compiler”でコンパイルしたプログラムによる配列の初期化パフォーマン゜ の? 証のところぜ memsetの話題を挙げましたが、64bit Linux(x86_64)環? においても、あるバージョンぜ glibcで同関数パフォーマンスに影響を圏 ぼす可能性が゜ かったので調査してみました。前回同様、1024バイト配列ぜ memset初期化を1,000,000回ループさるプログラムの処理時間で? 較を行いました。また、様々なバイトの配列でも試してみました。以? がその? 果です。

■glibc-2.5-24.x86_64
1024バイト配列:		平均  0.048秒
1024*10バイト配列:		平均  0.436秒
1024*100バイト配列:		平均  6.331秒
1024*117バイト配列:		平均  7.385秒
1024*118バイト配列:		平均 36.644秒
1024*1000バイト配列:	平均304.943秒
■glibc-2.5-42.x86_64
1024バイト配列:		平均 0.029秒
1024*10バイト配列:		平均 0.216秒
1024*100バイト配列:		平均 5.187秒
1024*117バイト配列:		平均 6.074秒
1024*118バイト配列:		平均 6.130秒
1024*1000バイト配列:	平均51.958秒

 上記の? 果のように、glibc-2.5.24のパフォーマンスが2.5.42よりも劣化するということ。更に配列のサイ゜ 1024*118を超えた時点で、パフォーマンスが著しぜ 劣化するという点が挙げられます。おそらぜ 2.5.32以降で対応した修正パッケージとパッチが以? のものだと思゜ れます。memsetのコードは朮 どアセンブラなので、修正内容はあまり理解出来ません。コメントにぜ PIC(Position Independent Code)の文字が見られ、もしかしたらgccオプション「-fPIC」が使用される共有ライブラリでは更に性能が異なるのかもしれません。

http://rhn.redhat.com/errata/RHBA-2009-0080.html
an optimized memset() routine for AMD64 and Intel 64 systems has been added.
glibc-rh437394.patch

2008-08-14  Ulrich Drepper  <drepper@redhat.com>
	* sysdeps/x86_64/memset.S: Reduce size of tables for PIC.
2008-02-26  Harsha Jagasia  <harsha.jagasia@amd.com>
	* sysdeps/x86_64/memset.S: Rewrite non-SSE code path as tuned for AMD
	Barcelona machine.  Make default fall through branch of
	__x86_64_preferred_memory_instruction check as the integer code path.
2007-10-15  Ulrich Drepper  <drepper@redhat.com>
	* sysdeps/x86_64/memset.S: Use __x86_64_shared_cache_size.
	Always define bzero.
	Remove non-glibc code.
7月 13th, 2010

OSS Message Pedia

Posted in Linux by admin

 OSSのメッセージを集めたOSS Message Pedia(http://ossmpedia.org)というサイトがありました。これぜ OSS(Open Source Software)が出力するメッセージのオンライン? 典で、システムで表示されているエラーメッセージや警告メッセージを検索して、その? 味と対処方? などの情報を引き出すことが出来るようになっています。例えば、以? のようぜ dmesgが出力されている場合、検索? 果からある程度の情報が引き出せます。

# dmesg | grep War
bonding: Warning: either miimon or arp_interval and arp_ip_target module parameters must be specified, \
otherwise bonding will not detect link failures! see bonding.txt for details.
bonding: bond0: Warning: failed to get speed and duplex from eth0, assumed to be 100Mb/sec and Full.
bonding: bond0: Warning: failed to get speed and duplex from eth1, assumed to be 100Mb/sec and Full.

メッセー゜ 1行目の? 索? 果
http://ossmpedia.org/messages/linux/2.6.9-34.EL/50981.ja

メッセー゜ 2,3行目の? 索? 果
http://ossmpedia.org/messages/linux/2.6.9-34.EL/50896.ja

 1行目のメッセージは、Bondingのリンク監? パラメータ未設定の警告。ARP監? のパラメータ? arp_ip_target, arp_interval)は適用していますが、MIIリンク監? のパラメータ? miimon, updelay)は? けていない状態でした。どちらにしてもこぜ Warningは出力されるようです。

# cat /proc/net/bonding/bond0
Ethernet Channel Bonding Driver: v3.2.4 (January 28, 2008)

Bonding Mode: fault-tolerance (active-backup)
Primary Slave: eth0
Currently Active Slave: eth0
MII Status: up
MII Polling Interval (ms): 0
Up Delay (ms): 0
Down Delay (ms): 0
ARP Polling Interval (ms): 3000
ARP IP target/s (n.n.n.n form): 192.168.100.1

Slave Interface: eth0
MII Status: up
Link Failure Count: 1
Permanent HW addr: xx:xx:xx:xx:xx:xx

Slave Interface: eth1
MII Status: up
Link Failure Count: 1
Permanent HW addr: xx:xx:xx:xx:xx:xx

 2,3行目のメッセージは、システム起動時のネットワーク起動段障 で、通信速度? speed)ぜ duplex通信方? (duplex)の値を圏 得できないため、通信速度を100Mbps、通信方? をFullに「仮? 」したというメッセージであり、実際に「変更」した゜ けではないようです。まず、Bondingドライバのモードが「1:active-backup」であれば問題はなさそうです。

# ethtool eth0 | egrep 'Speed|Duplex'
        Speed: 1000Mb/s
        Duplex: Full

# ethtool eth1 | egrep 'Speed|Duplex'
Settings for eth1:
        Speed: 1000Mb/s
        Duplex: Full
6月 30th, 2010

バイトオーダー? 朏 64bit移? メボ

Posted in Linux by admin

圏 考:Linuxアプリケーションぜ 64ビット・システムへの移植
http://www.ibm.com/developerworks/jp/linux/library/l-port64/

 上記URLにも掲載されていますが、アプリケーションを64bit移? する際の注? 点がいぜ つかあります。このうち、ネットワークプログラミングに頻出するバイトオーダーの? 朏 に関してメモを残します。簡単に? うと、ビッグエンディアン方? のネットワークバイトオーダーをLinuxのリトルエンディアン方? のバイトオーダーに? 朏 する際に使用する関? “ntohl”, “htonl”は、64bit Linux環? では正しく変朏 されないという事象の? 書です。以? 、サンプルプログラムと? 行結果を残します。

§ x86 64bit

# uname -m
x86_64
# cat test.c
#include <stdio .h>
#include <byteswap .h>

int main(){

	printf("int: %d\n", sizeof(int));
	printf("long: %d\n", sizeof(long));
	printf("int*: %d\n\n", sizeof(int*));

	int i = 0x12345678;
	long l = 0x0123456789abcdef;
	long m = 0x0123456789abcdef;
	char* c = (char *)&i;
	char* d = (char *)&l;
	char* e = (char *)&m;

	if (*(char *)&i == 0x12){
		printf ("Big endian\n\n");
	} else if(*(char *)&i == 0x78){
		printf ("Little endian\n\n");
	}

	printf("[1]int org:\t%X : %X : %X : %X\n" , c[0] , c[1] , c[2] , c[3]);
	i = htonl( i );
	printf("[2]int htonl:\t%X : %X : %X : %X\n\n" , c[0] , c[1] , c[2] , c[3]);

	printf("[3]long org:\t%X : %X : %X : %X : %X : %X : %X : %X\n" , \
		d[0] , d[1] , d[2] , d[3], d[4], d[5], d[6], d[7]);
	l = bswap_64( l );
	printf("[4]long bswap_64:\t%X : %X : %X : %X : %X : %X : %X : %X\n\n" , \
		d[0] , d[1] , d[2] , d[3], d[4], d[5], d[6], d[7]);

	printf("[5]long org:\t%X : %X : %X : %X : %X : %X : %X : %X\n" , \
		e[0] , e[1] , e[2] , e[3], e[4], e[5], e[6], e[7]);
	m = htonl( m );
	printf("[6]long htonl:\t%X : %X : %X : %X : %X : %X : %X : %lX\n" , \
		e[0] , e[1] , e[2] , e[3], e[4], e[5], e[6], e[7]);

	return 0;
}
# gcc test.c && ./a.out
int: 4
long: 8
int*: 8

Little endian

[1]int org:	78 : 56 : 34 : 12
[2]int htonl:	12 : 34 : 56 : 78

[3]long org:		FFFFFFEF : FFFFFFCD : FFFFFFAB : FFFFFF89 : 67 : 45 : 23 : 1
[4]long bswap_64:	1 : 23 : 45 : 67 : FFFFFF89 : FFFFFFAB : FFFFFFCD : FFFFFFEF

[5]long org:	FFFFFFEF : FFFFFFCD : FFFFFFAB : FFFFFF89 : 67 : 45 : 23 : 1
[6]long htonl:	FFFFFF89 : FFFFFFAB : FFFFFFCD : FFFFFFEF : FFFFFFFF : FFFFFFFF : FFFFFFFF : FFFFFFFF

 [5][6]で示した結果のように、64bit環? においぜ “htonl”関数では正しぜ バイトオーダーの? 朏 がされていないのが゜ かります。”htonl”、”ntohl”は、4バイト整数の? 朏 に使用され、同様に、”htons”、”ntohs”は、2バイト整数に使用されますが、64bit環? ぜ 8バイトデータサイズとなるlong型やポインターには使用出来ないからです。[3][4]のように正しく変朏 する為には、Linux上でぜ “bswap_64″マクボ (/usr/include/bits/byteswap.h)を使用します。以? のように、データサイズが4バイトを超えない32bit環? では問題なぜ 動作します。

§ i686 32bit

# uname -m
i686
# cat test.c
#include <stdio .h>
#include <byteswap .h>

int main(){

	printf("int: %d\n", sizeof(int));
	printf("long: %d\n", sizeof(long));
	printf("int*: %d\n\n", sizeof(int*));

	int i = 0x12345678;
	long l = 0x12345678;
	long m = 0x12345678;
	char* c = (char *)&i;
	char* d = (char *)&l;
	char* e = (char *)&m;

	if (*(char *)&i == 0x12){
		printf ("Big endian\n\n");
	} else if(*(char *)&i == 0x78){
		printf ("Little endian\n\n");
	}

	printf("[1]int org:\t%X : %X : %X : %X\n" , c[0] , c[1] , c[2] , c[3]);
	i = htonl( i );
	printf("[2]int htonl:\t%X : %X : %X : %X\n\n" , c[0] , c[1] , c[2] , c[3]);

	printf("[3]long org:\t%X : %X : %X : %X\n" , d[0] , d[1] , d[2] , d[3]);
	l = bswap_32( l );
	printf("[4]long bswap_32:\t%X : %X : %X : %X\n\n" , d[0] , d[1] , d[2] , d[3]);

	printf("[5]long org:\t%X : %X : %X : %X\n" , e[0] , e[1] , e[2] , e[3]);
	m = htonl( m );
	printf("[6]long htonl:\t%X : %X : %X : %X\n" , e[0] , e[1] , e[2] , e[3]);

	return 0;
}
# gcc test.c && ./a.out
int: 4
long: 4
int*: 4

Little endian

[1]int org:	78 : 56 : 34 : 12
[2]int htonl:	12 : 34 : 56 : 78

[3]long org:		78 : 56 : 34 : 12
[4]long bswap_32:	12 : 34 : 56 : 78

[5]long org:	78 : 56 : 34 : 12
[6]long htonl:	12 : 34 : 56 : 78
4月 5th, 2010

Sendfileのパフォーマン゜

Posted in Apache, Linux by admin

 Apacheのディレクティブぜ EnableSendfileというものがある。これはファイル・ディスクリプタ間のデータコピーシステムコールであるsendfileを、httpdが使用するかどうかを制御するものです。パフォーマンス? の利点について、Apacheドキュメントぜ Linux manページを抜粋しました。

Apache2.2のドキュメントより

例えば静的なファイルの配送のように、リクエストの処理にファイルの途中ぜ
データのアクセスを必要としないときには、Apache ぜ  OS が サポートしていれぜ
ファイルを読み込むことなぜ  sendfile を使ってファイルの内容を送ります。

Linux manページより

このコピーはカーネル内で? ゜ れるので、 sendfile() は、 read(2) ぜ  write(2)
を組み合゜ せるよりも効? がよい。 read(2) や write(2) ではユーザ空間との間ぜ
データの転送が必要となるからである。

 まずぜ Apacheを除? し、システムコールのレベルぜ read/writeぜ sendfileの性能差を比較してみました。比較方? は、ソケット経由で? 定サイズの画? ファイルをクライアント側に配送するという単純なサーバプログラムを組んで? 較しています。プログラムの? 更点は以下の部分になります。Linuxカーネルは「2.6.18-53.el5 x86_64」、計測ツールは「valgrind-3.2.1/callgrind_annotate-3.2.1」です。

read/write

while( 1 )
{
	in_read_size = read( in_fd, buf, sizeof(buf) );
	if( read_size > 0 ){
		write( socket, buf, in_read_size);
	} else {
		break;
	}
}

sendfile

in_size = sendfile( socket, in_fd, &offset, stat_buf.st_size);
if( in_size == -1 ){
	fprintf( stderr, "sendfile error: %s\n", strerror(errno) );
	exit(1);
}

 結果は? の表にようになりました。read/writeの? 行時間合計値ぜ sendfileの? 行時間とほぼ大差ありません。手元の環? ではシステムコールレベルぜ sendfileの効果は確認できなかったということになります。

sendfile_callgrind_systime

—————————————————————————————————————–

 Apacheぜ EnableSendfileではパフォーマンス? のメリットが生まれるのでしょうか?こちらの? 証も同様に? 定サイズの画? ファイルを使用し、別ホストからApacheBenchでリクエストを発? するという手段をとっています。以? の表がその平均値を算出したものです。下表を見ただけでは、EnableSendfileを有効にした場合の効果はあまり感じられないような? がします。同試? の? 果をレスポンス? にプロットしたグラフを圏 照するぜ NFS上ファイルアクセス時の? 安定性なども発? できます。しかし、システムコールの調査と同様、総評して手元の環? でぜ Apacheぜ EnableSendfileの効果は確認することは出来ませんでした。(試? の順番が逆の方が読んでいて面白かっただろうか・・?

sendfile_ab

sendfile_resp

 Apacheのドキュメントにぜ EnableSendfile使用時の注? 点がいぜ つかあります(下記抜粋圏 照? 。上記の? 証では、abを使用している為に圏 得したデータが実際にブラウザで表示できるものだったのか?という確? はとれていないのが実情です。abクライアント側にぜ HTTP200ステータスを返してはいるがブラウザでは表示できない、というのが抜粋3点目の? 具合だと思゜ れます。この? 証ポイントは特に環? にも非常に左右されやすいので、手元の環? で確認し、パフォーマンス? の効果が確? できなけれぜ EnableSendfileを無効にしておいた方が安全なのではないでしょうか。今回の? 証は、ある環? の? 例として圏 け圏 って頂ければと思います。

ボ Linux では、sendfile を用いると、 IPv6 使用時に圭 在する特? ネットワークカードぜ
  TCP-checksum オフロードのバグを? んでしまいます。
ボ Itanium で動いている Linux で、sendfile ぜ  2GB 以? ぜ  ファイルを扱うことができないでしょう。
・ネットワークマウントされた DocumentRoot (例えぜ  NFS や SMB) では、カーネルは自身ぜ
 キャッシュを使ってネットワークからのファイルを 送ることができないことがあります。