after benchmarking, ditching call_user_func