[postgis-tickets] [PostGIS] #4543: Use Ryū to output floating point numbers
PostGIS
trac at osgeo.org
Mon Oct 14 09:12:54 PDT 2019
#4543: Use Ryū to output floating point numbers
-------------------------+---------------------------
Reporter: Algunenano | Owner: Algunenano
Type: enhancement | Status: assigned
Priority: medium | Milestone: PostGIS 3.1.0
Component: liblwgeom | Version: trunk
Keywords: |
-------------------------+---------------------------
PG12 introduced an implementation of Ryū
(https://dl.acm.org/citation.cfm?id=3192369) to speed up the
transformation between floating points and strings, as it can be 10x
faster than a straight `sprintf(str, "%f", double)`.
It seemed to me that multiple Postgis' functions could use a similar
improvement so I've tested nasty hack to use Postgres' RYU implementation
for `lwprint_double` (this is a hack, so it doesn't take into account
desired precision or space left in the buffer):
Before:
{{{
explain analyze Select ST_AsText(the_geom) from
benchmark_4c7214d90a79aa6760367a084a4d4a2f61fbe1c6cc4f7f9e76020;
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------------------------------------
Seq Scan on
benchmark_4c7214d90a79aa6760367a084a4d4a2f61fbe1c6cc4f7f9e76020
(cost=0.00..33.63 rows=13 width=32) (actual time=547.194..5313.276 rows=13
loops=1)
Planning Time: 0.144 ms
Execution Time: 5313.322 ms
(3 rows)
}}}
After:
{{{
Seq Scan on
benchmark_4c7214d90a79aa6760367a084a4d4a2f61fbe1c6cc4f7f9e76020
(cost=0.00..33.63 rows=13 width=32) (actual time=64.062..478.339 rows=13
loops=1)
Planning Time: 0.628 ms
Execution Time: 478.373 ms
(3 rows)
}}}
The hack involves using PG function in liblwgeom, so that's a no-go from
the start, but it's useful to compare performance and see what kind of
improvement we could expect to get if we decided to go that way:
{{{
diff --git a/liblwgeom/lwprint.c b/liblwgeom/lwprint.c
index af56c4c27..1a0dc886d 100644
--- a/liblwgeom/lwprint.c
+++ b/liblwgeom/lwprint.c
@@ -486,27 +486,13 @@ trim_trailing_zeros(char* str)
* truncated and misses a terminating NULL.
*
*/
+/* This is also provided by snprintf.c */
+extern int double_to_shortest_decimal_bufn(double f, char *result);
+
int
lwprint_double(double d, int maxdd, char* buf, size_t bufsize)
{
- double ad = fabs(d);
- int ndd;
- int length = 0;
- if (ad <= FP_TOLERANCE)
- {
- d = 0;
- ad = 0;
- }
- if (ad < OUT_MAX_DOUBLE)
- {
- ndd = ad < 1 ? 0 : floor(log10(ad)) + 1; /* non-decimal digits */
- if (maxdd > (OUT_MAX_DOUBLE_PRECISION - ndd)) maxdd -= ndd;
- length = snprintf(buf, bufsize, "%.*f", maxdd, d);
- }
- else
- {
- length = snprintf(buf, bufsize, "%g", d);
- }
- trim_trailing_zeros(buf);
- return length;
+ int b = double_to_shortest_decimal_bufn(d, buf);
+ buf[b] = 0;
+ return b;
}
\ No newline at end of file
}}}
--
Ticket URL: <https://trac.osgeo.org/postgis/ticket/4543>
PostGIS <http://trac.osgeo.org/postgis/>
The PostGIS Trac is used for bug, enhancement & task tracking, a user and developer wiki, and a view into the subversion code repository of PostGIS project.
More information about the postgis-tickets
mailing list