Defining efficiently subdomain-dependent expressions

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.