I feel so dirty after this ​​
/LH

onopentag(name, attribs) { // the "svg" tag is, of course, SVG if (name.length === 3) { const zero = name.charAt(0); if (zero === 's' || zero === 'S') { const one = name.charAt(1); if (one === 'v' || one === 'V') { const two = name.charAt(2); if (two === 'g' || two === 'G') { resolve(true); } } } }

@hazelnoot my eyes! the googles do nothing!

it looks like this could have been a job for regexp? Or would that be too great a performance hit?

@avatastic @hazelnoot you don't even need regex for this:

if (name.toLowerCase().startsWith('svg')) { resolve(true) }
I remember that back in the day we had an assignment and one of my classmates solution was literally an if statement for every possible input. The poor guy didn't even use macros to generate that file, he copy pasted and typed input and output by hand.
But it worked...

@interru that's actually not equivalent
@hazelnoot completely missed the length check. In that case name.toLowerCase() === 'svg'
@hazelnoot is regex not usable in this scenario?
@hazelnoot is there any reason to not just do name.toLowerCase() === "svg"?
@mitsunee it's on a very hot code path and I don't trust the JIT to handle it correctly

@hazelnoot @mitsunee I have profiled it for you :)

It's very rough-and-ready, badly written, and I haven't verified any of this lol

function a(name, attribs) { // the "svg" tag is, of course, SVG if (name.length === 3) { const zero = name.charAt(0); if (zero === 's' || zero === 'S') { const one = name.charAt(1); if (one === 'v' || one === 'V') { const two = name.charAt(2); if (two === 'g' || two === 'G') { resolve(true); } } } } } function b(name, attribs) { // the "svg" tag is, of course, SVG if (name.toLowerCase() === "svg") { resolve(true); } } // EDIT: This should have been /^svg$/i const svgRegex = /\bsvg\b/i; function c(name, attribs) { // the "svg" tag is, of course, SVG if (svgRegex.test(name)) { resolve(true); } } function resolve(success) {}function compare(fs, c) { console.log(`Profiling functions over ${c} iterations.`); for (const f of fs) { console.log(`\t${f.name}: ${testLoopTime(f, c)}`); } } function testLoopTime(f, c) { let startTime = performance.now(); testLoop(f, c); let endTime = performance.now(); return endTime - startTime; } function testLoop(f, c) { for (let i = 0; i < c; i++) { let str = ""; if (i % 2 === 0){ for (let j = 0; j < i; j++) { str += "a"; } } else { str = "svg"; } f(str); } }compare([a, b, c], 1000); compare([a, b, c], 10000); compare([a, b, c], 100000);
Results
Profiling functions over 1000 iterations. a: 4ms b: 8ms c: 5msProfiling functions over 10000 iterations. a: 218ms b: 423ms c: 413msProfiling functions over 100000 iterations. a: 15194ms b: 27711ms c: 27781ms
Tested in Firefox

@hazelnoot @mitsunee while running the last test my laptop makes a very peculiar sound indeed - a tiny high-pitched whining πŸ€”

@hazelnoot @mitsunee I found a faster and more compact version!

function d(name, attribs) { // the "svg" tag is, of course, SVG if (name.length === 3 && (name.charAt(0) === 's' || name.charAt(0) === 'S') && (name.charAt(1) === 'v' || name.charAt(1) === 'V') && (name.charAt(2) === 'g' || name.charAt(2) === 'G')) { resolve(true); } }
Firefox results
Profiling functions over 1000 iterations. a: 2 b: 5 c: 3 d: 4(The numbers for 1000 vary so wildly between 1 and 3, and sometimes 4-5, that they're not worth considering)
Profiling functions over 10000 iterations. a: 155 b: 249 c: 245 d: 126Profiling functions over 100000 iterations. a: 12921 b: 27898 c: 27576 d: 12584
Chromium results
Profiling functions over 1000 iterations. a: 1.799999998882413 b: 2.599999999627471 c: 2.699999999254942 d: 1.5(The numbers for 1000 vary quite a bit, though not as much as in Firefox)
Profiling functions over 10000 iterations. a: 121.40000000037253 b: 194.90000000037253 c: 196.59999999962747 d: 98Profiling functions over 100000 iterations. a: 10114 b: 19862.099999999627 c: 20497.300000000745 d: 9974.400000000373

@hazelnoot @mitsunee whatever you choose, I do recommend adding a comment explaining why you wrote it that way, as otherwise some well-meaning soul will simply change it later ​​
@hazelnoot @mitsunee oops, I made the regex incorrectly for both tests! It should have been /^svg$/i, using the start- and end-of-string anchors. Fixing this has a negligible effect on all of the results, surprisingly enough.
@NotThatDeep @hazelnoot I definitely already knew that regex shouldn't be used for simple tests, but it's not like the best function here doesn't step through the string one char at a time either, the loop is just unrolled ​​
@mitsunee @hazelnoot sorry, what do you mean? The best function doesn't step through one char at a time, the loop is unrolled…?
@NotThatDeep @hazelnoot I did say that the best function does also step through the characters one at a time.

the fastest way would be to just compare the raw value in memory, but there's like 8 possibilities for that too because it needs to be case-insensitive.

Unrolling a loop means manually putting every step of a loop into your code instead of using a loop like regex would internally
@mitsunee @hazelnoot I'm a bit confused by your wording, sorry ​​

I see what you mean, just not how it really applies to my replies? I wasn't addressing anything to
you, just gathering some data I thought hazel would find helpful.
@hazelnoot why not just name.toLowerCase() == "svg" ?
@sodiboo performance - this runs in a very tight loop and I don't feel like experimenting to see if the JIT can optimize it enough

@hazelnoot @sodiboo i would assume that three indivial memory access could be slower than one 3-byte-wide one actually

i think the sensible thing would be benchmarking it