Skip to content

Commit 1796874

Browse files
authored
Merge pull request #2061 from joto/low-level-performance
Improve performance of some low level code
2 parents 6b54236 + 422ba14 commit 1796874

File tree

7 files changed

+55
-41
lines changed

7 files changed

+55
-41
lines changed

src/gen/gen-rivers.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ SELECT "{id_column}", "{width_column}", "{name_column}", "{geom_column}"
258258
if (!name.empty()) {
259259
names.emplace(id, name);
260260
}
261-
auto const geom = ewkb_to_geom(decode_hex(result.get_value(i, 3)));
261+
auto const geom = ewkb_to_geom(decode_hex(result.get(i, 3)));
262262

263263
if (geom.is_linestring()) {
264264
auto const &ls = geom.get<geom::linestring_t>();

src/gen/gen-tile-builtup.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ static void draw_from_db(double margin, canvas_list_t *canvas_list,
173173
box.max_x(), box.max_y());
174174

175175
for (int n = 0; n < result.num_tuples(); ++n) {
176-
auto const geom = ewkb_to_geom(decode_hex(result.get_value(n, 0)));
176+
auto const geom = ewkb_to_geom(decode_hex(result.get(n, 0)));
177177
cc.canvas.draw(geom, tile);
178178
}
179179
}

src/gen/gen-tile-raster.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ static void draw_from_db(double margin, unsigned int image_extent,
163163

164164
for (int n = 0; n < result.num_tuples(); ++n) {
165165
std::string param = result.get_value(n, 1);
166-
auto const geom = ewkb_to_geom(decode_hex(result.get_value(n, 0)));
166+
auto const geom = ewkb_to_geom(decode_hex(result.get(n, 0)));
167167

168168
auto const [it, success] = canvas_list->try_emplace(
169169
std::move(param), image_extent, image_buffer);

src/gen/tracer.cpp

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,21 +41,33 @@ void tracer_t::reset()
4141
m_num_points = 0;
4242
}
4343

44+
static potrace_word bit_squeeze(potrace_word w, unsigned char const *d) noexcept
45+
{
46+
return (0x80U & d[0]) | (0x40U & d[1]) | (0x20U & d[2]) | (0x10U & d[3]) |
47+
(0x08U & d[4]) | (0x04U & d[5]) | (0x02U & d[6]) | (0x01U & d[7]) |
48+
w;
49+
}
50+
51+
static_assert(sizeof(potrace_word) == 8);
52+
4453
void tracer_t::prepare(canvas_t const &canvas) noexcept
4554
{
4655
std::size_t const size = canvas.size();
4756
assert(size % bits_per_word == 0);
4857

4958
m_bits.reserve((size * size) / bits_per_word);
5059

51-
unsigned char const *d = canvas.begin();
52-
while (d != canvas.end()) {
53-
potrace_word w = 0x1U & *d++;
54-
for (std::size_t n = 1; n < bits_per_word; ++n) {
55-
w <<= 1U;
56-
assert(d != canvas.end());
57-
w |= 0x1U & *d++;
58-
}
60+
for (unsigned char const *d = canvas.begin(); d != canvas.end(); d += 8) {
61+
auto w = bit_squeeze(0, d);
62+
63+
w = bit_squeeze(w << 8U, d += 8);
64+
w = bit_squeeze(w << 8U, d += 8);
65+
w = bit_squeeze(w << 8U, d += 8);
66+
w = bit_squeeze(w << 8U, d += 8);
67+
w = bit_squeeze(w << 8U, d += 8);
68+
w = bit_squeeze(w << 8U, d += 8);
69+
w = bit_squeeze(w << 8U, d += 8);
70+
5971
m_bits.push_back(w);
6072
}
6173

src/wkb.cpp

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -576,32 +576,35 @@ geom::geometry_t ewkb_to_geom(std::string_view wkb)
576576
return geom;
577577
}
578578

579-
unsigned char decode_hex_char(char c)
580-
{
581-
if (c >= '0' && c <= '9') {
582-
return c - '0';
583-
}
584-
if (c >= 'A' && c <= 'F') {
585-
return c - 'A' + 10;
586-
}
587-
if (c >= 'a' && c <= 'f') {
588-
return c - 'a' + 10;
589-
}
579+
static constexpr std::array<char, 256> const hex_table = {
580+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
581+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
582+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
583+
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0,
584+
585+
0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0,
586+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
587+
0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0,
588+
};
590589

591-
throw std::runtime_error{"Invalid wkb: Not a hex character"};
590+
unsigned char decode_hex_char(char c) noexcept
591+
{
592+
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-constant-array-index)
593+
return hex_table[static_cast<std::size_t>(static_cast<unsigned char>(c))];
592594
}
593595

594-
std::string decode_hex(char const *hex)
596+
std::string decode_hex(std::string_view hex_string)
595597
{
598+
if (hex_string.size() % 2 != 0) {
599+
throw std::runtime_error{"Invalid wkb: Not a valid hex string"};
600+
}
601+
596602
std::string wkb;
603+
wkb.reserve(hex_string.size() / 2);
597604

598-
while (*hex != '\0') {
605+
// NOLINTNEXTLINE(llvm-qualified-auto, readability-qualified-auto)
606+
for (auto hex = hex_string.begin(); hex != hex_string.end();) {
599607
unsigned int const c = decode_hex_char(*hex++);
600-
601-
if (*hex == '\0') {
602-
throw std::runtime_error{"Invalid wkb: Not a valid hex string"};
603-
}
604-
605608
wkb += static_cast<char>((c << 4U) | decode_hex_char(*hex++));
606609
}
607610

src/wkb.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,15 @@
4141
[[nodiscard]] geom::geometry_t ewkb_to_geom(std::string_view wkb);
4242

4343
/**
44-
* Decode one hex character (0-9A-F or 0-9a-f) and return its value. Throw
45-
* an exception if not a valid hex character.
44+
* Decode one hex character (0-9A-F or 0-9a-f) and return its value.
45+
* Returns 0 for characters that are not hex characters.
4646
*/
47-
[[nodiscard]] unsigned char decode_hex_char(char c);
47+
[[nodiscard]] unsigned char decode_hex_char(char c) noexcept;
4848

4949
/**
5050
* Decode a string of hex characters. Throws an exception if the input is not
5151
* a valid hex encoding.
5252
*/
53-
[[nodiscard]] std::string decode_hex(char const *hex);
53+
[[nodiscard]] std::string decode_hex(std::string_view hex);
5454

5555
#endif // OSM2PGSQL_WKB_HPP

tests/test-wkb.cpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -189,15 +189,19 @@ TEST_CASE("wkb: geometrycollection", "[NoDB]")
189189

190190
TEST_CASE("wkb: invalid", "[NoDB]") { REQUIRE_THROWS(ewkb_to_geom("INVALID")); }
191191

192-
TEST_CASE("wkb hex decode of valid hex characters")
192+
TEST_CASE("wkb hex decode of valid and invalid hex characters")
193193
{
194194
REQUIRE(decode_hex_char('0') == 0);
195195
REQUIRE(decode_hex_char('9') == 9);
196196
REQUIRE(decode_hex_char('a') == 0x0a);
197197
REQUIRE(decode_hex_char('f') == 0x0f);
198198
REQUIRE(decode_hex_char('A') == 0x0a);
199199
REQUIRE(decode_hex_char('F') == 0x0f);
200-
REQUIRE_THROWS(decode_hex_char('x'));
200+
REQUIRE(decode_hex_char('#') == 0);
201+
REQUIRE(decode_hex_char('@') == 0);
202+
REQUIRE(decode_hex_char('g') == 0);
203+
REQUIRE(decode_hex_char('G') == 0);
204+
REQUIRE(decode_hex_char(0x7f) == 0);
201205
}
202206

203207
TEST_CASE("wkb hex decode of valid hex string")
@@ -216,11 +220,6 @@ TEST_CASE("wkb hex decode of valid hex string")
216220
REQUIRE(result == data);
217221
}
218222

219-
TEST_CASE("wkb hex decode of invalid hex string")
220-
{
221-
REQUIRE_THROWS(decode_hex("no"));
222-
}
223-
224223
TEST_CASE("wkb hex decode of empty string is okay")
225224
{
226225
std::string const hex{};

0 commit comments

Comments
 (0)