xml: rewrite the xml generator to avoid xml.Encoder
This commit intoduces a mostly hand-rolled XML encoder, inspired by xml.Encoder. Since plist is a simple format that doesn't require attributes, only has one data type with input in need of encoding, and is otherwise constrained, we don't need the full power of encoding/xml.
As a side effect, we can now elide the contents of empty elements
(<key></key>
-> <key/>
).
The speed, memory requirements and number of allocations are all improved.
Fixes https://github.com/DHowett/go-plist/issues/34.
name old time/op new time/op delta
XMLEncode-4 25.9µs ± 3% 14.9µs ± 1% -42.66%
BigXMLGenerate-4 47.3ms ± 1% 23.7ms ± 1% -49.91%
BigPrettyXMLGenerate-4 55.0ms ± 1% 30.0ms ± 1% -45.42%
XMLGenerate-4 16.0µs ± 1% 5.8µs ± 1% -63.81%
name old alloc/op new alloc/op delta
XMLEncode-4 8.71kB ± 0% 6.42kB ± 0% -26.26%
BigXMLGenerate-4 2.62MB ± 0% 1.60MB ± 0% -39.02%
BigPrettyXMLGenerate-4 2.62MB ± 0% 1.60MB ± 0% -39.02%
XMLGenerate-4 5.83kB ± 0% 4.50kB ± 0% -22.77%
name old allocs/op new allocs/op delta
XMLEncode-4 88.0 ± 0% 63.0 ± 0% -28.41%
BigXMLGenerate-4 86.7k ± 0% 72.6k ± 0% -16.24%
BigPrettyXMLGenerate-4 86.7k ± 0% 72.6k ± 0% -16.24%
XMLGenerate-4 54.0 ± 0% 31.0 ± 0% -42.59%