Hacktoberfest 2026: những issue maintainer đã đánh dấu cho tháng Mười, đang mở và phù hợp người mới. Xem issue Hacktoberfest

`_generate_sample_rand` seeds a Mersenne Twister per Transaction, eagerly, even when unsampled (6.4 µs)

Đang mở
#7,401 2 bình luận 0 reaction 0 người được giao Xem trên GitHub

Chưa có ai nhận issue này.

Đánh giá

Độ khó
4/5
Thời gian dự kiến
3-5 ngày
Mức phù hợp với người mới
64/100
Loại issue
Tái cấu trúc
Độ rõ ràng
Khá rõ ràng
Mức độ hoạt động
Sôi nổi
Công nghệ
python
Lĩnh vực
performance

Hướng nghiên cứu

Bắt đầu tại sentry_sdk/tracing.py ở Transaction.init và sentry_sdk/tracing_utils.py ở _generate_sample_rand; kiểm tra cách _sample_rand được đọc và liệu có yêu cầu khả năng tương thích đầu ra hay không. Chạy benchmark của issue để so sánh các phương án, sau đó xác minh rằng các transaction không được sampling tránh thực hiện công việc không cần thiết, đồng thời vẫn duy trì hành vi sampling xác định.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

Python Traces
Summary

Transaction.__init__ unconditionally computes _generate_sample_rand(self.trace_id), and _generate_sample_rand seeds a Mersenne Twister to produce a single float. That is 6.4 µs per call on CPython 3.14 / Apple M2, paid on every request through the ASGI integrations even when tracing is disabled and the value can never be used.

Two independent problems:

1. It is eager. sentry_sdk/tracing.py, Transaction.__init__:

baggage_sample_rand = None if self._baggage is None else self._baggage._sample_rand()
if baggage_sample_rand is not None:
    self._sample_rand = baggage_sample_rand
else:
    self._sample_rand = _generate_sample_rand(self.trace_id)

_sample_rand is only read when a sampling decision is actually made. With traces_sample_rate unset the transaction is never sampled, so this is pure waste. Making it a lazy property costs nothing.

2. It is expensive. sentry_sdk/tracing_utils.py:

def _generate_sample_rand(trace_id, *, interval=(0.0, 1.0)):
    ...
    rng = Random(trace_id)
    sample_rand_scaled = rng.randrange(lower_scaled, upper_scaled)
    return sample_rand_scaled / 1_000_000

Random(seed) runs the full MT19937 init_by_array over a 625-word state. Measured with timeit, 50k iterations, best of 5:

µs
Random(trace_id) (32-char hex string) 6.39
Random(int(trace_id, 16)) 5.90
Random(12345) 5.89
int(trace_id, 16) / 2**128 0.23

The cost is the Mersenne Twister initialisation, not the string hashing - seeding with a small int is just as slow. Deriving a uniformly distributed value in [0, 1) arithmetically from the same trace id is 27x cheaper and just as deterministic.

Impact

On a do-nothing FastAPI endpoint with tracing disabled, making _generate_sample_rand cheap moves the SDK's per-request overhead from +61.3 µs to +53.3 µs (in-process measurement, baseline 15.6 µs/req) - about 13% of the SDK's cost, for a value that is discarded.

Questions
  1. Is the fix to Transaction.__init__ simply making _sample_rand lazy? Happy to open a PR.
  2. Is the exact output of _generate_sample_rand required to be bit-compatible across SDKs, or only to be deterministic-from-trace_id and uniformly distributed? If the latter, int(trace_id, 16) / 2**128 (scaled into the requested interval) would be a drop-in replacement. If the former, the laziness fix alone still helps.
Repro
import timeit, uuid
from random import Random
tid = uuid.uuid4().hex
n = 50000
for label, fn in [
    ("Random(hex str)", lambda: Random(tid)),
    ("Random(int)", lambda: Random(int(tid, 16))),
    ("Random(12345)", lambda: Random(12345)),
    ("int(tid,16)/2**128", lambda: int(tid, 16) / 2**128),
]:
    print(f"{label:<20} {min(timeit.repeat(fn, number=n, repeat=5)) / n * 1e6:.2f} us")

Environment: CPython 3.14.7, sentry-sdk 2.67.1, Apple M2.

Context: this was found while measuring 7400, where the discarded Transaction is the larger half of the same problem.

Ngôn ngữ chính
Python
Star
2.2k
Fork
672
Merge trung bình
22 giờ 47 phút
Pull request đã merge (30 ngày)
224

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của getsentry/sentry-python

Tất cả issue của getsentry/sentry-python

Issue tương tự

Thêm issue về Python

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.