summaryrefslogtreecommitdiff
path: root/coverage/ctracer/tracer.c
diff options
context:
space:
mode:
authorNed Batchelder <ned@nedbatchelder.com>2021-10-14 18:32:41 -0400
committerNed Batchelder <ned@nedbatchelder.com>2021-10-14 18:59:00 -0400
commitd93614d1cefe5520bbda82d50603b79901d87303 (patch)
tree09bf1111b1f6467ee99e0491f37bee176d8eec28 /coverage/ctracer/tracer.c
parenta1101953f253754514e74d3d648c4d4ef9c0ad6c (diff)
downloadpython-coveragepy-git-nedbat/faster-branches.tar.gz
perf: reduce the overhead of recording branchesnedbat/faster-branches
Diffstat (limited to 'coverage/ctracer/tracer.c')
-rw-r--r--coverage/ctracer/tracer.c30
1 files changed, 23 insertions, 7 deletions
diff --git a/coverage/ctracer/tracer.c b/coverage/ctracer/tracer.c
index 00d9f106..f508a85d 100644
--- a/coverage/ctracer/tracer.c
+++ b/coverage/ctracer/tracer.c
@@ -174,22 +174,38 @@ static int
CTracer_record_pair(CTracer *self, int l1, int l2)
{
int ret = RET_ERROR;
-
- PyObject * t = NULL;
-
- t = Py_BuildValue("(ii)", l1, l2);
- if (t == NULL) {
+ PyObject * packed_obj = NULL;
+ long packed = 0;
+
+ // Conceptually, data is a set of tuples (l1, l2), but that literally
+ // making a set of tuples would require us to construct a tuple just to
+ // see if we'd already recorded an arc. On many-times-executed code,
+ // that would mean we construct a tuple, find the tuple is already in the
+ // set, then discard the tuple. We can avoid that overhead by packing
+ // the two line numbers into one integer instead.
+ // See collector.py:flush_data for the Python code that unpacks this.
+ if (l1 < 0) {
+ packed |= (1L << 40);
+ l1 = -l1;
+ }
+ if (l2 < 0) {
+ packed |= (1L << 41);
+ l2 = -l2;
+ }
+ packed |= (((long)l2) << 20) + (long)l1;
+ packed_obj = PyLong_FromLong(packed);
+ if (packed_obj == NULL) {
goto error;
}
- if (PySet_Add(self->pcur_entry->file_data, t) < 0) {
+ if (PySet_Add(self->pcur_entry->file_data, packed_obj) < 0) {
goto error;
}
ret = RET_OK;
error:
- Py_XDECREF(t);
+ Py_XDECREF(packed_obj);
return ret;
}