Code coverage performance is easy to explain. With no modification to your source code, you add a switch to your simulation and it adds a lot extra calculations that will slow your simulation down. You do not want to run with code coverage turned on for every simulation. Only after your test is passing, and then only periodically in regression tests.
You didn't explain the difference between a normal simulation and a UVM simulation. Is it the same stimulus and the UVM is just added to monitor and check the results? When you add code to a simulation, that will slow down the performance of the simulation depending on how much code was added, and how efficiently that code was written. Sometime a very few poorly written constructs like an assertion can slow down your simulation a lot. Questa has profiling tools to help you find those constructs.
If the UVM simulation is providing different stimulus than a normal simulation, then you can't make a fair comparison without knowing what parts of the design are being exercised, and how long the testcase is running for.