2ns is currently around the benchmark results of integer addition, an indication that the actual call got compiled out of the benchmark loop. Use $ for runtime arguments in BenchmarkTools, it changes quite a bit:
julia> @btime hasmethod(test_no_kw, (Any,))
1.000 ns (0 allocations: 0 bytes)
true
julia> @btime hasmethod($test_no_kw, $(Any,))
625.444 ns (9 allocations: 352 bytes)
true
Still slower than involving keyword arguments, I imagine it’s just extra work after method dispatch over the positional arguments.
julia> @btime hasmethod($test_many_kw, $(), $(:a,))
1.240 μs (15 allocations: 568 bytes)
true
julia> @btime hasmethod($test_many_kw, $(), $(:a, :c, :b))
1.260 μs (15 allocations: 600 bytes)
true
Ideally you’re not checking for method existence at runtime.