The UserExpression class is slow in general, because it requires execution of Python code. Some ways to implement more complicated logic in JIT-compiled C++ Expressions can be found in this thread and another one (linked by my answer in the first).
not mentioning that maybe fenics uses a higher order quadrature rule
Note that you can manually set the quadrature degree used by FEniCS, to override its (sometimes excessive) default choice, e.g.,
dx = dx(metadata={"quadrature_degree":n})
(and likewise for ds and dS), where n is an integer giving the degree of polynomial up to which integration is exact.