I also would have sworn up and down that using a DocumentFragment would be loads faster than both, but it doesn't seem to be the case. I wonder why that is.
Seems like Safari has quite naive element.append(...list) implementation and/or "destructuring to argv" operation is slow there.
I suspect that element.append(...list) is just a
for(auto arg : args)
element.append(arg);
so no transaction there at all - slower version of case #3.
On Windows I am testing it in Edge, Chrome and FF.
Edge and Chrome show close numbers (#1 fastest). FF shows #3 is faster - same problem as Safari I think.
But think about updates like this:
Here you need to update (or not) as the attribute as text nodes. You need some transactional mutation mechanism.