メモ代わり。てきとーに。 いや、ですからてきとーですって。 2年前ぐらいにPythonあたりでメールくれた方、ごめんなさい。メール紛失してしまい無視した形になってしまいました。。。

2008年5月9日金曜日

[libmemcahced][mod_chxj] apr_memcacheを廃止

0.12.0(svn)でlibmemcachedを使って早速apr_memcacheを廃止してみた。

10000、20000リクエスト投げてみたところ取りこぼしなし。
速度もapr_memcacheと変わらない。

うーむ。
とってもいい感じ。

ということで、configureのオプションを変えました。
revokeしたオプションは、

  • --with-apr-memcache-header
  • --with-apr_memcahce-lib-dir
で、追加したオプションは、
  • --with-memcached-header
  • --with-memcached-lib-dir
の2つ。
configureに探させようかと思ったが、それはまた今度。

で、実際に使う手順は以下のとおり。
http://tangent.org/552/libmemcached.htmlから、libmemcachedを取得する。

$ wget http://download.tangent.org/libmemcached-0.20.tar.gz
 

libmemcachedをコンパイル&インストール

$ tar xvzf libmemcached-0.20.tar.gz
$ cd libmemcached-0.20
$ ./configure
$ make
$ sudo make install
 


mod_chxjのコンパイル&インストール

$ ./configure --enable-memcache-cookie \
--with-memcached-header=/usr/local/include/libmemcached \
--with-memcached-lib-dir=/usr/local/lib
$ make
$ sudo make install
 


で完了。


.

[libmemcached] libmemcachedを使ってみる

libmemcacheは開発終了とのことで、libmemcachedを使ってみることに。

教えてもらった
http://alpha.mixi.co.jp/blog/?p=119
を読破。

まず、http://tangent.org/552/libmemcached.html
からlibmemcachedをダウンロードっす。
現行0.20が最新かもしれません。

そしたら、展開。


$ tar xvzf libmemcached-0.20.tar.gz
 

で、configure。

$ cd libmemcached-0.20
$ ./configure
 

で、make。

$ make
 


へー。
libmemcachedではマニュアルをpodで書いてるんだー。
libmemcacheよりもドキュメントがそろってそうな。
というのは置いといて、

インストール。

$ sudo make install
 

インストール完了。
念のため、

# ldconfig
 

も。


早速へぼいプログラムを作ってみる。
やりたいことは、
  • set
  • get
  • delete
  • add
の4点。
libmemcachedではマスターキーという概念があるようだが、とりあえずはほっておく。
で、1つづつやってみる。
と、その前に、

$ man 3 libmemcached_examples
 

を見る。

memcachedと通信するためには、まずmemcached_stなる構造体を
用意しなくちゃならない。この構造体は使った後には解放する。
なので、大きな流れとしては以下な感じ。

memcached_st *memc;
memcached_return rc;

memc = memcached_create(NULL);

/* ここら辺でなんかする */

memcached_free(memc);
 


サーバへのつなぎ方は以下な感じ。
まず、memcached_server_st構造体にmemcached_server_list_append関数を使って
接続するサーバを追加する。
追加し終わったら、そのmemcached_server_st構造体をmemcached_stへmemcached_server_push関数を使ってpush。
使い終わったら、memcached_server_stは解放する。

memcached_server_st *servers;
memcached_st *memc;
memcached_return rc;

/* memcached_st生成 */
memc = memcached_create(NULL);

/* サーバリスト生成
* server名=192.168.1.250
* ポート番号=11211
*/
servers = memcached_server_list_append(NULL, "192.168.1.250", 11211, &rc);
/* サーバリスト生成
* server名=192.168.1.250
* ポート番号=11212
*/
servers = memcached_server_list_append(servers, "192.168.1.250", 11212, &rc);

/* memcへpush */
rc = memcached_server_push(memc, servers);

/* memcached_server_st解放 */
/* man 3 libmemcached_examplesだとmemcahced_server_free()と書いてある */
memcached_server_list_free(servers);

 



ということでプログラムを早速作ってみる。
値をセットするだけのへぼいプログラム

/*
* gcc -o mset mset.c -I/usr/local/include -lmemcached
*/
#include <libmemcached/memcached.h>
#include <string.h>
#include <stdio.h>


static void usage(char *argv[]);

int
main(int argc, char *argv[])
{
memcached_st *memc;
memcached_server_st *servers;
memcached_return rc;

if (argc != 3) {
usage(argv);
return -1;
}

/* 初期化 */
memc = memcached_create(NULL);
servers = memcached_server_list_append(NULL, "192.168.1.250", 11211, &rc);
if (rc != MEMCACHED_SUCCESS) {
fprintf(stderr, "%s\n", memcached_strerror(memc, rc));
return -2;
}
/* memcへserversをpush */
rc = memcached_server_push(memc, servers);
if (rc != MEMCACHED_SUCCESS) {
fprintf(stderr, "%s\n", memcached_strerror(memc, rc));
return -2;
}
/* serversを解放 */
memcached_server_list_free(servers);

rc= memcached_set(memc, argv[1], strlen(argv[1]),
argv[2], strlen(argv[2]),
(time_t)600, (uint32_t)0);
if (rc != MEMCACHED_SUCCESS && rc != MEMCACHED_BUFFERED) {
fprintf(stderr, "%s\n", memcached_strerror(memc, rc));
memcached_free(memc);
return -2;
}
/* 解放 */
memcached_free(memc);
return 0;
}


static void
usage(char *argv[])
{
fprintf(stderr, "Usage: %s key value\n", argv[0]);
}
 


man 3 libmemcached_examplesを見ると、memcached_server_free()と
書いてあるが、その名前のシンボルはlibmemcachedには無いようだ。
代わりにmemcached_server_list_free()を使用して解放する。

値をgetするだけのへぼいプログラム


/*
* gcc -o mget mget.c -I/usr/local/include -lmemcached
*/
#include <libmemcached/memcached.h>
#include <string.h>
#include <stdio.h>


static void usage(char *argv[]);

int
main(int argc, char *argv[])
{
memcached_st *memc;
memcached_server_st *servers;
memcached_return rc;
char *value;
size_t value_length;
uint32_t flags;

if (argc != 2) {
usage(argv);
return -1;
}

/* 初期化 */
memc = memcached_create(NULL);
servers = memcached_server_list_append(NULL, "192.168.1.250", 11211, &rc);
if (rc != MEMCACHED_SUCCESS) {
fprintf(stderr, "%s\n", memcached_strerror(memc, rc));
return -2;
}
/* memcへserversをpush */
rc = memcached_server_push(memc, servers);
if (rc != MEMCACHED_SUCCESS) {
fprintf(stderr, "%s\n", memcached_strerror(memc, rc));
return -2;
}
/* serversを解放 */
memcached_server_list_free(servers);

value= memcached_get(memc, argv[1], strlen(argv[1]),
&value_length, &flags, &rc);
if (rc != MEMCACHED_SUCCESS) {
fprintf(stderr, "%s\n", memcached_strerror(memc, rc));
memcached_free(memc);
return -2;
}
/* 印字 */
fprintf(stderr, "value:[%s]\n", value);
free(value);
/* 解放 */
memcached_free(memc);
return 0;
}


static void
usage(char *argv[])
{
fprintf(stderr, "Usage: %s key\n", argv[0]);
}
 

気をつけるべきは、memcahced_get()の戻り値を使用した後、free()しなきゃならないことぐらいか。


値をdeleteするだげのしょぼいプログラム

/*
* gcc -o mdelete mdelete.c -I/usr/local/include -lmemcached
*/
#include <libmemcached/memcached.h>
#include <string.h>
#include <stdio.h>


static void usage(char *argv[]);

int
main(int argc, char *argv[])
{
memcached_st *memc;
memcached_server_st *servers;
memcached_return rc;
char *value;
size_t value_length;
uint32_t flags;

if (argc != 2) {
usage(argv);
return -1;
}

/* 初期化 */
memc = memcached_create(NULL);
servers = memcached_server_list_append(NULL, "192.168.1.250", 11211, &rc);
if (rc != MEMCACHED_SUCCESS) {
fprintf(stderr, "%s\n", memcached_strerror(memc, rc));
return -2;
}
/* memcへserversをpush */
rc = memcached_server_push(memc, servers);
if (rc != MEMCACHED_SUCCESS) {
fprintf(stderr, "%s\n", memcached_strerror(memc, rc));
return -2;
}
/* serversを解放 */
memcached_server_list_free(servers);

/* 削除 */
rc= memcached_delete(memc, argv[1], strlen(argv[1]), (time_t)0);
if (rc != MEMCACHED_SUCCESS && rc == MEMCACHED_BUFFERED) {
fprintf(stderr, "%s\n", memcached_strerror(memc, rc));
memcached_free(memc);
return -2;
}

/* 解放 */
memcached_free(memc);
return 0;
}


static void
usage(char *argv[])
{
fprintf(stderr, "Usage: %s key\n", argv[0]);
}
 

特に難しいことは無い。
memcached_deleteを使用するだけ。


値をaddするだけのしょぼいプログラム

/*
* gcc -o madd madd.c -I/usr/local/include -lmemcached
*/
#include <libmemcached/memcached.h>
#include <string.h>
#include <stdio.h>


static void usage(char *argv[]);

int
main(int argc, char *argv[])
{
memcached_st *memc;
memcached_server_st *servers;
memcached_return rc;

if (argc != 3) {
usage(argv);
return -1;
}

/* 初期化 */
memc = memcached_create(NULL);
servers = memcached_server_list_append(NULL, "192.168.1.250", 11211, &rc);
if (rc != MEMCACHED_SUCCESS) {
fprintf(stderr, "%s\n", memcached_strerror(memc, rc));
return -2;
}
/* memcへserversをpush */
rc = memcached_server_push(memc, servers);
if (rc != MEMCACHED_SUCCESS) {
fprintf(stderr, "%s\n", memcached_strerror(memc, rc));
return -2;
}
/* serversを解放 */
memcached_server_list_free(servers);

/* あっど */
rc = memcached_add(memc, argv[1], strlen(argv[1]),
argv[2], strlen(argv[2]),
(time_t)600, (uint32_t)0);

if (rc != MEMCACHED_SUCCESS && rc != MEMCACHED_STORED && rc != MEMCACHED_NOTSTORED) {
/* 値がセットされていない状態でaddするとMEMCACHED_SUCCESSが返ってくる。 */
fprintf(stderr, "%s\n", memcached_strerror(memc, rc));
memcached_free(memc);
return -2;
}
fprintf(stderr, "%s\n", memcached_strerror(memc, rc));

/* 解放 */
memcached_free(memc);
return 0;
}


static void
usage(char *argv[])
{
fprintf(stderr, "Usage: %s key value\n", argv[0]);
}
 

値がセットされていない状態でaddするとMEMCACHE_SUCCESSがrcに設定される。
値がセットされている上体でaddするとMEMCACHE_NOTSTOREDがrcに設定される。


とりあえず、必要そうな部分の簡単なプログラムを作ってみた。

おしまい。
.

2008年5月8日木曜日

[libmemcache] libmemcacheを使ってクライアントを作ってみる

apr_memcacheの代わりにlibmemcacheを使えないか、と思いmemcacheクライアントを作ってみる。

必要なパッケージ(Debian-Etchの場合)は以下のとおり。

  • libmemcache0
  • libmemcache-dev
apt-getでインストールする。

で、早速プログラミング。

値を設定する場合の全体の流れは多分以下のとおり。
  1. struct memcacheの領域を確保。
  2. struct memcache構造体にサーバを追加。
  3. タイムアウト等の諸設定
  4. mc_setをコール
  5. struct memcache構造体領域の解放

値を取得する場合の全体の流れは多分以下のとおり。
  1. struct memcache構造体領域を確保
  2. struct memcache構造体にサーバを追加
  3. タイムアウト等の諸設定
  4. struct memcache_req構造体の領域を確保
  5. struct memcache_req構造体に対してキーを追加し、レスポンス領域(struct memcache_res)へのポインタを取得
  6. mc_get等の関数をコール
  7. struct memcache_res構造体からレスポンスデータを取得
  8. struct memcache_res構造体領域を開放
  9. struct memcache構造体領域を開放
な感じで、”多分”良さそう。

サーバに値をセットするプログラム

#include <memcache.h>
#include <stdio.h>

int
main()
{
struct memcache *mc ;
int ret;

/* struct memcache構造体領域を確保 */
mc = mc_new();

/* サーバの追加 */
ret = mc_server_add4(mc, "192.168.1.250:11211");
if (ret != MCM_ERR_NONE) {
fprintf(stderr, "failed: mc_server_add4():[%d]\n", ret);
mc_free(mc);
return -1;
}

/* タイムアウトの設定(60秒でタイムアウト) */
/*
* sec = 60秒
* usec = 0
*/
mc_timeout(mc, 60, 0);

/* 値の設定 */
/* key="test-key" */
/* val="test-data" */
/* expire= 600秒 */
/* flags=0 */
ret = mc_set(mc, "test-key", sizeof("test-key")-1, "test-data", sizeof("test-data")-1, 600, 0);
if (ret != MCM_ERR_NONE) {
fprintf(stderr, "failed: mc_set():[%d]\n", ret);
mc_free(mc);
return -2;
}
mc_free(mc);
return 0;
}
 

な感じ。

実行してみる。

$ gcc -o b b.c -lmemcache
$ ./b



書かれたかどうかをチェック。

$ telnet 192.168.1.250 11211
Trying 192.168.1.250...
Connected to 192.168.1.250.
Escape character is '^]'.
get test-key 0 0 0
VALUE test-key 0 9
test-data
END
 

書かれているっぽい。



サーバから値を取得してみるプログラム

#include <memcache.h>
#include <stdio.h>

int
main()
{
struct memcache *mc ;
struct memcache_req *mcr;
struct memcache_res *res;
int ret;

/* struct memcache構造体領域を確保 */
mc = mc_new();

/* サーバの追加 */
ret = mc_server_add4(mc, "192.168.1.250:11211");
if (ret != MCM_ERR_NONE) {
fprintf(stderr, "failed: mc_server_add4():[%d]\n", ret);
mc_free(mc);
return -1;
}

/* タイムアウトの設定(60秒でタイムアウト) */
/*
* sec = 60秒
* usec = 0
*/
mc_timeout(mc, 60, 0);

/* 値の取得
*/
mcr = mc_req_new();
res = mc_req_add(mcr, "test-key", sizeof("test-key")-1);
mc_get(mc, mcr);


/* 取得した値を出力 */
fprintf(stderr, "res->key:[%s] res->val:[%s]\n", res->key, res->val);

mc_req_free(mcr);
mc_free(mc);

return 0;
}
 


早速、実行。

$ gcc -o c c.c -lmemcache
$ ./c
res->key:[test-key] res->val:[test-data]
 

取得できた。

.

[apr_memcache] とりあえずScatterGatherI/Oやめてみた

あまりに遅いんで、vectorを文字列に展開しちゃってから
送信するようにしたパッチを、バグ対応パッチを参考につくってみた。


http://docs.google.com/Doc?id=dcxd2jkv_0gsmc3hdz

って誰もいらないかな??

一応、これでMySQLよりは断然はやいし、
変なエラーもなさげ。

.

[apr_memcache][mod_chxj] おかしいなー

apr_memcacheにパッチを当てると、MySQLの場合の数倍遅い。
まぁ、パッチを見ると、ちゃんと送ろうとしているのは分かるんだけど。。

うーむ。

ちなみにapr_memcacheにパッチを当てない場合だと
10000リクエスト100スレッドで大体140秒ぐらいで終る。
で、apr_memcacheのバグが原因であると思われる取りこぼしやエラーは
10000リクエスト中3件。

パッチを当てた場合は
10000リクエスト100スレッドで大体5700秒。
取りこぼしやエラーは0件。

ということで、結果から見ると
取りこぼしやエラーが許容範囲であるならば、
できればパッチを当てたくない感じ。
だって、やたらと遅いもんね。

つーか、apr_memcacheやめてlibmemcacheを使ったらどうなんだろう。
ということでやってみようっと。

.

[その他] MyPCが壊れた

オンボードのビデオ、オーディオ、ネットワークアダプタが軒並壊れたー。

.

2008年5月7日水曜日

[memcache] 容量とかの情報を取得する

ググってたら見つけたんで、メモ。


$ telnet 192.168.1.250 11211
Trying 192.168.1.250...
Connected to 192.168.1.250.
Escape character is '^]'.
stats
STAT pid 2284
STAT uptime 262
STAT time 1210089897
STAT version 1.1.12
STAT rusage_user 0.000000
STAT rusage_system 0.010000
STAT curr_items 0
STAT total_items 0
STAT bytes 0
STAT curr_connections 2
STAT total_connections 3
STAT connection_structures 3
STAT cmd_get 0
STAT cmd_set 0
STAT get_hits 0
STAT get_misses 0
STAT bytes_read 31
STAT bytes_written 425
STAT limit_maxbytes 67108864
END
 


・・・あら、素敵。

.

2008年5月6日火曜日

[mod_chxj] MySQLクッキー機能がなんか変

MySQLクッキー機能がなんか変・・・。

ちなみに元ネタはmod_auth_mysql3.0.0。

--
コネクションを張ったあと、SELECT文を投げるのだが、
ここで万が一失敗した場合、もう一度コネクションを張りにいくようにしていた。
ここで、既に張ってあったコネクションをそのままにコネクションを張ったもんだから
切断していないコネクションが・・・。

ということで、0.12.0で対応完了。
.

[Python][お勉強] みんなのPythonまた読破

みんなのPython Webアプリ編」読破。

さらっと読める本。ま、面白かったかな・・?

さて、次は先生いわく「読んどけ」らしい
ちょっと古い「Pythonクイックリファレンス」。

.

[OS]ひさびさに遊んだ

ひさびさにOS周りでお遊び。

ELFのスタティックリンクしたものであればロード&実行できるんだけど、
ELFのダイナミックリンクしたものをロードしようとするとglibcのどこかで
わけのわからんところにJumpしちゃう。

うーむ。Linuxのelfローダと同じことしたつもりなんだけど、
やっぱりglibcをちゃんと読まないと駄目ってことかいな。

.