morita
morit****@razil*****
2008年 9月 14日 (日) 12:16:54 JST
森です。 はい! test/benchmark/以下あたりが良いと思います。 Kouhei Sutou さんは書きました: > 須藤です。 > > 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 > > _______________________________________________ > Senna-dev mailing list > Senna****@lists***** > http://lists.sourceforge.jp/mailman/listinfo/senna-dev > バグ報告方法:http://qwik.jp/senna/bug_report.html >