mapnik/mapnik — pull request #2231 by springmeyer (2014-04-30 17:00:11+00:00)
Title: static grammars

## background

Boost spirit grammars can be very expensive to create and destroy. Its not uncommon for some of our grammars to take significantly longer to allocate or de-allocate than to actually be used to parse something. This was the reason that for changes like https://github.com/mapnik/mapnik/commit/19f5f7741752ea9d2d251b07d994aadeb60ea0ab and https://github.com/mapnik/mapnik/commit/bf3efbeab8ec7c162699a2b87dcd5513d6f84dd3#diff-c271f31945dc3e5a07de9dfe0ae5ccfd so that when parsing maps we only create the grammars once.

However there are several major drawbacks to this approach:

- All grammars are stored as members on a single class (`mapnik::xml_tree`) and therefore need to all be included in that compilation unit leading to massive memory demands for compiling `src/xml_tree.cpp` and `src/load_map.cpp`
- When fast parsing of small map documents is critical I've seen that the creation of every possible grammar once per `mapnik::load_map` is a significant bottleneck: for example just deallocating the `css_color_grammar` in one benchmark took 3.5% of the time while actual xml parsing took less than 0.1%. Combine that with the time it takes to both allocate and deallocate all grammars (`expressions_grammar`, `transform_expression_grammar`, `image_filter_grammar` and `path_expression_grammar`) and this becomes a serious bottleneck.

![screenshot 2014-04-29 22 29 01](https://cloud.githubusercontent.com/assets/20300/2844198/cefd9006-d087-11e3-93f5-3a00adb1f094.png)

This changes our spirit grammar usage internally:

- Significantly reduces compile times for any cpp including `mapnik/xml_tree.hpp` and reduces peak memory usage compiling `src/xml_tree.cpp`.
- Only construct grammars on first use enabling grammar re-use across multiple `mapnik::load_map`
- Needed to modify expression and transform grammars to not take args (otherwise segfaults occured trying to mark as `static`)
- simplifies interfaces in general and allows fast parsing from python without passing grammar instance