Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
bench-geo-distance.c
Go to the documentation of this file.
1 /* -*- c-basic-offset: 2; coding: utf-8 -*- */
2 /*
3  Copyright (C) 2009 Kouhei Sutou <kou@clear-code.com>
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Lesser General Public
7  License version 2.1 as published by the Free Software Foundation.
8 
9  This library is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  Lesser General Public License for more details.
13 
14  You should have received a copy of the GNU Lesser General Public
15  License along with this library; if not, write to the Free Software
16  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18 
19 /*
20  groonga: 3ad91b868909444f66a36dbcbdbe2292ed14bd72
21  CFLAGS: -O0 -g
22  CPU: AMD Athlon(tm) 64 Processor 3000+
23 
24  % test/benchmark/bench-geo-distance
25  (time)
26  rectangular (WGS84): (0.0813662)
27  rectangular (TOKYO): (0.0621928)
28  spherical (WGS84): (0.0760155)
29  spherical (TOKYO): (0.0660843)
30  hubeny (WGS84): (0.110684)
31  hubeny (TOKYO): (0.0702277)
32  % test/benchmark/bench-geo-distance
33  (time)
34  rectangular (WGS84): (0.0742154)
35  rectangular (TOKYO): (0.0816863)
36  spherical (WGS84): (0.074316)
37  spherical (TOKYO): (0.0696254)
38  hubeny (WGS84): (0.0650147)
39  hubeny (TOKYO): (0.0644057)
40  % test/benchmark/bench-geo-distance
41  (time)
42  rectangular (WGS84): (0.0781161)
43  rectangular (TOKYO): (0.0706679)
44  spherical (WGS84): (0.075739)
45  spherical (TOKYO): (0.0809402)
46  hubeny (WGS84): (0.0727023)
47  hubeny (TOKYO): (0.0718146)
48  */
49 
50 #include <string.h>
51 
52 #include <db.h>
53 #include <groonga.h>
54 
55 #include "lib/benchmark.h"
56 
57 #define GET(context, name) (grn_ctx_get(context, name, strlen(name)))
58 
59 grn_obj *grn_expr_get_value(grn_ctx *ctx, grn_obj *expr, int offset);
60 
61 typedef struct _BenchmarkData
62 {
63  gchar *base_dir;
64  gboolean report_result;
65 
73 
74 static void
75 bench_geo_distance(gpointer user_data)
76 {
77  BenchmarkData *data = user_data;
78 
80  2, data->expression);
81 }
82 
83 static void
84 bench_setup_common(gpointer user_data)
85 {
86  BenchmarkData *data = user_data;
87 
89  data->database = grn_db_create(data->context, NULL, NULL);
90  data->expression = grn_expr_create(data->context, NULL, 0);
91 }
92 
93 static void
94 bench_setup_points(gpointer user_data,
95  const gchar *start_point_string,
96  const gchar *end_point_string,
97  grn_builtin_type wgs84_or_tgs)
98 {
99  BenchmarkData *data = user_data;
100  grn_obj start_point_text, end_point_text;
101 
102  GRN_TEXT_INIT(&start_point_text, 0);
103  GRN_TEXT_INIT(&end_point_text, 0);
104  GRN_TEXT_SETS(data->context, &start_point_text, start_point_string);
105  GRN_TEXT_SETS(data->context, &end_point_text, end_point_string);
106 
107  data->start_point = grn_obj_open(data->context, GRN_BULK, 0, wgs84_or_tgs);
108  data->end_point = grn_obj_open(data->context, GRN_BULK, 0, wgs84_or_tgs);
109  grn_obj_cast(data->context, &start_point_text, data->start_point, GRN_FALSE);
110  grn_obj_cast(data->context, &end_point_text, data->end_point, GRN_FALSE);
111  grn_ctx_push(data->context, data->start_point);
112  grn_ctx_push(data->context, data->end_point);
113 
114  grn_obj_unlink(data->context, &start_point_text);
115  grn_obj_unlink(data->context, &end_point_text);
116 }
117 
118 static void
119 bench_setup_wgs84(gpointer user_data)
120 {
121  bench_setup_common(user_data);
122  bench_setup_points(user_data,
123  "127980000x502560000",
124  "128880000x503640000",
126 }
127 
128 static void
129 bench_setup_tgs(gpointer user_data)
130 {
131  bench_setup_common(user_data);
132  bench_setup_points(user_data,
133  "127980000x502560000",
134  "128880000x503640000",
136 }
137 
138 static void
139 bench_setup_rectangular_wgs84(gpointer user_data)
140 {
141  BenchmarkData *data = user_data;
142 
143  bench_setup_wgs84(user_data);
144  data->geo_distance_proc = GET(data->context, "geo_distance");
145 }
146 
147 static void
148 bench_setup_rectangular_tgs(gpointer user_data)
149 {
150  BenchmarkData *data = user_data;
151 
152  bench_setup_tgs(user_data);
153  data->geo_distance_proc = GET(data->context, "geo_distance");
154 }
155 
156 static void
157 bench_setup_rectangular_wgs84_1st_to_2nd_quadrant_short(gpointer user_data)
158 {
159  BenchmarkData *data = user_data;
160 
161  bench_setup_common(user_data);
162  bench_setup_points(user_data,
163  "128452975x503157902",
164  "139380000x-31920000",
166  data->geo_distance_proc = GET(data->context, "geo_distance");
167 }
168 
169 static void
170 bench_setup_rectangular_wgs84_2nd_to_1st_quadrant_short(gpointer user_data)
171 {
172  BenchmarkData *data = user_data;
173 
174  bench_setup_common(user_data);
175  bench_setup_points(user_data,
176  "139380000x-31920000",
177  "128452975x503157902",
179  data->geo_distance_proc = GET(data->context, "geo_distance");
180 }
181 
182 static void
183 bench_setup_rectangular_wgs84_1st_to_3rd_quadrant_short(gpointer user_data)
184 {
185  BenchmarkData *data = user_data;
186 
187  bench_setup_common(user_data);
188  bench_setup_points(user_data,
189  "128452975x503157902",
190  "-56880000x-172310000",
192  data->geo_distance_proc = GET(data->context, "geo_distance");
193 }
194 
195 static void
196 bench_setup_rectangular_wgs84_3rd_to_1st_quadrant_short(gpointer user_data)
197 {
198  BenchmarkData *data = user_data;
199 
200  bench_setup_common(user_data);
201  bench_setup_points(user_data,
202  "-56880000x-172310000",
203  "128452975x503157902",
205  data->geo_distance_proc = GET(data->context, "geo_distance");
206 }
207 
208 static void
209 bench_setup_rectangular_wgs84_1st_to_4th_quadrant_short(gpointer user_data)
210 {
211  BenchmarkData *data = user_data;
212 
213  bench_setup_common(user_data);
214  bench_setup_points(user_data,
215  "128452975x503157902",
216  "-122100000x66300000",
218  data->geo_distance_proc = GET(data->context, "geo_distance");
219 }
220 
221 static void
222 bench_setup_rectangular_wgs84_4th_to_1st_quadrant_short(gpointer user_data)
223 {
224  BenchmarkData *data = user_data;
225 
226  bench_setup_common(user_data);
227  bench_setup_points(user_data,
228  "-122100000x66300000",
229  "128452975x503157902",
231  data->geo_distance_proc = GET(data->context, "geo_distance");
232 }
233 
234 static void
235 bench_setup_rectangular_wgs84_2nd_to_4th_quadrant_short(gpointer user_data)
236 {
237  BenchmarkData *data = user_data;
238 
239  bench_setup_common(user_data);
240  bench_setup_points(user_data,
241  "139380000x-31920000",
242  "-122100000x66300000",
244  data->geo_distance_proc = GET(data->context, "geo_distance");
245 }
246 
247 static void
248 bench_setup_rectangular_wgs84_4th_to_2nd_quadrant_short(gpointer user_data)
249 {
250  BenchmarkData *data = user_data;
251 
252  bench_setup_common(user_data);
253  bench_setup_points(user_data,
254  "-122100000x66300000",
255  "139380000x-31920000",
257  data->geo_distance_proc = GET(data->context, "geo_distance");
258 }
259 
260 static void
261 bench_setup_rectangular_wgs84_1st_to_2nd_quadrant_long(gpointer user_data)
262 {
263  BenchmarkData *data = user_data;
264 
265  bench_setup_common(user_data);
266  bench_setup_points(user_data,
267  "128452975x503157902",
268  "135960000x-440760000",
270  data->geo_distance_proc = GET(data->context, "geo_distance");
271 }
272 
273 static void
274 bench_setup_rectangular_wgs84_2nd_to_1st_quadrant_long(gpointer user_data)
275 {
276  BenchmarkData *data = user_data;
277 
278  bench_setup_common(user_data);
279  bench_setup_points(user_data,
280  "135960000x-440760000",
281  "128452975x503157902",
283  data->geo_distance_proc = GET(data->context, "geo_distance");
284 }
285 
286 static void
287 bench_setup_rectangular_wgs84_2nd_to_3rd_quadrant_short(gpointer user_data)
288 {
289  BenchmarkData *data = user_data;
290 
291  bench_setup_common(user_data);
292  bench_setup_points(user_data,
293  "135960000x-440760000",
294  "-56880000x-172310000",
296  data->geo_distance_proc = GET(data->context, "geo_distance");
297 }
298 
299 static void
300 bench_setup_rectangular_wgs84_3rd_to_2nd_quadrant_short(gpointer user_data)
301 {
302  BenchmarkData *data = user_data;
303 
304  bench_setup_common(user_data);
305  bench_setup_points(user_data,
306  "-56880000x-172310000",
307  "135960000x-440760000",
309  data->geo_distance_proc = GET(data->context, "geo_distance");
310 }
311 
312 static void
313 bench_setup_rectangular_wgs84_3rd_to_4th_quadrant_short(gpointer user_data)
314 {
315  BenchmarkData *data = user_data;
316 
317  bench_setup_common(user_data);
318  bench_setup_points(user_data,
319  "-56880000x-172310000",
320  "-122100000x66300000",
322  data->geo_distance_proc = GET(data->context, "geo_distance");
323 }
324 
325 static void
326 bench_setup_rectangular_wgs84_4th_to_3rd_quadrant_short(gpointer user_data)
327 {
328  BenchmarkData *data = user_data;
329 
330  bench_setup_common(user_data);
331  bench_setup_points(user_data,
332  "-122100000x66300000",
333  "-56880000x-172310000",
335  data->geo_distance_proc = GET(data->context, "geo_distance");
336 }
337 
338 static void
339 bench_setup_rectangular_wgs84_3rd_to_4th_quadrant_long(gpointer user_data)
340 {
341  BenchmarkData *data = user_data;
342 
343  bench_setup_common(user_data);
344  bench_setup_points(user_data,
345  "-56880000x-172310000",
346  "-121926000x544351000",
348  data->geo_distance_proc = GET(data->context, "geo_distance");
349 }
350 
351 static void
352 bench_setup_rectangular_wgs84_4th_to_3rd_quadrant_long(gpointer user_data)
353 {
354  BenchmarkData *data = user_data;
355 
356  bench_setup_common(user_data);
357  bench_setup_points(user_data,
358  "-121926000x544351000",
359  "-56880000x-172310000",
361  data->geo_distance_proc = GET(data->context, "geo_distance");
362 }
363 
364 static void
365 bench_setup_spherical_wgs84(gpointer user_data)
366 {
367  BenchmarkData *data = user_data;
368 
369  bench_setup_wgs84(user_data);
370  data->geo_distance_proc = GET(data->context, "geo_distance2");
371 }
372 
373 static void
374 bench_setup_spherical_tgs(gpointer user_data)
375 {
376  BenchmarkData *data = user_data;
377 
378  bench_setup_tgs(user_data);
379  data->geo_distance_proc = GET(data->context, "geo_distance2");
380 }
381 
382 static void
383 bench_setup_hubeny_wgs84(gpointer user_data)
384 {
385  BenchmarkData *data = user_data;
386 
387  bench_setup_wgs84(user_data);
388  data->geo_distance_proc = GET(data->context, "geo_distance3");
389 }
390 
391 static void
392 bench_setup_hubeny_tgs(gpointer user_data)
393 {
394  BenchmarkData *data = user_data;
395 
396  bench_setup_tgs(user_data);
397  data->geo_distance_proc = GET(data->context, "geo_distance3");
398 }
399 
400 static void
401 bench_teardown(gpointer user_data)
402 {
403  BenchmarkData *data = user_data;
404 
405  if (data->report_result) {
406  grn_obj *result;
407  result = grn_expr_get_value(data->context, data->expression, 0);
408  g_print("result: %g\n", GRN_FLOAT_VALUE(result));
409  /* http://vldb.gsi.go.jp/ says '38820.79' in WGS84 and
410  '38816.42' in Tokyo geodetic system for a distance
411  between '127980000x502560000' and '128880000x503640000'. */
412  }
413 
414  grn_obj_unlink(data->context, data->end_point);
415  grn_obj_unlink(data->context, data->start_point);
416  grn_obj_unlink(data->context, data->expression);
417  grn_obj_unlink(data->context, data->database);
418  grn_ctx_fin(data->context);
419 }
420 
421 int
422 main(int argc, gchar **argv)
423 {
424  BenchmarkData data;
425  BenchReporter *reporter;
426  gint n = 1000;
427 
428  grn_init();
429  bench_init(&argc, &argv);
430 
431  data.report_result = g_getenv("GROONGA_BENCH_REPORT_RESULT") != NULL;
432  data.context = g_new(grn_ctx, 1);
433 
434  {
435  const gchar *groonga_bench_n;
436  groonga_bench_n = g_getenv("GROONGA_BENCH_N");
437  if (groonga_bench_n) {
438  n = atoi(groonga_bench_n);
439  }
440  }
441 
442  reporter = bench_reporter_new();
443 
444 #define REGISTER(label, setup) \
445  bench_reporter_register(reporter, label, n, \
446  bench_setup_ ## setup, \
447  bench_geo_distance, \
448  bench_teardown, \
449  &data)
450  REGISTER("rectangular (WGS84)", rectangular_wgs84);
451  REGISTER("rectangular (TOKYO)", rectangular_tgs);
452  REGISTER("rectangular (WGS84 Tokyo to Lisbon)",
453  rectangular_wgs84_1st_to_2nd_quadrant_short);
454  REGISTER("rectangular (WGS84 Lisbon to Tokyo)",
455  rectangular_wgs84_2nd_to_1st_quadrant_short);
456  REGISTER("rectangular (WGS84 Tokyo to San Francisco)",
457  rectangular_wgs84_1st_to_2nd_quadrant_long);
458  REGISTER("rectangular (WGS84 San Francisco to Tokyo)",
459  rectangular_wgs84_2nd_to_1st_quadrant_long);
460  REGISTER("rectangular (WGS84 Brasplia to Cape Town)",
461  rectangular_wgs84_3rd_to_4th_quadrant_short);
462  REGISTER("rectangular (WGS84 Cape Town to Brasplia)",
463  rectangular_wgs84_4th_to_3rd_quadrant_short);
464  REGISTER("rectangular (WGS84 Brasplia to Sydney)",
465  rectangular_wgs84_3rd_to_4th_quadrant_long);
466  REGISTER("rectangular (WGS84 Sydney to Brasplia)",
467  rectangular_wgs84_4th_to_3rd_quadrant_long);
468  REGISTER("rectangular (WGS84 Tokyo to Brasplia)",
469  rectangular_wgs84_1st_to_4th_quadrant_short);
470  REGISTER("rectangular (WGS84 Brasplia to Tokyo)",
471  rectangular_wgs84_4th_to_1st_quadrant_short);
472  REGISTER("rectangular (WGS84 Lisbon to Cape Town)",
473  rectangular_wgs84_2nd_to_3rd_quadrant_short);
474  REGISTER("rectangular (WGS84 Cape Town to Lisbon)",
475  rectangular_wgs84_3rd_to_2nd_quadrant_short);
476  REGISTER("rectangular (WGS84 Tokyo to Cape Town)",
477  rectangular_wgs84_1st_to_3rd_quadrant_short);
478  REGISTER("rectangular (WGS84 Cape Town to Tokyo)",
479  rectangular_wgs84_3rd_to_1st_quadrant_short);
480  REGISTER("rectangular (WGS84 Lisbon to Cape Town)",
481  rectangular_wgs84_2nd_to_4th_quadrant_short);
482  REGISTER("rectangular (WGS84 Cape Town to Lisbon)",
483  rectangular_wgs84_4th_to_2nd_quadrant_short);
484  REGISTER("spherical (WGS84)", spherical_wgs84);
485  REGISTER("spherical (TOKYO)", spherical_tgs);
486  REGISTER("hubeny (WGS84)", hubeny_wgs84);
487  REGISTER("hubeny (TOKYO)", hubeny_tgs);
488 #undef REGISTER
489 
490  bench_reporter_run(reporter);
491  g_object_unref(reporter);
492 
493  g_free(data.context);
494 
495  bench_quit();
496  grn_fin();
497 
498  return 0;
499 }