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);