If you follow me (I know, you don't), you know I render my own maps. For that I use `mapnik`, a library that can take 
data and a style and generate the maps I want. I install `mapnik` using Debian sid's original packaging. Lately, I've 
been wondering if I can shave some time from its rendering time.

Debian binary packages are compiled from source (duh). Since there is a single binary package per CPU architecture, 
the compile options must be generic enough to run on all alternative CPUs in that arch. This means that they're 
optimized, but in the most generic way, nothing specialized to the CPU you actually have (unless you have the most 
generic one, which might not exist).

So the question is: can I get some more juice if I recompile at least `mapnik`, the lib that does most of the CPU 
crunching? Let's see.

But first, and this is the question that took me more time to answer: how do I personalize the flags using during 
compilation? You can donwload Debian source packages with `apt source mapnik` and the packages needed for compiling it 
with `sudo apt build-dep mapnik`. In particular, `mapnik` uses `cmake` and it's developed in C++, so what we're looking 
for is to provide options for `gcc` and/or `g++`. Luckily, `cmake` understands `CFLAGS` and `CXXFLAGS`, so now it's a 
matter of telling Debian's build system to set those.

Unluckily, it seems like `dpkg-buildpackage` ignores those. But that tool uses `dpkg-buildflags`, and that tool has 
several ways to modify those envvars. It has two sets of operations to modify the flags passed to, in this case, 
`cmake`. One set is for the package's maintainer, and the other can be used by a user like us to customize the 
compilation.

So, without further addo:

    DEB_CFLAGS_APPEND='-O3 -march=native -flto' DEB_CXXFLAGS_APPEND='-O3 -march=native -flto' dpkg-buildpackage --no-sign binary

This will build a new set of `.deb` files compiled with those flags. But it doesn't mean you can use them as is.

I mean, you _can_, but I would rather do this in a more clean manner. I would like a package that it's seen like an 
update to the one already provided by Debian, but that also looks like an older version to any update that might come
from Debian too (Debian sid is like a rolling release, and I update once a week). This can be achieved with version
suffixes[^1] by adding, for instance, `+0.1mdione` to the Debian version, and a new entry in the `debian/changelog`:

    mapnik (4.1.3+ds-2+0.1mdione) unstable; urgency=medium

      * Recompile with -O3 -march=native -flto

     -- Marcos Dione <mdione@grulic.org.ar>  Sun, 02 Nov 2025 11:55:22 +0200

More info at 
[Section 6.3 of the Guide for Debian Maintainers](https://www.debian.org/doc/manuals/debmake-doc/ch06.en.html#name-version).

And now, to test our optimizations. I decided to run a small batch, once for warm up, once to measure, then upgrade, 
then run it again. But I run (!!!) into trouble: the second run took _more_ time than the first one! In the end, I found 
a 16%+ swing between the slowest and the fastest runs (I run it several times more), way more than what any optimization of this 
kind might give. Still, I had no option than to continue, just in case.

And the winner is: no win. After several runs, I couldn't even get numbers as good as the fastest from the original 
version. So, at least in my case, Gentoo'ing it did not make any sense[^2].

[^1]: this is not an official name.

[^2]: OK, several caveats here: First, I didn't optimize the whole system. But in this case I'm not sure how much sense
      it would have made. I could optimize `postgres`[^4] (the data is mostly stored there) and the myriad of dependencies 
      for `mapnik`[^3], but that would take more time from me that what I evidently can (or, actually, can't) get out of it.
      Second, the system was not 100% idle, so maybe that explains the swings. Third, I had a third, but I forgot.

[^3]: 168 libraries, according to `ldd`, and I don't really know how many are used in the code paths I exercise.

[^4]: I'm going to end this post here, but I notice that at least for zoom level 11, `postgres` was using a core 100% for 
      ~2/3rds of the time it takes to render that single tile (3m+!), but afterwards its usage is lower, even when more cores
      (1 vs up to 8) are rendering at the same time.
