File: osmium_benchmark_static_vs_dynamic_index.cpp

package info (click to toggle)
libosmium 2.22.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 4,544 kB
  • sloc: cpp: 52,804; sh: 148; makefile: 19
file content (153 lines) | stat: -rw-r--r-- 5,941 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/*

  This benchmarks compares the run time for statically vs. dynamically
  configured index maps. You can configure index maps at compile-time using
  typedefs or at run-time using polymorphism.

  This will read the input file into a buffer and then run the
  NodeLocationForWays handler multiple times over the complete data. The
  number of runs depends on the size of the input, but is never smaller
  than 10.

  Do not run this with very large input files! It will need about 10 times
  as much RAM as the file size of the input file.

  The code in this file is released into the Public Domain.

*/

#include <osmium/handler/node_locations_for_ways.hpp>
#include <osmium/index/map/all.hpp>
#include <osmium/io/any_input.hpp>
#include <osmium/visitor.hpp>

#include <algorithm>
#include <chrono>
#include <cmath>
#include <cstdlib>
#include <exception>
#include <iostream>
#include <limits>
#include <memory>
#include <ratio>
#include <string>

using static_index_type = osmium::index::map::SparseMemArray<osmium::unsigned_object_id_type, osmium::Location>;
const std::string location_store{"sparse_mem_array"};

using dynamic_index_type = osmium::index::map::Map<osmium::unsigned_object_id_type, osmium::Location>;

using static_location_handler_type = osmium::handler::NodeLocationsForWays<static_index_type>;
using dynamic_location_handler_type = osmium::handler::NodeLocationsForWays<dynamic_index_type>;

int main(int argc, char* argv[]) {
    if (argc != 2) {
        std::cerr << "Usage: " << argv[0] << " OSMFILE\n";
        return 1;
    }

    try {
        const std::string input_filename{argv[1]};

        const osmium::memory::Buffer buffer{osmium::io::read_file(input_filename)};

        const auto& map_factory = osmium::index::MapFactory<osmium::unsigned_object_id_type, osmium::Location>::instance();

        const auto buffer_size = buffer.committed() / (1024UL * 1024UL); // buffer size in MBytes
        const int runs = std::max(10, static_cast<int>(5000ULL / buffer_size));

        std::cout << "input: filename=" << input_filename << " buffer_size=" << buffer_size << "MBytes\n";
        std::cout << "runs: " << runs << "\n";

        double static_min = std::numeric_limits<double>::max();
        double static_sum = 0;
        double static_max = 0;

        double dynamic_min = std::numeric_limits<double>::max();
        double dynamic_sum = 0;
        double dynamic_max = 0;

        for (int i = 0; i < runs; ++i) {

            {
                // static index
                osmium::memory::Buffer tmp_buffer{buffer.committed()};
                for (const auto& item : buffer) {
                    tmp_buffer.add_item(item);
                    tmp_buffer.commit();
                }

                static_index_type static_index;
                static_location_handler_type static_location_handler{static_index};

                const auto start = std::chrono::steady_clock::now();
                osmium::apply(tmp_buffer, static_location_handler);
                const auto end = std::chrono::steady_clock::now();

                const double duration = std::chrono::duration<double, std::milli>(end - start).count();

                if (duration < static_min) {
                    static_min = duration;
                }
                if (duration > static_max) {
                    static_max = duration;
                }
                static_sum += duration;
            }

            {
                // dynamic index
                osmium::memory::Buffer tmp_buffer{buffer.committed()};
                for (const auto& item : buffer) {
                    tmp_buffer.add_item(item);
                    tmp_buffer.commit();
                }

                std::unique_ptr<dynamic_index_type> index = map_factory.create_map(location_store);
                dynamic_location_handler_type dynamic_location_handler{*index};
                dynamic_location_handler.ignore_errors();

                const auto start = std::chrono::steady_clock::now();
                osmium::apply(tmp_buffer, dynamic_location_handler);
                const auto end = std::chrono::steady_clock::now();

                const double duration = std::chrono::duration<double, std::milli>(end - start).count();

                if (duration < dynamic_min) {
                    dynamic_min = duration;
                }
                if (duration > dynamic_max) {
                    dynamic_max = duration;
                }
                dynamic_sum += duration;
            }
        }

        const double static_avg = static_sum / runs;
        const double dynamic_avg = dynamic_sum / runs;

        std::cout << "static  min=" << static_min << "ms avg=" << static_avg << "ms max=" << static_max << "ms\n";
        std::cout << "dynamic min=" << dynamic_min << "ms avg=" << dynamic_avg << "ms max=" << dynamic_max << "ms\n";

        const double rfactor = 100.0;
        const double diff_min = std::round((dynamic_min - static_min) * rfactor) / rfactor;
        const double diff_avg = std::round((dynamic_avg - static_avg) * rfactor) / rfactor;
        const double diff_max = std::round((dynamic_max - static_max) * rfactor) / rfactor;

        const double prfactor = 10.0;
        const double percent_min = std::round((100.0 * diff_min / static_min) * prfactor) / prfactor;
        const double percent_avg = std::round((100.0 * diff_avg / static_avg) * prfactor) / prfactor;
        const double percent_max = std::round((100.0 * diff_max / static_max) * prfactor) / prfactor;

        std::cout << "difference:";
        std::cout << " min=" << diff_min << "ms (" << percent_min << "%)";
        std::cout << " avg=" << diff_avg << "ms (" << percent_avg << "%)";
        std::cout << " max=" << diff_max << "ms (" << percent_max << "%)\n";
    } catch (const std::exception& e) {
        std::cerr << e.what() << '\n';
        return 1;
    }

    return 0;
}