Description
Describe the bug
Running with coveragepy on PyPy drastically slows down programs using Decimal:
~/tmp/pypyperftest$ time poetry run coverage run -m covperftest.covperftest 10000000
10000000
real 7m37,942s
user 7m36,118s
sys 0m1,348s
~/tmp/pypyperftest$ time poetry run python -m covperftest.covperftest 10000000
10000000
real 0m5,891s
user 0m5,267s
sys 0m0,606s
I've noticed this issue while experimenting with PyPy's newest versions in the past, trying to migrate to Python 3.8. At the time I didn't pay much attention, just gave up. Now that PyPy launched a new version supporting 3.9, I tried to investigate a bit more and got the results above. At first I thought that maybe it was because PyPy is using Decimal with a pure Python implementation, but forcing the C implementation yields similar results (if not slower).
To Reproduce
- What version of Python are you using?
- Pypy 3.9 (7.3.8) - but I've noticed this problem while using earlier versions of PyPy.
- What version of coverage.py shows the problem?
- I tested with the latest release, version 6.3.2.
- What versions of what packages do you have installed?
- I tried to test in a virtualenv with as few packages as possible:
cffi==1.15.0
coverage==6.3.2
covperftest==1.0.0
greenlet==0.4.13
hpy==0.0.3
readline==6.2.4.1
tomli==2.0.1
- What code shows the problem?
- I'm not sure where the problem in coveragepy is (or if there's even a problem at all, maybe it's something related to how Decimal works on PyPy, but I thought it would be better to report this here).
- What commands did you run?
- I created a sample script to test this, which I executed in a virtualenv managed using poetry:
import random
import sys
from decimal import Decimal
size = int(sys.argv[1]) if len(sys.argv) > 1 else 100000
values = []
for _ in range(size):
values.append(Decimal(3) * random.randint(0, 10000))
print(len(values), file=sys.stderr)
Expected behavior
Although a worse performance is to be expected when getting the coverage, it gets much worse when using Decimal. I tried the same code using just an integer, and the execution time was around 4.5x slower when using coveragepy. But when using Decimal, it was 77x slower.