Challenge: write a really really small front() for UTF8

Michel Fortin michel.fortin at michelf.ca
Mon Mar 24 06:39:45 PDT 2014


On 2014-03-24 06:08:30 +0000, "safety0ff" <safety0ff.dev at gmail.com> said:

> Everything seems to work in your corrected versions:
> http://dpaste.dzfl.pl/3b32535559ba
> 
> Andrei's version doesn't compile on recent compiler versions due to 
> goto skipping initialization.

Ok, so let's check what happens in actual usage. In other words, what 
happens when front is inlined and used in a loop. I'm counting the 
number of assembly lines of this main function for looping through each 
possible input using the various implementations:

http://goo.gl/QjnA2k

implementation   line count of main in assembly
andralex         285 -  9 labels = 276 instructions
MFortin1         135 - 13 labels = 122 instructions
MFortin2         150 - 14 labels = 136 instructions
safety0ff         -- not inlined (too big?) --
dnspies          161 - 15 labels = 146 instructions
CWilliams        233 - 25 labels = 208 instructions

For compactness, my first implementation seems to be the winner, both 
with and without inlining.

That said, I think front should only assume a non-empty char[] and thus 
should check the length before accessing anything after the first byte 
to protect against incomplete multi-byte sequences such as 
[0x1000_0000]. So I added this line to my two implementations:

    if (1+tailLength >= s.length) return dchar.init;

Now lets see what happens with those changes:

http://goo.gl/XPCGYE

implementation   line count of main in assembly
MFortin1Check    103 - 11 labels =  92 instructions
MFortin2Check    135 - 13 labels = 122 instructions

Now I'm baffled. Adding a test makes the code shorter? It actually make 
the standalone functions longer by 8 instructions (as expected), but 
the inlined version is shorter. My guess is that the optimizer creates 
something entirely different and it turns out that this different 
version optimises better after inlining.

That said, my test "main" function isn't very representative of the 
general case because the length is statically known by the optimizer. 
Let's see what it does when the length is not statically known:

http://goo.gl/E2Q0Yu

implementation   line count of main in assembly
andralex         384 -  9 labels = 375 instructions
MFortin1         173 - 19 labels = 154 instructions
MFortin2         182 - 18 labels = 164 instructions
safety0ff         -- not inlined --
dnspies           -- not inlined --
CWilliams        229 - 23 labels = 206 instructions
MFortin1Check    211 - 24 labels = 187 instructions
MFortin2Check    218 - 21 labels = 197 instructions

So again MFortin1 is the winner for compactness. Still, I maintain that 
we ought to at least check the length of the array for multi-byte 
sequences to protect against incomplete sequences that could lay at the 
end of the string, so I'd favor MFortin1Check.

-- 
Michel Fortin
michel.fortin at michelf.ca
http://michelf.ca



More information about the Digitalmars-d mailing list