Don’t do this if you care about performance. Find another way to accomplish what you want.
In the case of fun_file, you only timed the cost of evaluating fun_file after it was compiled (because @btime runs the code multiple times and prints the minimum time), whereas in all the other cases you timed the cost of eval (which includes code generation).
The analogous thing, without using a file, would be to first eval a function expression once that includes all your generated expressions, and then subsequently call that function in @btime. But that won’t work if you are generating new expressions at runtime over and over. (Unless you call the expressions many times for each time they are generated, in which case the cost of eval-ing a function once may be negligible.)
Except in very narrow circumstances (e.g. you are writing a Julia interpreter GUI), doing runtime eval is a good sign that you need to re-think your approach.