Kouhei Sutou
kou****@cozmi*****
2008年 9月 13日 (土) 10:58:56 JST
須藤です。 In <48CAF****@razil*****> "[Senna-dev 1025] Re: sen_table_factory" on Sat, 13 Sep 2008 07:55:17 +0900, morita <morit****@razil*****> wrote: > ご提案ありがとうございます。どんな使い勝手が求められているのか > よく伝わりました! > > えーと、、今の段階ではflagの値や約束事もまだ固まり切れていないので、 > まずはそこをきっちりと作り込みたいと思っています。 > > その上でsen_table_create()等を今より扱いやすいシグネチャに改良することを > 検討したいと思います。 よろしくお願いします。 ところで、サンプルプログラムの中からベンチマーク関連の部分を 抜き出して、benchmark/以下にでも入れてしまってよいですか? 他のベンチマークも簡単に作れるようにすると、これから嬉しいこ ともあるかと思います。 なにかを提案する時に、今回のようにベンチマークもつけて、そん なに遅くないよ、とか言えるのにも使えると思います。 > Kouhei Sutou さんは書きました: > > 須藤です。 > > > > sen_table_create()の中にはencodingなどいくつかデフォルト値があるものがあります。 > > また、pathを指定しているときはsen_obj_flagsにSEN_OBJ_PERSISTENTフラグを立て > > ないとダメ、みたいなちょっとした約束事もあります。 > > > > デフォルト値は指定しなくても使える、ちょっとした約束はうまいことやってくれる、 > > などをやってsen_table_create()を便利に使えるようにするsen_table_factoryオブジェクト > > を作るのはどうでしょうか? > > > > で、気になるのは遅くなるんじゃないかということだと思いますが、大したことはない > > ようです。最後にベンチマークを含むサンプル実装をつけてあります。ベンチマークでは > > 100回sen_table_create()をしています。ということで、sen_table_factoryオブジェクトを > > 導入しませんか?(プログラムはGLibを使っているので`pkg-config --cflags --libs glib-2.0` > > 付きでビルドしてください。) > > > > 結果: > > -- > > normal (persistent): (1.07456) > > factory (persistent): (1.05743) > > normal (temporary) : (0.640719) > > factory (temporary) : (0.684413) > > -- > > > > /* -*- c-basic-offset: 2 -*- */ > > > > #include <errno.h> > > #include <stdlib.h> > > #include <string.h> > > > > #include <glib.h> > > #include <glib/gstdio.h> > > > > #include <senna.h> > > extern sen_ctx sen_gctx; > > > > #define DEFAULT_FLAGS (SEN_OBJ_PERSISTENT | SEN_OBJ_TABLE_PAT_KEY) > > #define DEFAULT_VALUE_SIZE (1024) > > > > gboolean > > bench_utils_remove_path (const char *path, GError **error) > > { > > if (!g_file_test(path, G_FILE_TEST_EXISTS)) { > > g_set_error(error, G_FILE_ERROR, G_FILE_ERROR_NOENT, > > "path doesn't exist: %s", path); > > return FALSE; > > } > > > > if (g_file_test(path, G_FILE_TEST_IS_DIR)) { > > if (g_rmdir(path) == -1) { > > g_set_error(error, G_FILE_ERROR, g_file_error_from_errno(errno), > > "can't remove directory: %s", path); > > return FALSE; > > } > > } else { > > if (g_unlink(path) == -1) { > > g_set_error(error, G_FILE_ERROR, g_file_error_from_errno(errno), > > "can't remove path: %s", path); > > return FALSE; > > } > > } > > > > return TRUE; > > } > > > > gboolean > > bench_utils_remove_path_recursive (const char *path, GError **error) > > { > > if (g_file_test(path, G_FILE_TEST_IS_DIR)) { > > GDir *dir; > > const gchar *name; > > > > dir = g_dir_open(path, 0, error); > > if (!dir) > > return FALSE; > > > > while ((name = g_dir_read_name(dir))) { > > const gchar *full_path; > > > > full_path = g_build_filename(path, name, NULL); > > if (!bench_utils_remove_path_recursive(full_path, error)) > > return FALSE; > > } > > > > g_dir_close(dir); > > > > return bench_utils_remove_path(path, error); > > } else { > > return bench_utils_remove_path(path, error); > > } > > > > return TRUE; > > } > > > > void > > bench_utils_remove_path_recursive_force (const gchar *path) > > { > > bench_utils_remove_path_recursive(path, NULL); > > } > > > > typedef struct _BenchmarkData > > { > > gchar *base_dir; > > gchar *space_path; > > > > sen_ctx *context; > > sen_obj *space; > > const char *name; > > unsigned name_size; > > char *path; > > sen_obj_flags flags; > > sen_obj *key_type; > > unsigned value_size; > > sen_encoding encoding; > > } BenchmarkData; > > > > typedef void (*BenchmarkSetupFunc) (gpointer user_data); > > typedef void (*BenchmarkFunc) (gpointer user_data); > > typedef void (*BenchmarkTeardownFunc) (gpointer user_data); > > > > static void > > bench_report(const gchar *label, gint n, > > BenchmarkSetupFunc benchmark_setup, > > BenchmarkFunc benchmark, > > BenchmarkTeardownFunc benchmark_teardown, > > gpointer data) > > { > > GTimer *timer; > > gint i; > > > > g_print("%s: ", label); > > timer = g_timer_new(); > > g_timer_stop(timer); > > g_timer_reset(timer); > > for (i = 0; i < n; i++) { > > benchmark_setup(data); > > g_timer_continue(timer); > > benchmark(data); > > g_timer_stop(timer); > > benchmark_teardown(data); > > } > > g_print("(%g)\n", g_timer_elapsed(timer, NULL)); > > } > > > > static void > > bench_normal(gpointer user_data) > > { > > BenchmarkData *data = user_data; > > sen_obj *table; > > > > table = sen_table_create(data->context, data->space, > > data->name, data->name_size, > > data->path, data->flags, > > data->key_type, data->value_size, > > data->encoding); > > sen_obj_close(data->context, table); > > } > > > > static void > > bench_normal_temporary(gpointer user_data) > > { > > BenchmarkData *data = user_data; > > sen_obj *table; > > > > table = sen_table_create(data->context, data->space, > > data->name, data->name_size, > > NULL, data->flags & ~SEN_OBJ_PERSISTENT, > > data->key_type, data->value_size, > > data->encoding); > > sen_obj_close(data->context, table); > > } > > > > typedef struct _sen_table_factory > > { > > sen_ctx *context; > > sen_obj *space; > > char *name; > > unsigned name_size; > > char *path; > > sen_obj_flags flags; > > sen_obj *key_type; > > unsigned value_size; > > sen_encoding encoding; > > } sen_table_factory; > > > > static sen_table_factory * > > sen_table_factory_create(void) > > { > > sen_table_factory *factory; > > > > factory = g_new0(sen_table_factory, 1); > > > > factory->context = &sen_gctx; > > factory->space = NULL; > > factory->name = NULL; > > factory->name_size = 0; > > factory->path = NULL; > > factory->flags = DEFAULT_FLAGS; > > factory->key_type = NULL; > > factory->value_size = DEFAULT_VALUE_SIZE; > > factory->encoding = sen_enc_default; > > > > return factory; > > } > > > > static void > > sen_table_factory_set_context(sen_table_factory *factory, sen_ctx *context) > > { > > factory->context = context; > > } > > > > static void > > sen_table_factory_set_space(sen_table_factory *factory, sen_obj *space) > > { > > factory->space = space; > > } > > > > static void > > sen_table_factory_set_name(sen_table_factory *factory, const char *name) > > { > > factory->name = g_strdup(name); > > factory->name_size = strlen(name); > > } > > > > static void > > sen_table_factory_set_path(sen_table_factory *factory, const char *path) > > { > > factory->path = g_strdup(path); > > if (path) > > factory->flags |= SEN_OBJ_PERSISTENT; > > else > > factory->flags &= ~SEN_OBJ_PERSISTENT; > > } > > > > static void > > sen_table_factory_set_key_type(sen_table_factory *factory, sen_obj *key_type) > > { > > factory->key_type = key_type; > > } > > > > static sen_obj * > > sen_table_factory_make(sen_table_factory *factory) > > { > > return sen_table_create(factory->context, factory->space, > > factory->name, factory->name_size, > > factory->path, factory->flags, > > factory->key_type, factory->value_size, > > factory->encoding); > > } > > > > static void > > sen_table_factory_close(sen_table_factory *factory) > > { > > g_free(factory->name); > > g_free(factory->path); > > g_free(factory); > > } > > > > static void > > bench_factory(gpointer user_data) > > { > > BenchmarkData *data = user_data; > > sen_table_factory *factory; > > sen_obj *table; > > > > factory = sen_table_factory_create(); > > sen_table_factory_set_context(factory, data->context); > > sen_table_factory_set_space(factory, data->space); > > sen_table_factory_set_name(factory, data->name); > > sen_table_factory_set_path(factory, data->path); > > sen_table_factory_set_key_type(factory, data->key_type); > > > > table = sen_table_factory_make(factory); > > sen_obj_close(data->context, table); > > > > sen_table_factory_close(factory); > > } > > > > static void > > bench_factory_temporary(gpointer user_data) > > { > > BenchmarkData *data = user_data; > > sen_table_factory *factory; > > sen_obj *table; > > > > factory = sen_table_factory_create(); > > sen_table_factory_set_context(factory, data->context); > > sen_table_factory_set_space(factory, data->space); > > sen_table_factory_set_name(factory, data->name); > > sen_table_factory_set_key_type(factory, data->key_type); > > > > table = sen_table_factory_make(factory); > > sen_obj_close(data->context, table); > > > > sen_table_factory_close(factory); > > } > > > > static void > > bench_setup(gpointer user_data) > > { > > BenchmarkData *data = user_data; > > const gchar *type_name; > > > > bench_utils_remove_path_recursive_force(data->base_dir); > > g_mkdir_with_parents(data->base_dir, 0755); > > > > data->context = sen_ctx_open(NULL, SEN_CTX_USEQL); > > data->space = sen_space_create(data->context, NULL, > > data->space_path, sen_enc_default); > > > > type_name = "name"; > > data->key_type = sen_type_create(data->context, data->space, > > type_name, strlen(type_name), > > SEN_OBJ_FIXED_SIZE, sizeof(sen_id)); > > > > } > > > > static void > > bench_teardown(gpointer user_data) > > { > > BenchmarkData *data = user_data; > > > > sen_obj_close(data->context, data->key_type); > > sen_obj_close(data->context, data->space); > > sen_ctx_close(data->context); > > bench_utils_remove_path_recursive_force(data->base_dir); > > } > > > > int > > main(int argc, gchar **argv) > > { > > BenchmarkData data; > > > > sen_init(); > > > > data.base_dir = g_build_filename(g_get_tmp_dir(), "senna-bench", NULL); > > data.space_path = g_build_filename(data.base_dir, "space", NULL); > > data.name = "table"; > > data.name_size = strlen(data.name); > > data.path = g_build_filename(data.base_dir, "table", NULL); > > data.flags = DEFAULT_FLAGS; > > data.key_type = NULL; > > data.value_size = DEFAULT_VALUE_SIZE; > > data.encoding = sen_enc_default; > > > > bench_report(" normal (persistent)", 100, > > bench_setup, bench_normal, bench_teardown, &data); > > bench_report("factory (persistent)", > > 100, bench_setup, bench_factory, bench_teardown, &data); > > bench_report(" normal (temporary) ", 100, > > bench_setup, bench_normal_temporary, bench_teardown, &data); > > bench_report("factory (temporary) ", > > 100, bench_setup, bench_factory_temporary, > > bench_teardown, &data); > > > > bench_utils_remove_path_recursive_force(data.base_dir); > > > > g_free(data.path); > > g_free(data.space_path); > > g_free(data.base_dir); > > > > sen_fin(); > > > > return 0; > > } > > > > _______________________________________________ > > Senna-dev mailing list > > Senna****@lists***** > > http://lists.sourceforge.jp/mailman/listinfo/senna-dev > > バグ報告方法:http://qwik.jp/senna/bug_report.html > > > > _______________________________________________ > Senna-dev mailing list > Senna****@lists***** > http://lists.sourceforge.jp/mailman/listinfo/senna-dev > バグ報告方法:http://qwik.jp/senna/bug_report.html