Right, I always played with fire spread disabled for this reason. What interval did you check for building attacks? The shorter it is, the more performance impact there is.
Right now the check for trees attacking buildings is implemented as checking random points all over the generated surface, which scales linearly with number of chunks and inversely with attack interval. It's tolerable when that interval is set to something like 5 minutes.
It can probably be done in some smart way where I cache which chunks have buildings placed down or something like that, but I didn't bother to do that yet, since current method is foolproof and good enough for non-megabases and reasonable settings. It's a TODO.
run_coro
and retaliation cost so much because of massive amounts of trees dying. Dunno how much can be done there. Maybe coroutines can be made a bit cheaper if I'm smarter about sleeping for N ticks.