I don't really have a project for the visibility jam, but today I was changing some code in the feed reader while I was looking at performance, and ended up writing some small visualization.
One of my test case is displaying a "big" html page, and I was looking at how much time was spent looking up kerning information for codepoints. Turns out there was about a lot of calls to the kerning function, about 96000 (times 2 but it doesn't matter), so I looked up if a binary search would be faster than the current linear search for that particular function.
The perfs seemed similar in the two cases, with the binary search maybe a tiny bit faster (talking about 200 micro seconds so it doesn't matter). So I then decided to check if the new version of the function was producing the same result as the old one. I wrote this simple code:
data_t output = memory_get_virtual( mebioctet( 10 ), 0 );
for ( umm i = 0; i < set.codepoint_count; i++ ) {
s32 codepoint = set.codepoints[ i ];
codepoint_metrics_t* cm = font_get_codepoint_metrics( collection.fonts, codepoint );
b32 out = false;
for ( umm j = 0; j < set.codepoint_count; j++ ) {
s32 kerning = font_get_kerning( collection.fonts, cm, set.codepoints[ j ] );
if ( kerning ) {
if ( !out ) {
string_push_u64( &output, codepoint, 0, 0, 0 );
memory_push_copy_l( &output, ":\n" );
out = true;
}
memory_push_copy_l( &output, " " );
string_push_u64( &output, set.codepoints[ j ], 0, 0, 0 );
memory_push_copy_l( &output, ", " );
string_push_s64( &output, kerning, 0, 0, 0 );
memory_push_copy_l( &output, "\n" );
}
}
}
file_write_entire( string_l( "kern_1.txt" ), output.bytes, output.used, true, &g_file_error );
Which produce this kind of result
33:
8217, -100
8221, -100
39:
65, -100
198, -100
44:
8217, -210
8221, -210
45:
65, -50
73, -30
74, -100
83, -20
84, -150
86, -50
87, -50
88, -80
89, -140
90, -30
97, -20
118, -40
119, -20
120, -50
121, -40
122, -40
198, -50
230, -20
46:
44, -130
45, -160
173, -160
8211, -120
8212, -120
8217, -210
8221, -210
...
And they didn't produce the same result. The new version seemed to produce wrong values: most of the original output consist of negative values that are multiples of 10 and I wasn't seeing that in the new version.
So I tried to figure what was wrong and while the process wasn't interesting, it turned out that both version were wrong, and I had been using wrong kerning information for several years !
The codepoint_metrics_t
struct contained the offset to use to reach the correct part of the kerning array for that codepoint. I never filled that offset after pushing things in the array, meaning all kerning queries started on the first element of the array (only the first codepoint metrics produced the correct value) and since the number of kerning entries was correct for each codepoint metrics, the search often didn't find the requested codepoint, and when it did, it was likely not the correct value.
After fixing the issue, I took a before and after screenshot and did a difference between the two to see the change. Here is what came up (opening the images in a new tab is a good idea):
Before (wrong)

After (correct)

Animated

Difference

That's all for me.