It's actually slower and more memory intensive than any of the other solutions. Tie::File internally keeps a list of byte offsets for all the lines, and it needs lot of additional overhead that is supposed to optimize writes which you never make any use of.
Oops. Guessed wrong, then.
Your code also doesn't get the edge cases right: if there's a match within less than $context lines of the previous, it will be missed.
That was intentional, and it depends on your definition of "missed". That hit will be printed with the context of the previous hit. Changing the behavior would just require removing the line:
$i += $context;