[Senna-dev 1028] Re: sen_table_factory

Back to archive index

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
> 




Senna-dev メーリングリストの案内
Back to archive index