A Line-by-Line C# Port of VLC's Gaussian Blur Ran 23% Slower Than the C, Then Both Got 30 Times Faster
Martin Finkel raced VLC's 2007 blur filter against a C# copy inside the same player, on the same frames, with byte-identical output. The language gap shrank to single digits. The algorithm gap did not.

The race had strict rules. Finkel’s C# filter plugs into VLC through VLCLR, his bridge for writing native VLC plugins in .NET, compiled ahead of time with Native AOT. Both filters ran “inside the same VLC, on the same frames, with byte-identical output,” on an 11th-gen Core i7 laptop chip with four cores.
The blur itself is old. VLC has carried it since 2007 as “Spatial blur,” and the bell curve behind it goes back to Gauss in 1809. At sigma 4 it averages a 25-pixel window for every pixel, once across and once down.
Round one was the honest copy. VLC took 62.0, 125.9 and 252.9 milliseconds a frame at sigma 2, 4 and 8. The C# port took 78.9, 155.2 and 298.1, “about 23% longer.” Finkel went looking for why and found it in the machine code: .NET’s RyuJIT “emits about twice as many instructions: it recomputes Math.Min(…) on every step and keeps the sum in memory.” He’s clear that the garbage collector wasn’t the culprit. The filter “allocates nothing on the managed heap per frame, so the garbage collector has nothing to collect while it runs.”
An update the same day narrowed that first gap. Pulling the bounds into local variables and switching to nint indices put the C# “within 8% of the C,” and it came out ahead at sigma 4 in that run.
Round two changed the algorithm, in both languages. Division became a multiply by a magic reciprocal and a shift. Rows were read in order. The symmetric kernel got folded so each weight multiplies a pair of pixels at once, and the borders got their own loop. The C dropped to 23.3, 40.7 and 75.4 milliseconds. The C# landed at 28.1, 50.6 and 98.9, which Finkel puts at “2.5 times faster than the current VLC code.”
Round three went to AVX2, still on a single thread, handling “16 pixels per instruction in the horizontal pass.” The tuned C ran 3.08, 4.17 and 6.62 milliseconds. The tuned C# ran 3.05, 4.23 and 7.22. “On par, within the measurement noise,” he wrote, with “C# takes 9% longer at the largest blur. Both are 30 times faster than the current VLC code.”
At sigma 4 that’s the difference between watching 1080p video at about 8 frames a second and about 240.
He also liked reading the C# better. “The types say what is in each register, where C has one __m256i for everything.”
The race turned up two real bugs along the way. With hardware decoding on, any CPU filter turned half the picture green, and the blur read past the right edge of each line. His fix for the second, merge request 10490, explains that the bound let luma reads land “two pixels past the last visible one,” in the line padding, so “the rightmost columns depended on whatever the padding contained.” It was merged on October 14.
Finkel says Claude “wrote most of the code and the benchmark harness,” and that he designed the experiment and the rules. He still thinks this filter “belongs on the GPU.” Whether anyone sends VLC the 30-times-faster version is the part his post leaves open.
His closing line sets the terms for anyone picking a language for hot loops: “If the last 10% matters, C is still the answer. For everything else, the language you are most productive in, plus a good algorithm, will get you further.” The price he puts on choosing C# is “knowing what the compiler does with your loops,” which means reading the disassembly when a number looks wrong, the way he did in round one.