Your benchmark disagrees with mine (with x 20 and x 200). Additionally, I think you should re-read perlre with regards to what /o does.
I am sure diotalevi will improve upon my explanation but in a nutshell, /o is an old optimization predating qr//. If you needed to interpolate a variable inside a regex such as /$regex/ but knew that $regex would never change, the flag would tell perl to only compile the regex once. In fact, if you broke your promise and changed $regex then it would still not recompile it leading to buggy code. Then came along qr// and improved things greatly (see /o is dead, long live qr//!).
Since you are not using a variable in your interpolation - the /o is having no effect.
the fault for the huge disparity seems to be mine. i accidentally wrote $string instead of $str in the source code as i first posted my regex solution and since themage seems to have his solution based on mine he copied the mistake. The huge results are based on $string being uninitialized.
i found the mistake as i tried my solution later on my pc and changed the typo. but that was after themage wrote his reply
"WHAT CAN THE HARVEST HOPE FOR IF NOT THE CARE OF THE REAPER MAN"
-- Terry Pratchett, "Reaper Man"