[Groonga-commit] groonga/groonga [master] add grn_geo_cursor.

Back to archive index

null+****@clear***** null+****@clear*****
2011年 10月 16日 (日) 16:45:39 JST


Kouhei Sutou	2011-10-16 07:45:39 +0000 (Sun, 16 Oct 2011)

  New Revision: 611b673026e7884e3c72c4daaa1f93aec81c185d

  Log:
    add grn_geo_cursor.

  Modified files:
    include/groonga.h
    lib/db.c
    lib/geo.c
    lib/geo.h
    lib/ii.c
    lib/ii.h
    test/benchmark/bench-geo-select.c

  Modified: include/groonga.h (+34 -0)
===================================================================
--- include/groonga.h    2011-10-17 21:50:55 +0000 (1ef25f0)
+++ include/groonga.h    2011-10-16 07:45:39 +0000 (60c0b60)
@@ -419,6 +419,7 @@ typedef unsigned short int grn_obj_flags;
 #define GRN_CURSOR_TABLE_NO_KEY        (0x13)
 #define GRN_CURSOR_TABLE_VIEW          (0x14)
 #define GRN_CURSOR_COLUMN_INDEX        (0x18)
+#define GRN_CURSOR_GEO                 (0x1a)
 #define GRN_TYPE                       (0x20)
 #define GRN_PROC                       (0x21)
 #define GRN_EXPR                       (0x22)
@@ -1793,6 +1794,39 @@ GRN_API int grn_geo_estimate_in_rectangle(grn_ctx *ctx,
                                           grn_obj *top_left_point,
                                           grn_obj *bottom_right_point);
 
+/**
+ * grn_geo_cursor_open_in_rectangle:
+ * @index: the index column for TokyoGeoPoint or WGS84GeoPpoint type.
+ * @top_left_point: the top left point of the target
+ * rectangle. (ShortText, Text, LongText, TokyoGeoPoint or
+ * WGS84GeoPoint)
+ * @bottom_right_point: the bottom right point of the target
+ * rectangle. (ShortText, Text, LongText, TokyoGeoPoint or
+ * WGS84GeoPoint)
+ * @offset: the cursor returns records from @offset
+ * position. @offset is based on 0.
+ * @limit: the cursor returns at most @limit records. -1
+ * means no limit.
+ *
+ * It opens a cursor to get records in the rectangle
+ * specfied by @top_left_point and @bottom_right_point.
+ **/
+GRN_API grn_obj *grn_geo_cursor_open_in_rectangle(grn_ctx *ctx,
+                                                  grn_obj *index,
+                                                  grn_obj *top_left_point,
+                                                  grn_obj *bottom_right_point,
+                                                  int offset,
+                                                  int limit);
+
+/**
+ * grn_geo_cursor_next:
+ * @cursor: the geo cursor.
+ *
+ * It returns the next posting that has record ID. It
+ * returns NULL after all records are returned.
+ **/
+GRN_API grn_posting *grn_geo_cursor_next(grn_ctx *ctx, grn_obj *cursor);
+
 
 /* query & snippet */
 

  Modified: lib/db.c (+3 -0)
===================================================================
--- lib/db.c    2011-10-17 21:50:55 +0000 (23aac34)
+++ lib/db.c    2011-10-16 07:45:39 +0000 (ce93a5b)
@@ -6373,6 +6373,9 @@ grn_obj_close(grn_ctx *ctx, grn_obj *obj)
         GRN_FREE(ic);
       }
       break;
+    case GRN_CURSOR_GEO :
+      grn_geo_cursor_close(ctx, obj);
+      break;
     case GRN_TYPE :
       GRN_FREE(obj);
       rc = GRN_SUCCESS;

  Modified: lib/geo.c (+286 -22)
===================================================================
--- lib/geo.c    2011-10-17 21:50:55 +0000 (6fa284b)
+++ lib/geo.c    2011-10-16 07:45:39 +0000 (9d15352)
@@ -18,16 +18,9 @@
 #include <string.h>
 #include <stdlib.h>
 #include "geo.h"
-#include "ii.h"
-#include "db.h"
 #include "pat.h"
 #include "util.h"
 
-typedef enum {
-  MESH_LATITUDE,
-  MESH_LONGITUDE
-} mesh_direction;
-
 typedef struct {
   grn_id id;
   double d;
@@ -52,7 +45,7 @@ typedef struct {
   int end;
   int distance;
   int diff_bit;
-  mesh_direction direction;
+  grn_geo_mesh_direction direction;
 } in_rectangle_data;
 
 static int
@@ -860,12 +853,12 @@ in_rectangle_data_prepare(grn_ctx *ctx, grn_obj *index,
     latitude_distance = top_left->latitude - bottom_right->latitude;
     longitude_distance = bottom_right->longitude - top_left->longitude;
     if (latitude_distance > longitude_distance) {
-      data->direction = MESH_LATITUDE;
+      data->direction = GRN_GEO_MESH_LATITUDE;
       geo_point_input = bottom_right;
       data->base.latitude = bottom_right->latitude;
       data->base.longitude = bottom_right->longitude - longitude_distance;
     } else {
-      data->direction = MESH_LONGITUDE;
+      data->direction = GRN_GEO_MESH_LONGITUDE;
       geo_point_input = top_left;
       data->base.latitude = top_left->latitude - latitude_distance;
       data->base.longitude = top_left->longitude;
@@ -875,18 +868,21 @@ in_rectangle_data_prepare(grn_ctx *ctx, grn_obj *index,
     data->diff_bit = compute_diff_bit(geo_key_input, geo_key_base);
     compute_min_and_max(&(data->base), data->diff_bit,
                         &(data->min), &(data->max));
-    if (data->direction == MESH_LATITUDE) {
+    switch (data->direction) {
+    case GRN_GEO_MESH_LATITUDE :
       data->distance = data->max.latitude - data->min.latitude + 1;
       data->start = data->min.latitude;
       data->end = top_left->latitude;
-    } else {
+      break;
+    case GRN_GEO_MESH_LONGITUDE :
       data->distance = data->max.longitude - data->min.longitude + 1;
       data->start = data->min.longitude;
       data->end = bottom_right->longitude;
+      break;
     }
 #ifdef GEO_DEBUG
     printf("direction: %s\n",
-           data->direction == MESH_LATITUDE ? "latitude" : "longitude");
+           data->direction == GRN_GEO_MESH_LATITUDE ? "latitude" : "longitude");
     printf("base:         ");
     grn_p_geo_point(ctx, &(data->base));
     printf("input:        ");
@@ -913,10 +909,218 @@ exit :
   return ctx->rc;
 }
 
+grn_obj *
+grn_geo_cursor_open_in_rectangle(grn_ctx *ctx,
+                                 grn_obj *index,
+                                 grn_obj *top_left_point,
+                                 grn_obj *bottom_right_point,
+                                 int offset,
+                                 int limit)
+{
+  grn_geo_cursor_in_rectangle *cursor = NULL;
+  in_rectangle_data data;
+
+  GRN_VOID_INIT(&(data.top_left_point_buffer));
+  GRN_VOID_INIT(&(data.bottom_right_point_buffer));
+  if (in_rectangle_data_prepare(ctx, index, top_left_point, bottom_right_point,
+                                "geo_in_rectangle()", &data)) {
+    goto exit;
+  }
+
+  cursor = GRN_MALLOCN(grn_geo_cursor_in_rectangle, 1);
+  if (!cursor) {
+    ERR(GRN_NO_MEMORY_AVAILABLE,
+        "[geo][cursor][in-rectangle] failed to allocate memory for geo cursor");
+    goto exit;
+  }
+
+  cursor->obj.header.type = GRN_CURSOR_GEO;
+  cursor->obj.header.impl_flags = GRN_OBJ_ALLOCATED;
+  cursor->obj.header.flags = 0;
+  cursor->obj.header.domain = GRN_ID_NIL;
+
+  cursor->pat = data.pat;
+  cursor->index = index;
+  cursor->diff_bit = data.diff_bit;
+  cursor->start_mesh_point = data.start;
+  cursor->end_mesh_point = data.end;
+  cursor->distance = data.distance;
+  cursor->direction = data.direction;
+  memcpy(&(cursor->top_left), data.top_left, sizeof(grn_geo_point));
+  memcpy(&(cursor->bottom_right), data.bottom_right, sizeof(grn_geo_point));
+  memcpy(&(cursor->base), &(data.base), sizeof(grn_geo_point));
+  cursor->pat_cursor = NULL;
+  cursor->ii_cursor = NULL;
+  cursor->offset = offset;
+  cursor->rest = limit;
+
+exit :
+  grn_obj_unlink(ctx, &(data.top_left_point_buffer));
+  grn_obj_unlink(ctx, &(data.bottom_right_point_buffer));
+  return (grn_obj *)cursor;
+}
+
+typedef grn_bool (*grn_geo_cursor_callback)(grn_ctx *ctx, grn_ii_posting *posting, void *user_data);
+
+static void
+grn_geo_cursor_each(grn_ctx *ctx, grn_obj *geo_cursor,
+                    grn_geo_cursor_callback callback, void *user_data)
+{
+  grn_geo_cursor_in_rectangle *cursor;
+  grn_obj *pat;
+  grn_table_cursor *pat_cursor;
+  grn_ii *ii;
+  grn_ii_cursor *ii_cursor;
+  grn_ii_posting *posting = NULL;
+  grn_geo_point *current, *base, *top_left, *bottom_right;
+  int diff_bit, distance, end_mesh_point;
+  grn_geo_mesh_direction direction;
+  int i = 0;
+  int mesh_point;
+  grn_id index_id;
+
+  cursor = (grn_geo_cursor_in_rectangle *)geo_cursor;
+  if (cursor->rest == 0) {
+    return;
+  }
+
+  pat = cursor->pat;
+  pat_cursor = cursor->pat_cursor;
+  ii = (grn_ii *)(cursor->index);
+  ii_cursor = cursor->ii_cursor;
+  current = &(cursor->current);
+  base = &(cursor->base);
+  top_left = &(cursor->top_left);
+  bottom_right = &(cursor->bottom_right);
+  diff_bit = cursor->diff_bit;
+  distance = cursor->distance;
+  end_mesh_point = cursor->end_mesh_point;
+  direction = cursor->direction;
+
+  while (GRN_TRUE) {
+    if (!pat_cursor) {
+      if (!(cursor->pat_cursor = pat_cursor =
+            grn_table_cursor_open(ctx,
+                                  pat,
+                                  base,
+                                  diff_bit,
+                                  NULL, 0,
+                                  0, -1,
+                                  GRN_CURSOR_PREFIX|GRN_CURSOR_SIZE_BY_BIT))) {
+        cursor->rest = 0;
+        return;
+      }
+#ifdef GEO_DEBUG
+      {
+        switch (direction) {
+        case GRN_GEO_MESH_LATITUDE :
+          mesh_point = base->latitude;
+          break;
+        case GRN_GEO_MESH_LONGITUDE :
+          mesh_point = base->longitude;
+          break;
+        }
+        printf("mesh-point:          %10d\n", mesh_point);
+        inspect_mesh(ctx, base, diff_bit,
+                     (mesh_point - cursor->start_mesh_point) /
+                     distance);
+      }
+#endif
+    }
+
+    while (ii_cursor || (index_id = grn_table_cursor_next(ctx, pat_cursor))) {
+      if (!ii_cursor) {
+        grn_table_get_key(ctx, pat, index_id, current, sizeof(grn_geo_point));
+        if (grn_geo_in_rectangle_raw(ctx, current, top_left, bottom_right)) {
+          inspect_tid(ctx, index_id, current, 0);
+          if (!(cursor->ii_cursor = ii_cursor =
+                grn_ii_cursor_open(ctx,
+                                   ii,
+                                   index_id,
+                                   GRN_ID_NIL,
+                                   GRN_ID_MAX,
+                                   ii->n_elements,
+                                   0))) {
+            continue;
+          }
+        } else {
+          continue;
+        }
+      }
+
+      while ((posting = grn_ii_cursor_next(ctx, ii_cursor))) {
+        if (cursor->offset == 0) {
+          if (!callback(ctx, posting, user_data)) {
+            return;
+          }
+          if (cursor->rest > 0) {
+            if (--(cursor->rest) == 0) {
+              return;
+            }
+          }
+        } else {
+          cursor->offset--;
+        }
+      }
+      grn_ii_cursor_close(ctx, ii_cursor);
+      cursor->ii_cursor = ii_cursor = NULL;
+    }
+    grn_table_cursor_close(ctx, pat_cursor);
+    cursor->pat_cursor = pat_cursor = NULL;
+
+    switch (direction) {
+    case GRN_GEO_MESH_LATITUDE :
+      mesh_point = (base->latitude += distance);
+      break;
+    case GRN_GEO_MESH_LONGITUDE :
+      mesh_point = (base->longitude += distance);
+      break;
+    }
+    if (mesh_point > end_mesh_point + distance) {
+      cursor->rest = 0;
+      return;
+    }
+  }
+}
+
+static grn_bool
+grn_geo_cursor_next_callback(grn_ctx *ctx, grn_ii_posting *posting,
+                             void *user_data)
+{
+  grn_ii_posting **return_posting = user_data;
+  *return_posting = posting;
+}
+
+grn_posting *
+grn_geo_cursor_next(grn_ctx *ctx, grn_obj *geo_cursor)
+{
+  grn_ii_posting *posting = NULL;
+  grn_geo_cursor_each(ctx, geo_cursor, grn_geo_cursor_next_callback, &posting);
+  return (grn_posting *)posting;
+}
+
 grn_rc
-grn_geo_select_in_rectangle(grn_ctx *ctx, grn_obj *index,
-                            grn_obj *top_left_point, grn_obj *bottom_right_point,
-                            grn_obj *res, grn_operator op)
+grn_geo_cursor_close(grn_ctx *ctx, grn_obj *geo_cursor)
+{
+  grn_geo_cursor_in_rectangle *cursor;
+
+  if (!geo_cursor) { return GRN_INVALID_ARGUMENT; }
+
+  cursor = (grn_geo_cursor_in_rectangle *)geo_cursor;
+  if (cursor->pat) { grn_obj_unlink(ctx, cursor->pat); }
+  if (cursor->index) { grn_obj_unlink(ctx, cursor->index); }
+  if (cursor->pat_cursor) { grn_table_cursor_close(ctx, cursor->pat_cursor); }
+  if (cursor->ii_cursor) { grn_ii_cursor_close(ctx, cursor->ii_cursor); }
+  GRN_FREE(cursor);
+
+  return GRN_SUCCESS;
+}
+
+static inline grn_rc
+grn_geo_select_in_rectangle_loop(grn_ctx *ctx, grn_obj *index,
+                                 grn_obj *top_left_point,
+                                 grn_obj *bottom_right_point,
+                                 grn_obj *res, grn_operator op)
 {
   in_rectangle_data data;
 
@@ -929,9 +1133,9 @@ grn_geo_select_in_rectangle(grn_ctx *ctx, grn_obj *index,
 
   {
     grn_obj *pat;
-    int diff_bit, i, start, end, distance;
+    int diff_bit, mesh_point, start, end, distance;
     grn_geo_point *top_left, *bottom_right, *base;
-    mesh_direction direction;
+    grn_geo_mesh_direction direction;
 
     pat = data.pat;
     start = data.start;
@@ -942,7 +1146,7 @@ grn_geo_select_in_rectangle(grn_ctx *ctx, grn_obj *index,
     bottom_right = data.bottom_right;
     base = &(data.base);
     diff_bit = data.diff_bit;
-    for (i = start; i < end + distance; i += distance) {
+    for (mesh_point = start; mesh_point < end + distance; mesh_point += distance) {
       grn_table_cursor *tc;
       tc = grn_table_cursor_open(ctx, pat,
                                  base, diff_bit,
@@ -950,9 +1154,9 @@ grn_geo_select_in_rectangle(grn_ctx *ctx, grn_obj *index,
                                  0, -1,
                                  GRN_CURSOR_PREFIX|GRN_CURSOR_SIZE_BY_BIT);
 #ifdef GEO_DEBUG
-      printf("i:                   %10d\n", i);
+      printf("mesh-point:          %10d\n", mesh_point);
 #endif
-      inspect_mesh(ctx, base, diff_bit, (i - data.start) / distance);
+      inspect_mesh(ctx, base, diff_bit, (mesh_point - start) / distance);
       if (tc) {
         grn_id tid;
         grn_geo_point point;
@@ -966,7 +1170,7 @@ grn_geo_select_in_rectangle(grn_ctx *ctx, grn_obj *index,
         }
         grn_table_cursor_close(ctx, tc);
       }
-      if (direction == MESH_LATITUDE) {
+      if (direction == GRN_GEO_MESH_LATITUDE) {
         base->latitude += distance;
       } else {
         base->longitude += distance;
@@ -980,6 +1184,66 @@ exit :
   return ctx->rc;
 }
 
+typedef struct {
+  grn_hash *res;
+  grn_operator op;
+} grn_geo_select_in_rectangle_data;
+
+static grn_bool
+grn_geo_select_in_rectangle_callback(grn_ctx *ctx, grn_ii_posting *posting,
+                                     void *user_data)
+{
+  grn_geo_select_in_rectangle_data *data = user_data;
+  grn_ii_posting_add(ctx, posting, data->res, data->op);
+  return GRN_TRUE;
+}
+
+static inline grn_rc
+grn_geo_select_in_rectangle_cursor(grn_ctx *ctx, grn_obj *index,
+                                   grn_obj *top_left_point,
+                                   grn_obj *bottom_right_point,
+                                   grn_obj *res, grn_operator op)
+{
+  grn_obj *cursor;
+  grn_posting *posting;
+
+  cursor = grn_geo_cursor_open_in_rectangle(ctx, index,
+                                            top_left_point, bottom_right_point,
+                                            0, -1);
+  if (cursor) {
+    grn_geo_cursor_in_rectangle *geo_cursor = (grn_geo_cursor_in_rectangle *)cursor;
+    grn_geo_select_in_rectangle_data data;
+    data.res = (grn_hash *)res;
+    data.op = op;
+    grn_geo_cursor_each(ctx, cursor, grn_geo_select_in_rectangle_callback,
+                        &data);
+    grn_obj_unlink(ctx, cursor);
+    grn_ii_resolve_sel_and(ctx, (grn_hash *)res, op);
+  }
+
+  return ctx->rc;
+}
+
+grn_rc
+grn_geo_select_in_rectangle(grn_ctx *ctx, grn_obj *index,
+                            grn_obj *top_left_point, grn_obj *bottom_right_point,
+                            grn_obj *res, grn_operator op)
+{
+  char *grn_geo_select_in_rectangle_env;
+
+  grn_geo_select_in_rectangle_env = getenv("GRN_GEO_SELECT_IN_RECTANGLE");
+  if (grn_geo_select_in_rectangle_env &&
+      strcmp(grn_geo_select_in_rectangle_env, "cursor") == 0) {
+    return grn_geo_select_in_rectangle_cursor(ctx, index,
+                                              top_left_point, bottom_right_point,
+                                              res, op);
+  } else {
+    return grn_geo_select_in_rectangle_loop(ctx, index,
+                                            top_left_point, bottom_right_point,
+                                            res, op);
+  }
+}
+
 static grn_rc
 geo_point_get(grn_ctx *ctx, grn_obj *pat, int flags, grn_geo_point *geo_point)
 {

  Modified: lib/geo.h (+32 -0)
===================================================================
--- lib/geo.h    2011-10-17 21:50:55 +0000 (c5832e4)
+++ lib/geo.h    2011-10-16 07:45:39 +0000 (791f7c5)
@@ -21,6 +21,9 @@
 #include "groonga_in.h"
 #endif /* GROONGA_IN_H */
 
+#include "ii.h"
+#include "db.h"
+
 #ifdef WIN32
 #define _USE_MATH_DEFINES
 #endif /* WIN32 */
@@ -51,6 +54,35 @@ extern "C" {
   _longitude = GRN_GEO_INT2RAD(_val->longitude);\
 } while (0)
 
+typedef enum _grn_geo_mesh_direction grn_geo_mesh_direction;
+enum _grn_geo_mesh_direction {
+  GRN_GEO_MESH_LATITUDE,
+  GRN_GEO_MESH_LONGITUDE
+};
+
+typedef struct _grn_geo_cursor_in_rectangle grn_geo_cursor_in_rectangle;
+struct _grn_geo_cursor_in_rectangle {
+  grn_db_obj obj;
+  grn_obj *pat;
+  grn_obj *index;
+  int diff_bit;
+  int start_mesh_point;
+  int end_mesh_point;
+  int distance;
+  grn_geo_mesh_direction direction;
+  grn_geo_point top_left;
+  grn_geo_point bottom_right;
+  grn_geo_point base;
+  grn_geo_point current;
+  grn_table_cursor *pat_cursor;
+  grn_ii_cursor *ii_cursor;
+  int offset;
+  int rest;
+};
+
+grn_rc grn_geo_cursor_close(grn_ctx *ctx, grn_obj *geo_cursor);
+
+
 int grn_geo_table_sort(grn_ctx *ctx, grn_obj *table, int offset, int limit,
                        grn_obj *result, grn_table_sort_key *keys, int n_keys);
 

  Modified: lib/ii.c (+7 -0)
===================================================================
--- lib/ii.c    2011-10-17 21:50:55 +0000 (7fe6433)
+++ lib/ii.c    2011-10-16 07:45:39 +0000 (14ac12d)
@@ -5472,6 +5472,13 @@ res_add(grn_ctx *ctx, grn_hash *s, grn_rset_posinfo *pi, uint32_t score,
   }
 }
 
+grn_rc
+grn_ii_posting_add(grn_ctx *ctx, grn_ii_posting *pos, grn_hash *s, grn_operator op)
+{
+  res_add(ctx, s, (grn_rset_posinfo *)(pos), (1 + pos->weight), op);
+  return ctx->rc;
+}
+
 #ifdef USE_BHEAP
 
 /* todo */

  Modified: lib/ii.h (+3 -0)
===================================================================
--- lib/ii.h    2011-10-17 21:50:55 +0000 (ce894ec)
+++ lib/ii.h    2011-10-16 07:45:39 +0000 (c0c609e)
@@ -129,6 +129,9 @@ typedef struct {
 
 typedef struct _grn_ii_cursor grn_ii_cursor;
 
+GRN_API grn_rc grn_ii_posting_add(grn_ctx *ctx, grn_ii_posting *pos,
+                                  grn_hash *s, grn_operator op);
+
 GRN_API grn_ii_cursor *grn_ii_cursor_open(grn_ctx *ctx, grn_ii *ii, grn_id tid,
                                           grn_id min, grn_id max, int nelements, int flags);
 grn_ii_cursor *grn_ii_cursor_openv1(grn_ii *ii, uint32_t key);

  Modified: test/benchmark/bench-geo-select.c (+117 -12)
===================================================================
--- test/benchmark/bench-geo-select.c    2011-10-17 21:50:55 +0000 (2ff53f0)
+++ test/benchmark/bench-geo-select.c    2011-10-16 07:45:39 +0000 (867306f)
@@ -18,13 +18,16 @@
 
 /*
   groonga: e65e87f0039f6bb2da3d9b959423774d3f66b567
-  CFLAGS: -O0 -g
-  CPU: Intel(R) Core(TM) i5 CPU       U 470  @ 1.33GHz stepping 05
+  CFLAGS: -O0 -ggdb3
+  CPU: Intel(R) Core(TM) i7 CPU         860  @ 2.80GHz stepping 05
 
   % (cd test/benchmark; make --quiet run-bench-geo-select)
   run-bench-geo-select:
-                         (time)
-    select_in_rectangle: (1.84038)
+                                        (time)
+    select_in_rectangle (1st)   (loop): (0.943075)
+    select_in_rectangle (1st) (cursor): (0.937281)
+    select_in_rectangle (2nd)   (loop): (0.928663)
+    select_in_rectangle (2nd) (cursor): (0.947011)
 */
 
 #include <string.h>
@@ -48,6 +51,8 @@ typedef struct _BenchmarkData
 
   grn_obj top_left_point;
   grn_obj bottom_right_point;
+
+  const gchar *original_in_rectangle_implementation;
 } BenchmarkData;
 
 static void
@@ -62,12 +67,15 @@ set_geo_point(grn_ctx *context, grn_obj *geo_point, const gchar *geo_point_text)
 }
 
 static void
-bench_setup(gpointer user_data)
+bench_setup_common(gpointer user_data)
 {
   BenchmarkData *data = user_data;
   const gchar *tokyo_station = "35.68136,139.76609";
   const gchar *ikebukuro_station = "35.72890,139.71036";
 
+  data->original_in_rectangle_implementation =
+    g_getenv("GRN_GEO_SELECT_IN_RECTANGLE");
+
   data->result = grn_table_create(data->context, NULL, 0, NULL,
                                   GRN_OBJ_TABLE_HASH_KEY | GRN_OBJ_WITH_SUBREC,
                                   data->table, NULL);
@@ -79,6 +87,76 @@ bench_setup(gpointer user_data)
 }
 
 static void
+bench_setup_implementation_loop(gpointer user_data)
+{
+  g_setenv("GRN_GEO_SELECT_IN_RECTANGLE", "loop", TRUE);
+}
+
+static void
+bench_setup_implementation_cursor(gpointer user_data)
+{
+  g_setenv("GRN_GEO_SELECT_IN_RECTANGLE", "cursor", TRUE);
+}
+
+static void
+bench_setup_query_partial(gpointer user_data)
+{
+  BenchmarkData *data = user_data;
+  const gchar *tokyo_station = "35.68136,139.76609";
+  const gchar *ikebukuro_station = "35.72890,139.71036";
+
+  set_geo_point(data->context, &(data->top_left_point),
+                ikebukuro_station);
+  set_geo_point(data->context, &(data->bottom_right_point),
+                tokyo_station);
+}
+
+static void
+bench_setup_query_all(gpointer user_data)
+{
+  BenchmarkData *data = user_data;
+  const gchar *tokyo_station = "35.0,140.0";
+  const gchar *ikebukuro_station = "36.0,139.0";
+
+  set_geo_point(data->context, &(data->top_left_point),
+                ikebukuro_station);
+  set_geo_point(data->context, &(data->bottom_right_point),
+                tokyo_station);
+}
+
+static void
+bench_setup_in_rectangle_loop_partial(gpointer user_data)
+{
+  bench_setup_common(user_data);
+  bench_setup_implementation_loop(user_data);
+  bench_setup_query_partial(user_data);
+}
+
+static void
+bench_setup_in_rectangle_cursor_partial(gpointer user_data)
+{
+  bench_setup_common(user_data);
+  bench_setup_implementation_cursor(user_data);
+  bench_setup_query_partial(user_data);
+}
+
+static void
+bench_setup_in_rectangle_loop_all(gpointer user_data)
+{
+  bench_setup_common(user_data);
+  bench_setup_implementation_loop(user_data);
+  bench_setup_query_all(user_data);
+}
+
+static void
+bench_setup_in_rectangle_cursor_all(gpointer user_data)
+{
+  bench_setup_common(user_data);
+  bench_setup_implementation_cursor(user_data);
+  bench_setup_query_all(user_data);
+}
+
+static void
 bench_geo_select_in_rectangle(gpointer user_data)
 {
   BenchmarkData *data = user_data;
@@ -101,6 +179,15 @@ bench_teardown(gpointer user_data)
   }
 
   grn_obj_unlink(data->context, data->result);
+
+  if (data->original_in_rectangle_implementation) {
+    g_setenv("GRN_GEO_SELECT_IN_RECTANGLE",
+             data->original_in_rectangle_implementation,
+             TRUE);
+  } else {
+    g_unsetenv("GRN_GEO_SELECT_IN_RECTANGLE");
+  }
+  data->original_in_rectangle_implementation = NULL;
 }
 
 static gchar *
@@ -169,13 +256,31 @@ main(int argc, gchar **argv)
 
   reporter = bench_reporter_new();
 
-#define REGISTER(label, type)                           \
-  bench_reporter_register(reporter, label, n,           \
-                          bench_setup,                  \
-                          bench_geo_select_ ## type,    \
-                          bench_teardown,               \
-                          &data)
-  REGISTER("select_in_rectangle", in_rectangle);
+#define REGISTER(label, type, implementation, area)                     \
+  bench_reporter_register(                                              \
+    reporter,                                                           \
+    label,                                                              \
+    n,                                                                  \
+    bench_setup_ ## type ## _ ## implementation ## _ ## area,           \
+    bench_geo_select_ ## type,                                          \
+    bench_teardown,                                                     \
+    &data)
+  REGISTER("1st: select_in_rectangle   (loop) (partial)",
+           in_rectangle, loop, partial);
+  REGISTER("1st: select_in_rectangle (cursor) (partial)",
+           in_rectangle, cursor, partial);
+  REGISTER("2nd: select_in_rectangle   (loop) (partial)",
+           in_rectangle, loop, partial);
+  REGISTER("2nd: select_in_rectangle (cursor) (partial)",
+           in_rectangle, cursor, partial);
+  REGISTER("1st: select_in_rectangle   (loop)     (all)",
+           in_rectangle, loop, all);
+  REGISTER("1st: select_in_rectangle (cursor)     (all)",
+           in_rectangle, cursor, all);
+  REGISTER("2nd: select_in_rectangle   (loop)     (all)",
+           in_rectangle, loop, all);
+  REGISTER("2nd: select_in_rectangle (cursor)     (all)",
+           in_rectangle, cursor, all);
 #undef REGISTER
 
   bench_reporter_run(reporter);




Groonga-commit メーリングリストの案内
Back to archive index