Skip to content

Commit feeb9c8

Browse files
brettlangdonKyle-Verhoogchristophe-papazianvitor-de-araujoemmettbutler
authored andcommitted
perf: cache trace_id_64bits when encoding (#14034)
Avoiding accessing the `Span.trace_id_64bits` computed per-span, when the value is the same for every encoded trace. This change accesses the trace id once and passes along to every `pack_span` call. ## Checklist - [x] PR author has checked that all the criteria below are met - The PR description includes an overview of the change - The PR description articulates the motivation for the change - The change includes tests OR the PR description describes a testing strategy - The PR description notes risks associated with the change, if any - Newly-added code is easy to change - The change follows the [library release note guidelines](https://ddtrace.readthedocs.io/en/stable/releasenotes.html) - The change includes or references documentation updates if necessary - Backport labels are set (if [applicable](https://ddtrace.readthedocs.io/en/latest/contributing.html#backporting)) ## Reviewer Checklist - [ ] Reviewer has checked that all the criteria below are met - Title is accurate - All changes are related to the pull request's stated goal - Avoids breaking [API](https://ddtrace.readthedocs.io/en/stable/versioning.html#interfaces) changes - Testing strategy adequately addresses listed risks - Newly-added code is easy to change - Release note makes sense to a user of the library - If necessary, author has acknowledged and discussed the performance implications of this PR as reported in the benchmarks PR comment - Backport labels are set in a manner that is consistent with the [release branch maintenance policy](https://ddtrace.readthedocs.io/en/latest/contributing.html#backporting) --------- Co-authored-by: kyle <[email protected]> Co-authored-by: Christophe Papazian <[email protected]> Co-authored-by: Vítor De Araújo <[email protected]> Co-authored-by: Emmett Butler <[email protected]> Co-authored-by: jsimpher <[email protected]> Co-authored-by: Yun Kim <[email protected]> Co-authored-by: Taegyun Kim <[email protected]>
1 parent 8b4dceb commit feeb9c8

File tree

2 files changed

+24
-8
lines changed

2 files changed

+24
-8
lines changed

ddtrace/internal/_encoding.pyx

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,7 @@ cdef class MsgpackEncoderBase(BufferedEncoder):
498498
cdef int ret
499499
cdef Py_ssize_t L
500500
cdef void * dd_origin = NULL
501+
cdef unsigned long long trace_id_64bits = 0
501502

502503
L = len(trace)
503504
if L > ITEM_LIMIT:
@@ -507,12 +508,26 @@ cdef class MsgpackEncoderBase(BufferedEncoder):
507508
if ret != 0:
508509
raise RuntimeError("Couldn't pack trace")
509510

510-
if L > 0 and trace[0].context is not None and trace[0].context.dd_origin is not None:
511+
# TODO: Can we skip packing an empty array?
512+
if L == 0:
513+
return 0
514+
515+
if trace[0].context is not None and trace[0].context.dd_origin is not None:
511516
dd_origin = self.get_dd_origin_ref(trace[0].context.dd_origin)
512517

518+
# PERF: _trace_id_64bits is a computed property, cache/convert once for all spans
519+
try:
520+
trace_id_64bits = trace[0]._trace_id_64bits
521+
522+
# We can get TypeError if the trace_id is not an int
523+
# e.g. "unsupported operand type(s) for &: 'int' and 'str'"
524+
except Exception as e:
525+
raise RuntimeError(
526+
"failed to pack span: {!r}. Exception: {}".format(trace[0], e)
527+
)
513528
for span in trace:
514529
try:
515-
ret = self.pack_span(span, dd_origin)
530+
ret = self.pack_span(span, trace_id_64bits, dd_origin)
516531
except Exception as e:
517532
raise RuntimeError("failed to pack span: {!r}. Exception: {}".format(span, e))
518533

@@ -562,7 +577,7 @@ cdef class MsgpackEncoderBase(BufferedEncoder):
562577
cpdef flush(self):
563578
raise NotImplementedError()
564579

565-
cdef int pack_span(self, object span, void *dd_origin) except? -1:
580+
cdef int pack_span(self, object span, unsigned long long trace_id_64bits, void *dd_origin) except? -1:
566581
raise NotImplementedError()
567582

568583

@@ -744,7 +759,7 @@ cdef class MsgpackEncoderV04(MsgpackEncoderBase):
744759

745760
raise TypeError("Unhandled metrics type: %r" % type(metrics))
746761

747-
cdef int pack_span(self, object span, void *dd_origin) except? -1:
762+
cdef int pack_span(self, object span, unsigned long long trace_id_64bits, void *dd_origin) except? -1:
748763
cdef int ret
749764
cdef Py_ssize_t L
750765
cdef int has_span_type
@@ -775,7 +790,7 @@ cdef class MsgpackEncoderV04(MsgpackEncoderBase):
775790
ret = pack_bytes(&self.pk, <char *> b"trace_id", 8)
776791
if ret != 0:
777792
return ret
778-
ret = pack_number(&self.pk, span._trace_id_64bits)
793+
ret = msgpack_pack_unsigned_long_long(&self.pk, trace_id_64bits)
779794
if ret != 0:
780795
return ret
781796

@@ -1020,7 +1035,7 @@ cdef class MsgpackEncoderV05(MsgpackEncoderBase):
10201035
cdef void * get_dd_origin_ref(self, str dd_origin):
10211036
return <void *> PyLong_AsLong(self._st._index(dd_origin))
10221037

1023-
cdef int pack_span(self, object span, void *dd_origin) except? -1:
1038+
cdef int pack_span(self, object span, unsigned long long trace_id_64bits, void *dd_origin) except? -1:
10241039
cdef int ret
10251040

10261041
ret = msgpack_pack_array(&self.pk, 12)
@@ -1037,8 +1052,7 @@ cdef class MsgpackEncoderV05(MsgpackEncoderBase):
10371052
if ret != 0:
10381053
return ret
10391054

1040-
_ = span._trace_id_64bits
1041-
ret = msgpack_pack_uint64(&self.pk, _ if _ is not None else 0)
1055+
ret = msgpack_pack_unsigned_long_long(&self.pk, trace_id_64bits)
10421056
if ret != 0:
10431057
return ret
10441058

tests/tracer/test_encoders.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ def gen_trace(nspans=1000, ntags=50, key_size=15, value_size=20, nmetrics=10):
7070
resource="/fsdlajfdlaj/afdasd%s" % i,
7171
service="myservice",
7272
parent_id=parent_id,
73+
# All spans in a trace must share a trace_id
74+
trace_id=root.trace_id if root else None,
7375
) as span:
7476
span._parent = root
7577
span.set_tags({rands(key_size): rands(value_size) for _ in range(0, ntags)})

0 commit comments

Comments
 (0)