Aquileo | Jochen Topfhttps://blog.jochentopf.com/
Personal blog of Jochen TopfenWed, 03 Jun 2026 17:18:13 +0200Rassmalog 12.0.1Aquileo | Spyglass Improvementshttps://blog.jochentopf.com/2026-06-03-spyglass-improvements.html
https://blog.jochentopf.com/2026-06-03-spyglass-improvements.htmlWed, 03 Jun 2026 17:14:10 +0200<p>Whenever I have some time, I keep improving <a href="https://spyglass.jochentopf.com/"><span class="caps">OSM</span> Spyglass</a>. A very useful addition is that Spyglass now shows suggestions for the key and value filter fields. Spyglass gets possible keys/values from the data currently loaded and will show all keys/values matching what you have typed so far.</p> <p>There are many other small improvements in the UI, one is a new menu option in the location control: Switch lat/lon. Very useful when you have a system that shows the coordinates the other way around from what <span class="caps">OSM</span> Spyglass expects (for instance <span class="caps">QGIS</span>). Just copy and paste the coordinates, Spyglass will jump to the wrong location, but one click later you are at the right spot.</p> <p>There are many internal changes also. There is support now for storing <span class="caps">OSM</span> object attributes (version, changeset, timestamp) with the data. (No support for user ids or user names so far.) Attributes are currently not enabled on the version running on <a href="https://spyglass.jochentopf.com/">spyglass.jochentopf.com</a> to save some disk space and import time, and they are not shown in the UI anyways. More work for the future…</p> <p>There are also plenty of changes with the database tables, how I am organizing the data internally. I am trying out various formats to minimize storage and make queries more efficient and/or easy to use. The biggest change is that I switched from using <span class="caps">JSONB</span> for the tags to that old classic, the <tt>hstore</tt> format. <span class="caps">JSONB</span> and <tt>hstore</tt> are quite similar for what we are doing here, but there is one big difference: It is possible to create a <span class="caps">GIST</span> index that combines geometry and tags when using <tt>hstore</tt> making queries with key/value filter somewhat faster.</p> <p>Another area I have been experimenting with is how to detect and display “unusual data”. Unusual data in this case are things like ways that contain only a single node, or ways having duplicate nodes in them, relations without <tt>type</tt> tag or without members and so on. So we are talking about some low-level errors in the data, that I want to detect and show to the user in a useful way, so that they can figure out why some object is not showing up properly in the map. Single-node ways, for instance, would usually not be visible, because you can’t have a line with only one point in it. So this case is detected and the way shown as black point with an orange center. When selected, the way is shown with a message “Way contains only a single point!”.</p> <p>Some other “unusual” cases are currently detected and the information is in the database but now shown yet.</p>openstreetmapspyglassAquileo | OSM Spyglasshttps://blog.jochentopf.com/2026-02-19-osm-spyglass.html
https://blog.jochentopf.com/2026-02-19-osm-spyglass.htmlThu, 19 Feb 2026 21:32:50 +0100<p>Two years ago or so I started the <span class="caps">OSM</span> <span class="caps">XRAY</span> project, later I wrote about it <a href="https://blog.jochentopf.com/2024-09-30-introducing-osm-xray.html">in this blog post</a>. Since then I have renamed this project to “<span class="caps">OSM</span> Spyglass” and I have kept working on it on and off.</p> <p>At the <a href="https://2025.stateofthemap.eu/">State of the Map Europe 2025 in Dundee</a> I gave a talk with the title <i>“Everything Everywhere All At Once”</i> about this project. You can see the video <a href="https://www.youtube.com/watch?v=U_GxGnAdWZI">on Youtube</a>. This got some people excited about the project, there is even some talk about <a href="https://github.com/openstreetmap/operations/issues/1313">putting the tool on <span class="caps">OSMF</span> infrastructure</a>. Until this comes about the tool is now hosted at <a href="https://spyglass.jochentopf.com/">spyglass.jochentopf.com</a>.</p> <p>I am finally getting around to writing some more about what’s been happening since my first announcement and since the talk.</p>
<h2>User Interface</h2> <p>I keep fiddling with the user interface. Optional globe view (not much to do for me now that Maplibre supports that out of the box), map is now resizable (horizontally), display of city names in some zoom levels, improved pop-up menus for keys and tags, and much more. Generally the UI has been getting faster and more reliable.</p> <p>There are still some bugs to fix and plenty of possible improvements. And I’d be happy about feedback and ideas. Its quite a lot of information we are trying to show here in limited space, so good ideas on how to do that are needed.</p>
<h2>Caching</h2> <p>In the first blog post I wrote about some caching that I implemented in the database. That did work but it turns out it is pretty useless. The user wants to access the newest data anway and we can keep up with minutely updates (at least in larger zoom levels), so I removed the caching completely for vector tiles and for high zoom rasters. Only raster images at zoom levels up to 10 are cached. Currently we can not deliver them fast enough otherwise.</p>
<h2>Map updates</h2> <p>The database is updated from <span class="caps">OSM</span> using minutely diffs. We are usually about 3 to 5 minutes behind the <span class="caps">OSM</span> data, that’s just how long it takes the <span class="caps">OSM</span> servers to create the minutely diffs, push them out to their server and for our update job to download the data and to apply it to the database. It is unlikely we can improve on that much further. Spyglass shows the timestamp of the latest data it has in the bottom right corner. This timestamp is updated whenever new data is loaded, i.e. when you move the map or so.</p> <p>Vector tiles are always generated on the fly from the current database, for higher zoom levels they contain all data, for medium zoom levels only “larger” objects are shown, i.e. long ways and larger areas. In small and medium zoom levels raster tiles are shown. They always contain all data. So for the medium zoom levels raster data in gray is overlayed with vector data in black (nodes and ways) or blue (relations). So you can see everything, but only click on the larger items.</p> <p>Raster tiles in small zoom levels are only updated once per day, for zoom 0 to 7 this happens by taking the zoom level 8 tiles, and merging and rescaling them. I have spent quite some time on optimizing this. The first version happened in the database but only generated black-and-white tiles, the current version uses code written in Go which creates grayscale images which are much better than the black-and-white images. And it is much faster than the gdal tools I tried for this task. Gdal is a great tool, but, as an “all purpose tool”, it has to cope with all sorts of different data sources, projections etc. which makes it much slower than a specialized tool for a specific use case. It only takes a few minutes now to create the low zoom tiles from the zoom level 8 tiles. And they are not stored in the database any more but on disk which is easier and they are faster to use that way, too.</p> <p>Rasters are still generated in the database from the data. That is, unfortunately, not as efficient as one might think. We don’t need to copy the data from the database into another process, and the cost of actually getting the data seems to be not that huge, but the rasterizing costs time. This is probably something that could be improved inside PostGIS, or maybe we have to get rid of this idea alltogether and move rendering outside the database. There is plenty of space to experiment and improve performance here.</p>
<h2>Server</h2> <p>Originally I used pg_tileserv as server to create the vector tiles from the database on the fly. It could also be tricked into creating the raster tiles. But I also needed GeoJSON output and some other <span class="caps">API</span> endpoints. I experimented with pg_featureserv which did work, but having two servers with lots of specialized PL/pgSQL functions in the database plus an ever growing configuration for nginx (used as reverse proxy) became too complicated and error prone. So I decided to rewrite the server from scratch in Go. Turns out it is really easy to write robust and featureful <span class="caps">HTTP</span> servers in Go, it comes with everything you need; the only external library I am using is for accessing the database. And deployment is really easy: Just copy over one Go binary and restart the server, no extra configuration files or functions to update in the database etc.</p>
<h2>Filters</h2> <p>Everything is done three times for nodes, ways, and relations. There are three sets of raster tiles, 3 sets of vector tiles. It is easy to switch those layers on and off in the UI. And then there is the key or tag filter. The vector tiles in higher zoom levels contain all the data, the filter is applied on the client, which is very fast. For raster tiles the filtering has to be done on the server which takes somewhat more time. Filtering is (silently) disabled on the small zoom levels, so you always see all data there. This isn’t great as a user experience, I’ll still have to figure out a way to make this transition more user friendly. Or, ideally, allow filtering on all zoom levels.</p>
<p>It is a lot of fun to zip around the map and look at far away places and how they are mapped. <a href="https://spyglass.jochentopf.com/">Try it out!</a>. And if you have any problems or ideas, open an issue on <a href="https://codeberg.org/jot/osm-spyglass">Codeberg</a>.</p>openstreetmapspyglassAquileo | More taginfo newshttps://blog.jochentopf.com/2025-01-08-more-taginfo-news.html
https://blog.jochentopf.com/2025-01-08-more-taginfo-news.htmlWed, 08 Jan 2025 12:55:21 +0100<p>Once a year or so I set aside some time to work on taginfo. Then I start working on it and find more and more things that I want to work on and invariably it takes longer than planned. And there is always much more to do that I don’t get to. But I did get some interesting things done this time around…</p> <h2>Tag status</h2> <p><span class="caps">OSM</span> wiki pages about keys and tags show a <a href="https://wiki.openstreetmap.org/wiki/Tag_status">Tag status</a> for many tags. The status is somewhat fuzzy, which one of the about 10 common values a tag should have is not always so clear, and sometimes wiki pages for different languages show different values. But thanks to a lot of work from a lot of people the state of the wiki documentation has improved a lot over the years and this information is now better maintained and quite useful.</p> <p><a href="https://taginfo.openstreetmap.org/sources/wiki/tag_status#overview" target="_blank"><img src="https://blog.jochentopf.com/img/2025-01-08-tag-status-stats.png" style="max-width: 36em; margin: 10px 0; border: 1px solid #a0a0a0;"></a> <p>Taginfo has always parsed out this status information from the wiki pages but not done anything with it. But now it does. On key pages the Overview tab now shows a “Status” box which shows the status from the wiki, or it might tell you that the status is unknown or ambiguous (if there is a disagreement between different language wiki pages). I created a new “look” for the status badge which uses the same colors as the wiki for some of the status values.</p> <p>There are probably more places where we want to show that status, not only on the “key” pages, but also the “tag” pages and some others. But I’ll leave that for some later time.</p> <p>You can also get an overview about all the keys and tags and their status on the <a href="https://taginfo.openstreetmap.org/sources/wiki/tag_status">Tag status</a> page on taginfo. This shows statistics about all the status values, lists of keys and tags, and also special tables showing which keys and tags have inconsistent status values in different languages.</p> <h2>Data from wiki</h2> <p>Which brings me to the next topic: There is a lot of information in the wiki. Taginfo can’t known what information is correct or not, but it can flag some problems with the data, inconsistencies it finds, or, for instance, all the images used to document keys and tags that are quite large and so need a long time to load.</p> <p>The <a href="https://taginfo.openstreetmap.org/sources/wiki">Wiki source</a> section on taginfo now collects a lot of such information to help wiki maintainers with their job. Some of what’s shown there is new, some has been available in reports or taginfo-internal pages before. I hope this will be useful for somebody.</p> <h2>Discardable tags</h2> <p>There is one somewhat special tag status called <a href="https://wiki.openstreetmap.org/wiki/Discardable_tags">“discardable”</a>. Tags with this status have been found not to be useful and some editors remove these tags automatically and silently when <span class="caps">OSM</span> objects are edited. That way the data will sooner or later be removed from <span class="caps">OSM</span> without any huge automated edit.</p> <p>Taginfo now <a href="https://taginfo.openstreetmap.org/sources/sw">reads the configuration</a> from the iD and <span class="caps">JOSM</span> editors to find out which tags they think of as discardable as well as the tag status information from the wiki. A <a href="https://taginfo.openstreetmap.org/reports/discardable_tags">new report</a> shows this information which could be especially useful for editor developers and wiki maintainers.</p> <p>And in the mentioned “Status” box on the key pages, this information will also be highlighted.</p> <a href="https://taginfo.openstreetmap.org/keys/geobase%3Auuid" target="_blank"><img src="https://blog.jochentopf.com/img/2025-01-08-discardable-tags.png" style="max-width: 36em; margin: 10px 0; border: 1px solid #a0a0a0;"/></a> <h2><span class="caps">CSV</span> export</h2> <p>Most tables shown on taginfo have a “<span class="caps">JSON</span>” button in the header which links to a <span class="caps">URL</span> for downloading the data shown in the table. You don’t have to read the <span class="caps">API</span> docs, just use that link, maybe change the parameters a bit and get to the data that’s in that table.</p> <img src="https://blog.jochentopf.com/img/2025-01-08-csv.png" style="max-width: 36em; margin: 10px 0; border: 1px solid #a0a0a0;"/> <p>Using <span class="caps">JSON</span> is great for many use cases, but in some cases it is still somewhat cumbersome. A user had asked for <span class="caps">CSV</span> export, so I implemented that also. Most tables now also have a “<span class="caps">CSV</span>” button. So it is really easy to, say export some data to <span class="caps">CSV</span>, load it into LibreOffice and create some chart.</p> <h2>Keyboard shortcuts</h2> <p>There probably aren’t many people using the keyboard shortcuts that taginfo provides. But they can be quite useful for experienced users. But who can remember them all?</p> <img src="https://blog.jochentopf.com/img/2025-01-08-keyboard-shortcuts.png" style="max-width: 36em; margin: 10px 0; border: 1px solid #a0a0a0;"/> <p>There is now a new feature: You can press and hold the question mark (?) key on any page and taginfo will show you which shortcuts there are and what links on that page they are a shortcut for. Not the most important thing, but it was fun to work on that, fiddle around and see how to best do that.</p></p>openstreetmaptaginfoAquileo | Taginfo gets a new layouthttps://blog.jochentopf.com/2024-12-09-taginfo-gets-a-new-layout.html
https://blog.jochentopf.com/2024-12-09-taginfo-gets-a-new-layout.htmlMon, 09 Dec 2024 17:58:02 +0100<p>Some of the most often seen pages on taginfo are the pages describing a key. To be more specific, the “Overview” tab on that page. And it has never really looked that great. The layout is strange and a lot of prime screen real estate is wasted.</p> <p><a href="https://blog.jochentopf.com/img/2024-12-09-taginfo-key.png"><img src="https://blog.jochentopf.com/img/2024-12-09-taginfo-key.png" style="max-width: 36em; margin: 10px 0; border: 1px solid #a0a0a0;"/></a> <p>And to make matters worse, the layout totally breaks on small screens:</p> <a href="https://blog.jochentopf.com/img/2024-12-09-taginfo-key.png"><img src="https://blog.jochentopf.com/img/2024-12-09-taginfo-small-screen.png" style="max-width: 18em; margin: 10px 8em; border: 1px solid #a0a0a0;"/></a> <p>So it was high time we did something about it. The new design is built around fixed size boxes containing different information about that key, as you can see here:</p> <a href="https://blog.jochentopf.com/img/2024-12-09-taginfo-new.png"><img src="https://blog.jochentopf.com/img/2024-12-09-taginfo-new.png" style="max-width: 36em; margin: 10px 0; border: 1px solid #a0a0a0;"/></a> <p>The boxes will wrap as needed, so the whole thing is still reasonably pretty on small screens:</p> <a href="https://blog.jochentopf.com/img/2024-12-09-taginfo-small-screen-new.png"><img src="https://blog.jochentopf.com/img/2024-12-09-taginfo-small-screen-new.png" style="max-width: 16em; margin: 10px 10em; border: 1px solid #a0a0a0;"/></a> <p>To fit the values distribution chart into a box, it had to change. It uses a 3D layout now which shows a lot more information. I threw in a small version of the chronology chart and instead of just showing the image from the wiki, a list of wiki pages is shown that link directly to those pages. So there is a lot more information right there on the overview page.</p> <p>Oh, and all of this goes for the tag pages and the relation type pages, too. They have also been updated with the new layout.</p> <p>An added benefit of those boxes is that we can have more or less of them as needed. For instance when there is no wiki page about a key, the wiki box will not show up. For some tags (like <tt>website</tt> or <tt>wikidata</tt>) an extra box will be shown with links. I am already thinking about more boxes to add, but this will come at another time.</p> <p>The new layout is now online, try it out at <a href="https://taginfo.openstreetmap.org/">taginfo.openstreetmap.org</a>.</p></p>openstreetmaptaginfoAquileo | Introducing OSM XRAYhttps://blog.jochentopf.com/2024-09-30-introducing-osm-xray.html
https://blog.jochentopf.com/2024-09-30-introducing-osm-xray.htmlMon, 30 Sep 2024 23:17:11 +0200<p>This blog post is about the new <span class="caps">OSM</span> <span class="caps">XRAY</span> service. [Update April 2026: This service has since been renamed to Spyglass]. You can find a demo <a href="https://spyglass.jochentopf.com/">here</a>. It uses vector tiles with all <span class="caps">OSM</span> data to really show <b>all</b> of <span class="caps">OSM</span>, mostly for debugging. But it is also interesting to just explore what’s there.</p>
<h2>Vector Tiles with <span class="caps">ALL</span> Data</h2>
<p>Every time there is talk about vector tiles of OpenStreetMap data the question arises whether we can have vector tiles with “all of <span class="caps">OSM</span>”. Not just data with this or that tag suitable for rendering this or that type of map but everything. All of it. All objects from the <span class="caps">OSM</span> database.</p>
<p>It is possible to do that. Nine years ago Mapbox/<span class="caps">HOT</span> already did that with something called <a href="https://osmlab.github.io/osm-qa-tiles/">QA tiles</a>. The project is long defunct though. And we have a lot more data by now. More recently Wat Mildon published his <a href="https://watmildon.github.io/TIGERMap/WAMap/">WAMap</a> (See also <a href="https://community.openstreetmap.org/t/demo-full-data-vector-tile-map-with-basic-filtering-for-qa/111351">this thread on community.openstreetmap.org</a>) which also shows that this is totally possible.</p>
<p>So it is possible. And it turns out it is actually not that complicated. But is it useful?</p>
<p>There are two problems with vector tiles containing “everything”:</p>
<ol> <li>“Everything from <span class="caps">OSM</span>” is quite a lot of data. Vector tiles work best if they are at most a few kilobytes each. If you include everything in <span class="caps">OSM</span>, vector tiles will often need a few megabytes. This data takes longer to transmit and the browser will struggle to render it. Everything will become sluggish.</li> <li>Rendering <span class="caps">OSM</span> data into a usable map is difficult. You need to take many tags and tag combinations into account, handle bad data and handle <span class="caps">OSM</span> specialties like ways that can be lines or polygons or complex relations. And you need to do that with a rendering configuration that is rather limited and hard to use, like the styling language of Maplibre.</li> </ol>
<p>These problems become much more pronounced for smaller zoom levels. It might be slow, but on zoom level 14 you can download and show everything. But on zoom level 0 you would have to download the whole planet file with more than 70GB and process that in the browser just to show the outlines of the continents. Not really feasible.</p>
<p>The solution for all these problems is usually to preprocess the data on the server, decide which parts you need on which zoom level and convert the data into a format that the renderer can work with more easily.</p>
<h2>Use Cases</h2>
<p>Okay, so most use cases don’t need the “full <span class="caps">OSM</span> data” in vector tiles and they are better of doing things differently. But maybe there are use case which do need it. I can think of two: One is for experimentation. Sometimes you want to create a map but don’t know yet what <span class="caps">OSM</span> data there is and how best to transform it into something more useful and faster to render. Having all data available might make the map slow to be created, but it is still possible. So you can show the data, tweak the display and when you are done and know what you want, go back to the server, convert the data there and then have a fast map. This is a definite use case and I have used this approach many times, but usually using <span class="caps">QGIS</span> and not vector tiles. It is much easier to play around with a <span class="caps">GUI</span> tool.</p>
<p>The other use case I can think of is as a debug view. Similiar to what the “Map Data” button on openstreetmap.org does. Or similar to what you see in an <span class="caps">OSM</span> editor where you can click on everything and see the tags etc. In fact the existence of <span class="caps">OSM</span> editors in the browser shows that this is totally feasible and does make sense.</p>
<p>Now having said all of this, the question of what <strong>would</strong> be possible is still open. How far can we go?</p>
<h2>How to do it?</h2>
<p>Just creating vector tiles with everything in them is pretty easy. Use the flex output of osm2pgsql to create a database with all <span class="caps">OSM</span> objects having a “tags” <span class="caps">JSONB</span> column that contains all the tags and we are already half there. Using osm2pgsql gives me something extra that nobody has done yet with “full” vector tiles: The database can be updated continuously from minutely diffs, so we can show a map that always shows all current <span class="caps">OSM</span> data.</p>
<p>From the data in the database we need to create the vector tiles and we need to do it fast. There are several vector tile servers that can do that. For this project I am using pg_tileserv, because it will automatically convert all the data from the <span class="caps">JSONB</span> tags column into vector tile attributes and is pretty easy and flexibly configured using PostgreSQL functions. Creating vector tiles on something like zoom level 12 or 14 is very straightforward that way. In a densly mapped urban area the browser might take a while to download and render that tile, but it does work.</p>
<p>Of course if you want to do complex rendering this will become more and more expensive with every rendering rule you have. But for a debug site a wire-frame view is enough. So we only need a few rules for rendering black dots and lines.</p>
<p>For smaller zoom levels this isn’t a solution though. We need to somehow reduce the amount of data. I played around with several approaches for a while, simplifying the geometries. But sooner or later this approach breaks down. So I reverted back to “ye olde raster tile” approach for smaller zoom levels. I could have gone with a renderer like Mapnik, but just for the fun of it I decided to try the raster capabilities of the PostGIS extension. Turns out you can render vectors into raster tiles completely inside the database and after some experimentation I got it to be reasonably performant, too. There aren’t many styling options, though, so this approach will not work for most use cases. But in my case I am interested only in, as I said, drawing some black dots and lines, and PostGIS can do that.</p>
<p>Okay, I have the outline of a solution here. Vector tiles for zoom level 14 and above, raster tiles for zoom levels 0 to 13.</p>
<h2>Caching and Prerendering</h2>
<p>For the higher zoom levels the database query is actually quite performant. And because this service is not intended for massive use, just as a debugging tool for a few mappers, we could probably get by without any kind of caching. But just for the fun of it I added some caching inside the database. For a high traffic site I would not consider this, the overhead for caching inside PostgreSQL compared to about any other solution must be quite large. And the database is the bottleneck for the whole operation, so we should not add any load to it. But I realized I could add caching inside the database without any additional software component, just using the abilities of pg_tileserv and osm2pgsql for caching and expiry, so I wanted to try it. And at least I created the <tt>tile_cache</tt> table as <tt>UNLOGGED</tt> to reduce the overhead somewhat. We’ll see how that goes.</p>
<p>The smaller the zoom levels gets, the more data needs to be processed for each tile. And that takes time. So from zoom level 10 down I pre-render all tiles. Some tiles are rendered from the data and for the smallest zoom levels they are just resized bitmaps of the middle zoom levels. Currently these are rendered once on import and never rerendered, but it should be possible to do that once a week or so. It takes a few hours to do this.</p>
<p>Creating all of this took a few hours here and there on a few weekends. But I needed more, I needed some way to show all of this in a browser.</p>
<h2>The Application</h2>
<p>Actually creating the tiles was easy compared to figuring out how to show the data and how to interact with it. I wanted a fast and easy to use tool that allows exploring the <span class="caps">OSM</span> data. It took me quit a while and many experiments to get the interface to where it is now. How do you show tags? How do you handle selecting objects? What if there are multiple objects under the mouse cursor? How do you show relations? All at once or one member at a time?</p>
<p>The solution I came up with is certainly not perfect, I am sure we’ll improve it over time. There are some clear limitations, for instance selections only work in zoom level 14 and above. But it is already fun to explore <span class="caps">OSM</span> that way. So I am happy to release it in the state it is in. I am excited to see what improvements we’ll come up with over time.</p>
<p>Also it turns out that there is so much <span class="caps">OSM</span> data that it is sometimes difficult to navigate this map full of black dots and lines that cover the background map shown for reference. So I added an overlay of <span class="caps">OSM</span> boundaries. This was straightforward to do because <span class="caps">XRAY</span> uses the <a href="https://osm2pgsql.org/themepark/">osm2pgsql Themepark framework</a> which makes it easy to mix in layers from different configurations, in this case I am using the boundaries layer from the Shortbread configuration.</p>
<h2>What’s next?</h2>
<p>Currently this is only running as a test/demo on the osm2pgsql test machine sponsored by <span class="caps">FOSSGIS</span>. It can’t stay there forever because we need that maschine for testing new osm2pgsql versions etc. We’ll see where we can find a permanent host for this.</p>
<p>There are plenty of things that need improving. For some of them I have already opened issues in the <a href="https://github.com/joto/osm-xray"><span class="caps">OSM</span> <span class="caps">XRAY</span> repository</a> and I am sure you’ll come up with more ideas and find some bugs. The two most important issues in my mind are the question of how to handle selected objects in low zoom levels and how to handle filtering in low zoom levels. I am open to ideas.</p>openstreetmaposm-xrayosm2pgsqlspyglassAquileo | Out of memoryhttps://blog.jochentopf.com/2024-08-15-out-of-memory.html
https://blog.jochentopf.com/2024-08-15-out-of-memory.htmlThu, 15 Aug 2024 13:19:57 +0200<p>I have to import a lot of <span class="caps">OSM</span> planet files to test things due to my work on osm2pgsql. I have a test machine for that graciously provided by <a href="https://fossgis.de/"><span class="caps">FOSSGIS</span> e.V.</a>, the <span class="caps">OSM</span> Foundation local chapter for Germany. A few days ago I imported a planet file and osm2pgsql ran out of memory.</p> <p>I was doing a non-slim import, which means that all node locations and all way nodes are stored in memory. Until recently this worked okay, but it seems the planet has grown beyond what fits into the 128 GB <span class="caps">RAM</span> that this machine has. This does not come as a big surprise, it was going to happen sooner or later — I wrote about this issue in my 2022 paper on the “Evolution of the <span class="caps">OSM</span> Data Model” <a href="https://media.jochentopf.com/media/2022-08-15-study-evolution-of-the-osm-data-model.pdf">(<span class="caps">PDF</span>)</a>.</p> <p>I don’t have a bigger machine and I am not going to get one anytime soon. And other people are probably in the same position, so I added support for the <tt>-F/--flat-nodes</tt> option in non-slim mode to osm2pgsql. This means we can move nearly 100 GB worth of data into a file on disk instead of having it in memory. The <a href="https://github.com/osm2pgsql-dev/osm2pgsql/pull/2221">PR</a> was just merged. (You still need lots of memory, though, because without enough memory for caching, processing will become painfully slow anway.)</p>openstreetmaposm2pgsqlAquileo | Minutely updated maphttps://blog.jochentopf.com/2023-09-25-minutely-updated-map.html
https://blog.jochentopf.com/2023-09-25-minutely-updated-map.htmlMon, 25 Sep 2023 12:39:04 +0200<p>Most OpenStreetMap-based maps you see these days on the Internet are only updated every so often. Some may be updated daily, most are probably only updated every few weeks or months. And that is totally okay for most use cases. But there are some maps that are updated continuously so that changes in the <span class="caps">OSM</span> data appear as fast as possible, which is important to motivate <span class="caps">OSM</span> contributors and helps with quickly detecting and fixing problems. The most important map with continuous updates is the main map you see on <a href="https://www.openstreetmap.org/">www.openstreetmap.org</a>.</p> <h2>Minutely Diffs</h2> <p>To enable everybody to keep up with changes in <span class="caps">OSM</span> data, the <span class="caps">OSMF</span> publishes <a href="https://wiki.openstreetmap.org/wiki/Planet.osm/diffs">minutely diffs</a>, i.e. files containing the <span class="caps">OSM</span> updates for a single minute. There are several challenges when keeping a map up to date from those diffs. The first is that the diffs don’t contain enough information. Only the immediate object that changed is in the diff, but not other objects that also need data from the changed object to draw them correctly. This means that you need a database with all the <span class="caps">OSM</span> data for the whole planet locally available to correctly interpret the diffs and update the map.</p> <p>I am working with osm2pgsql which has solved this problem a long time ago and <a href="https://blog.jochentopf.com/2023-07-25-improving-the-middle-of-osm2pgsql.html">recently got some improvements on that front</a>.</p> <h2>Data Conversion and Cleanup</h2> <p>The second problem is that even if you have an up-to-date <span class="caps">OSM</span> database available, you still need to draw the map from that data. And the <span class="caps">OSM</span> data format isn’t a good fit for that job. You can directly draw a map from <span class="caps">OSM</span> data (the <span class="caps">JOSM</span> editor does this for instance), but usually you want other data formats in between (such as PostgreSQL/PostGIS tables or vector tiles). <p>Osm2pgsql was invented years ago to solve this problem by doing conversions from <span class="caps">OSM</span> data into database tables with geometries which can be rendered into maps directly by many tools out there. With the <a href="https://osm2pgsql.org/doc/manual.html#the-flex-output">flex output</a> I have been working on for several years now, this conversion has become much more powerful, so that we are getting better and better at converting the data into formats that are easier to work with on the rendering side. In this step we can also clean up the data which makes it considerably easier to work with when rendering.</p> <h2>Generalization</h2> <p>The third problem is the problem of generalization. The conversions described above usually only work on one <span class="caps">OSM</span> object at a time (or a few like a way and its node members). That works well enough for large zoom levels where you want to render features on the same level of detail as they are modelled in the <span class="caps">OSM</span> database. But for smaller zoom levels you need to accumulate hundreds, sometimes tens of thousands of <span class="caps">OSM</span> objects into something larger to show on the map. You can, sort of, do without generalization, but that means rendering can become very slow. Which makes the continuously updated map not updating so quickly any more.</p> <p>I have been working on that problem in the <a href="https://osm2pgsql.org/generalization/">generalization project</a>, adding code to osm2pgsql to quickly calculate generalized data from the <span class="caps">OSM</span> data already in the database when something changes and write the data back into the database.</p> <h2>Technology Demo</h2> <p>To tie all of this together and to show what we can do today (and what we can’t do yet) I have created [this technology demo] (Update: not available any more). The map on that page is updated continuously from <span class="caps">OSM</span> data using the minutely diffs. For most data this includes updates of all the lower zoom levels. The only exception are the roads on lower zoom levels which are only updated every once in a while, because I haven’t yet figured out a way to do this really quickly. And the ocean data is also only updated once daily from <a href="https://osmdata.openstreetmap.de/">osmdata.openstreetmap.de</a>.</p> <p>Tiles are rendered on the fly from the PostgreSQL/PostGIS database. There is no caching involved, each tile is created for each request. Of course this is not something fit for a production map where some caching will be needed, but I didn’t do it for this map on purpose to demonstrate how fast this setup still is at producing those tiles.</p> <p>The tiles use the <a href="https://shortbread-tiles.org">Shortbread</a> tiles format. It is a somewhat simple format, especially compared to the wealth of detail you see on the <span class="caps">OSM</span> Carto map on openstreetmap.org, but it shows the most important stuff and we have to start somewhere.</p> <h2>Want to try this yourself?</h2> <p>My setup runs on a 8 core (16 with HT) machine with 128 GB <span class="caps">RAM</span> and the database needs about 800 GB plus about 80 GB for the flat node file. Setup takes about 20 hours including the initial import, initial calculation of generalized data and then catchup with the changes that happened in <span class="caps">OSM</span> in the mean time.</p> <p>You’ll need <a href="https://github.com/osm2pgsql-dev/osm2pgsql">osm2pgsql</a> and <a href="https://github.com/osm2pgsql-dev/osm2pgsql-themepark">osm2pgsql-themepark</a>, use the current master. I am using the T-Rex tileserver in my current setup and the osm2pgsql-themepark framework will generate a configuration for that, but you can also use a different tileserver. (In fact development on T-Rex has stopped, so you might want to look into alternatives.)</p> <h2>What’s next?</h2> <p>This map is only a prototype. There is more work to be done to turn this into something that could be used for real. To make this operational the whole stack including web server, tile server, and caching has to be set up properly. Because I am not caching tiles, I didn’t have to set up cache expiry either.</p> <p>The generalization code we have now is already working quite well for lots of layers, but it is kind of simplistic. And it has to become faster and more robust and needs to be extended to other feature types. It currently takes about a minute to re-generate all the data for the smaller zoom levels, that’s kind of tight for something that should update every minute. And, as mentioned, the road layers can only be updated less often. (They currently need about 15 or 20 minutes to update for the whole planet.)</p> <p>Over a decade ago <span class="caps">OSM</span> was the first map out there that not only everybody could change, but that also would show those changes for everybody to see in minutes. But we have become stuck at that point. Changes in higher zoom levels are shown quickly, but in lower zoom levels it takes more time. And, arguably, we have also been moving backwards, because typical vector tile maps don’t support minutely updates. With this demo and blog post I hope to get some more people interested in this work so that together we can make a better, continously updated, always current <span class="caps">OSM</span> map. My focus will be to keep working on the building blocks in osm2pgsql to make this possible.</p>openstreetmaposm2pgsqlAquileo | Improving the middle of osm2pgsqlhttps://blog.jochentopf.com/2023-07-25-improving-the-middle-of-osm2pgsql.html
https://blog.jochentopf.com/2023-07-25-improving-the-middle-of-osm2pgsql.htmlTue, 25 Jul 2023 16:46:57 +0200<p>In <a href="https://osm2pgsql.org/">osm2pgsql</a> there is that code that stores the raw data it gets from the input files and makes it available to other parts of osm2pgsql for further processing. This code is called, in osm2pgsql-speak, the “middle”. There are two implementations of this “middle”, one stores the data in <span class="caps">RAM</span> and doesn’t support updates. The other stores the data in the database and supports updates. <a href="https://blog.jochentopf.com/2020-12-21-osm2pgsql-middle-improvements.html">Back in 2020 I started looking into that code</a> to see what could be improved. In 2021 we <a href="https://osm2pgsql.org/news/2021/06/02/release-1.5.0.html">released version 1.5.0</a> which contained a basically rewritten <span class="caps">RAM</span> middle. And now, in 2023, I finally got around to improving the database middle.</p> <p>There were several things in the old database middle which weren’t that great that we wanted to address.</p> <h2>Database table format</h2> <p>First, the format osm2pgsql uses in the database is rather strange. Tags are stored as an array with alternating keys and values, relation members are stored in an even stranger format. That’s done for historical reasons and it works well enough for osm2pgsql itself, but it made it rather awkward to access this data from <span class="caps">SQL</span>. With modern versions of PostgreSQL we have better options for storing this data, in both these cases we can use the <span class="caps">JSONB</span> type to efficiently store and access this data.</p> <p>This change reduces the database size by nearly 10% and only slows down the import by a few minutes for the whole planet.</p> <h2>Storing attributes</h2> <p>The old format stores <span class="caps">OSM</span> object attributes (timestamp, version, changeset, user id, and user name) as pseudo-tags in the same place the other tags are stored. This is not only rather inefficient, it also means we have to disentangle real and pseudo-tags when we read the data again.</p> <p>The new code simply stores the attributes in their own database columns. If an attribute isn’t there, a <span class="caps">NULL</span> is stored. The exception is the user name. Because the user id and user name duplicates information it is much more efficient to just store the user id with each <span class="caps">OSM</span> object and have an extra lookup table for the user names. This has the added benefit that when a user changes their user name, the lookup table will be updated the next time the user changes an object, this way the data is always consistent.</p> <p>Because most users don’t need those attributes, the attribute storage is only enabled with a specific command line option. That did’t change.</p> <p>Storing the attributes used to make the database more than 50% larger. With these changes the added storage needed is negligable. Processing time has improved somewhat but is still much larger compared to processing time without attributes. (This is not because of anything in the “middle”, but because with attributes enabled osm2pgsql will send <i>all</i> nodes through the output processing, not just nodes with tags.)</p> <h2>Node tags</h2> <p>The old format never stored node tags in the database, because historically this was not needed for osm2pgsql. Way and relation tags need to be stored so that when a change in a node or way comes in, all parent ways and relations can also be updated. But because nodes are never the parent of another object the node tags are never needed.</p> <p>But we want to do more complex processing today. For a while now we have the so-called two-stage processing which allows special processing of relation members. But that only works for way members and not for node members, because we were missing those node tags.</p> <p>The new code can now store the node tags, too. You have to ask for this using a command line option, because not everybody will need this and storage costs quite a bit of disk space (as I write this about 30GB plus 5GB index for the whole planet). With the new format you can now access this data from <span class="caps">SQL</span>. The code to tie this in with two-stage processing isn’t written yet though, more work to do…</p> <h2>Performance</h2> <p>There were several problems with the way osm2pgsql was processing the data and accessing the database which were fixed in this effort. Some of these we have known about for a long time, other issues only were diagnosed now that we were looking into all the details.</p> <ul>
<li>For each changed node or changed way, osm2pgsql asks the database for all ways and relations the changed objects are in. The new code asks only once for all nodes and once for all ways. This change alone can mean a 10x speed increase!</li>
<li>We used to process some ways and relations twice if a member node or way changed and also the object itself changed. That’s just wasteful. Saves about 10% processing time to not do this.</li>
<li>When deleting objects, the database would in some cases not realize that it should use an existing index to figure out what to delete. So it used a full table scan which turns an operation that should basically take no time at all into one that can take 10 seconds or more. And we have many of those queries. Simply forcing the database to use the index fixes this.</li>
<li>For each object read from a change file we have to delete a possibly existing earlier version of that object from the database. But many objects are brand new so they can’t possibly exist in the database. So we now get the maximum node, way, and relation ids that exist in the database and check all incoming objects against those. For every object with larger than the known max id, we omit the delete, which gets us a slight performance boost.</li>
<p></ul> <p>There are more places where performance can probably be improved, but it needs a lot of testing with different scenarios to figure out which change actually improves performance and which makes it worse. Quite often the database (or more often the complex interaction between database and osm2pgsql) behaves differently than what the user (or developer) would expect. It needs a lot of time to figure out exactly what’s happening and why and how the different pieces interact.</p> <p>Our test server (graciously sponsored by <a href="https://www.fossgis.de/"><span class="caps">FOSSGIS</span> e.V.</a>) spent many days and weeks doing planet imports and updates in different configurations to help figure out what works and what doesn’t.</p> <h2>The Properties table</h2> <p>There is another “piece of infrastructure” that we recently added. The <tt>osm2pgsql_properties</tt> table stores some information about how osm2pgsql was called and about the input data. This means that when you are running updates (with <tt>osm2pgsql --append</tt>) osm2pgsql already knows some of the settings it needs and you don’t have to specify them on the command line any more.</p> <p>This feature comes in handy now that we have the old “legacy” database format and the shiny “new” database format. For some time osm2pgsql needs to support both formats so that users can move over when it is convenient for them to do a re-import. The format is stored in that properties table so that it is automatically used for updates.</p> <h2>So what have we gained?</h2> <p>For the first time we now have a <a href="https://osm2pgsql.org/doc/manual.html#database-structure">documented database format</a> so that users can “officially” use it instead of treating it as some internal thing that nobody is allowed to touch. This allows more specialized processing of <span class="caps">OSM</span> data involving several related objects, for instance barriers on roads or something like that.</p> <p>For the first time it is now possible to easily store <b>all</b> <span class="caps">OSM</span> data with all tags and all attributes in a database using osm2pgsql. This opens up new use case for users who don’t just want a rendering database but do statistics or special analytics on raw <span class="caps">OSM</span> data. Before now you had to use Osmosis (or some other specialized tools) to do these things, now you can use osm2pgsql (and get all the other features of osm2pgsql at the same time).</p> <p>While the new database format takes slightly more processing time than the old format this is more than made up with the performance improvements we have done. Users running minutely updates will probably only see slight improvements if at all, but if you import a larger update, processing time might only be a tenth of what is was before.</p> <h2>Status</h2> <p>All this great new stuff is available in the “master” branch at the moment, but we’ll do a release soon. The new database format is still marked as experimental, because we want to have the option to change the format if user testing should reveal some bigger flaw. You need to activate it using a command line option. See the <a href="https://osm2pgsql.org/doc/manual.html#middle">Documentation</a> for all the details. In further releases we’ll finalize the format and sooner or later make it the default.</p> <p>Many thanks to <a href="https://www.thunderforest.com/">Thunderforest</a> and <a href="https://www.geofabrik.de/">Geofabrik</a> for supporting this work!</p></p>openstreetmaposm2pgsqlAquileo | Linking to external tools from taginfohttps://blog.jochentopf.com/2023-07-15-linking-to-external-tools-from-taginfo.html
https://blog.jochentopf.com/2023-07-15-linking-to-external-tools-from-taginfo.htmlSat, 15 Jul 2023 19:43:25 +0200<p><a href="https://taginfo.openstreetmap.org/">Taginfo</a> has as its goal to find and collect all useful knowledge about <span class="caps">OSM</span> tags and make it accessible. But taginfo can’t do everything. That’s why it has always linked to tools that “do something with <span class="caps">OSM</span> tags”, the most popular one is probably Overpass Turbo.</p> <p>Taginfo does have maps showing an overview of where certains tags are used, but the maps are static and not available for all tags. The link to Overpass gives you more option of exploring the actual <span class="caps">OSM</span> data on a map (and much more).</p> <p>Similarly taginfo can show you in a graph how often a key or tag was used over time. But you can only see this graph for a single key or tag and all it does is count the uses. But there are tools out there that can do more. In the last weeks I have integrated links to two such tools to taginfo: Martin Raifer’s <a href="https://taghistory.raifer.tech/"><span class="caps">OSM</span> Tag history</a> tool and the <a href="https://dashboard.ohsome.org/">ohsome dashboard</a> from HeiGIT. Both allow you do explore the <span class="caps">OSM</span> tag history, but in different ways.</p> <p><a target="_blank" href="https://taginfo.openstreetmap.org/tags/tourism=attraction"><img
src="https://blog.jochentopf.com/img/2023-07-15-taginfo-tools.png" width="430"/></a><br />
<p>To use these tools look for the tool buttons on the top right of all key, tag, and relation pages. The filter setting right above the tool buttons will affect those link (except on the relation pages where a filter on relations is always used).</p> <p>The <span class="caps">OSM</span> Tag history tool is also available from the comparison page (<a href="https://taginfo.openstreetmap.org/compare/amenity=restaurant/amenity=fast_food">example</a>). In this case it shows the curves for all compared keys and tags on a single graph making it easy to see the differences and similarities.</p> <p>Do you know of any other tools that can (generically) handle <span class="caps">OSM</span> tags, keys, and/or relation types and that might be useful to integrate into taginfo? Open an issue on the <a href="https://github.com/taginfo/taginfo/issues">taginfo issue tracker!</a></p></p>openstreetmaptaginfoAquileo | Modernizing taginfohttps://blog.jochentopf.com/2023-04-22-modernizing-taginfo.html
https://blog.jochentopf.com/2023-04-22-modernizing-taginfo.htmlSat, 22 Apr 2023 18:07:54 +0200<p>About once a year I set aside a week to work on <a href="https://taginfo.openstreetmap.org/">taginfo</a>, one of my many projects that doesn’t get enough attention. And inevitably once I get started there are so many things I want to do that it takes two weeks instead of the originally allotted week. So this time I thought I plan with the two weeks from the start. You probably know where this goes: I spend more like three or four weeks on taginfo…</p> <p>This time I worked on something I wanted to do for a long time: Modernize the Javascript and <span class="caps">CSS</span>. The web technologies <span class="caps">HTML</span>, <span class="caps">CSS</span>, and Javascript have matured quite a lot in the last decade. Browsers are pretty good at keeping backwards compatibility and the old code still worked, but it was showing its age and newer and better solutions for many problems are available today.</p> <p>Back in 2010 when I started taginfo, jQuery was a popular library. It still exists today but browsers have gained so much native functionality that it isn’t as important. And most of the jQuery plugins I was using have not been updated in years, some you can’t even find on the Internet any more. So I decided to get rid of jQuery and most external Javascript libraries altogether and write the code I need myself.</p> <p>The taginfo site doesn’t have much Javascript on it. The most complex piece is the code for the dynamic tables you see on many pages. They were generated by an unmaintained jQuery plugin called Flexigrid in which I have fixed some bugs and changed some things here or there. I looked around for a Javascript library that could give me the same functionality in more modern code, but couldn’t find anything not tied to some complex framework. So I decided to write that myself. This has the added advantage that I can write exactly the functionality I want and don’t have to add some external warts to some existing Javascript library. The tables get their content through asynchronous <span class="caps">API</span> calls, support sorting by different columns, filter queries, paging (with buttons or the keyboard, or — new — with the mouse wheel (press Shift to use that)) and resizing of columns.</p> <p> The rest of the Javascript is mostly pretty simple. The “tab” functionality, autocomplete for the search, some mouse and keyboard interaction. A lot of the code is simple formatting of key and tag links, numbers and so on which was already there and basically unchanged.</p> <p>The only external library I am still using is <a href="https://d3js.org/">D3</a> for the tag cloud on the home page and the charts and graphs. That library is pretty stable and it does some clever and useful stuff. And it doesn’t have any dependencies on jQuery or anything else.</p> <p>You might wonder why I am not using some kind of modern Javascript framework. The reason is simple: They are changing too fast. Taginfo has been around for a long time and I expect it to be around for a long time. But, as mentioned, I can only work on it for small amounts of time here or there. So it is important it keeps working without any intervention and that, when I find the time to work on it, I can actually work on it and not spend my time updating to the newest framework version or getting NodeJS updated so that the build system works before I can do this one little change. Most of the Javascript I am writing is in one file, the same with the <span class="caps">CSS</span>. I don’t build the <span class="caps">CSS</span> or use Typescript or something like that. I have to do some things myself that a framework could solve for me, but taginfo isn’t so complex that this isn’t possible.</p> <p>So, after all that work, what do I have to show for it? Most people will not even notice the changes. The site looks and feels more or less the same as before. That’s intentional. I have ideas for more changes, but they have to wait for the next time. But the big changes under the hood make the site already work better on smaller screens. Many bug reports I get are about the site not working correctly on mobile phones. There is still a lot to be done in that regard, but because of the cleaner <span class="caps">CSS</span> and Javascript it is now much easier to work on that.</p> <p>Inevitably I broke some things in the process. Some issues I found myself, some were found by users. And more will probably be found in the next weeks or months. But I am pretty happy with the state the web site is in right now. Maybe the next time I work on taginfo I can work on the content side.</p>openstreetmaptaginfo