Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Speed up id generation #65

Merged
merged 3 commits into from
Jan 12, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions py_zipkin/util.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
import codecs
import os
import random
import struct
import time


def generate_random_64bit_string():
Expand All @@ -11,16 +11,22 @@ def generate_random_64bit_string():

:returns: random 16-character string
"""
return str(codecs.encode(os.urandom(8), 'hex_codec').decode('utf-8'))
return '{:016x}'.format(random.getrandbits(64))


def generate_random_128bit_string():
"""Returns a 128 bit UTF-8 encoded string. Follows the same conventions
as generate_random_64bit_string().

:returns: random 32-character string
The upper 32 bits are the current time in epoch seconds, and the
lower 96 bits are random. This allows for AWS X-Ray `interop
<https://github.com/openzipkin/zipkin/issues/1754>`_

:returns: 32-character hex string
"""
return str(codecs.encode(os.urandom(16), 'hex_codec').decode('utf-8'))
t = int(time.time())
lower_96 = random.getrandbits(96)
return '{:032x}'.format((t << 96) | lower_96)


def unsigned_hex_to_signed_int(hex_string):
Expand Down
1 change: 1 addition & 0 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ coverage
mock
ordereddict
pytest
pytest-benchmark[histogram]
11 changes: 11 additions & 0 deletions tests/profiling/zipkin_span_benchmark_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import pytest

import py_zipkin.zipkin as zipkin


@pytest.mark.parametrize('use_128', [False, True])
def test_create_attrs_for_span(benchmark, use_128):
benchmark(
zipkin.create_attrs_for_span,
use_128bit_trace_id=use_128,
)
13 changes: 8 additions & 5 deletions tests/util_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,24 @@
from py_zipkin import util


@mock.patch('py_zipkin.util.codecs.encode', autospec=True)
@mock.patch('py_zipkin.util.random.getrandbits', autospec=True)
def test_generate_random_64bit_string(rand):
rand.return_value = b'17133d482ba4f605'
rand.return_value = 0x17133d482ba4f605
random_string = util.generate_random_64bit_string()
assert random_string == '17133d482ba4f605'
# This acts as a contract test of sorts. This should return a str
# in both py2 and py3. IOW, no unicode objects.
assert isinstance(random_string, str)


@mock.patch('py_zipkin.util.codecs.encode', autospec=True)
def test_generate_random_128bit_string(rand):
rand.return_value = b'17133d482ba4f60517133d482ba4f605'
@mock.patch('py_zipkin.util.time.time', autospec=True)
@mock.patch('py_zipkin.util.random.getrandbits', autospec=True)
def test_generate_random_128bit_string(rand, mock_time):
rand.return_value = 0x2ba4f60517133d482ba4f605
mock_time.return_value = float(0x17133d48)
random_string = util.generate_random_128bit_string()
assert random_string == '17133d482ba4f60517133d482ba4f605'
rand.assert_called_once_with(96) # 96 bits
# This acts as a contract test of sorts. This should return a str
# in both py2 and py3. IOW, no unicode objects.
assert isinstance(random_string, str)
Expand Down
13 changes: 12 additions & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ envlist = pre-commit, py27, py34, py35, py36, flake8
deps = -rrequirements-dev.txt
commands =
coverage erase
coverage run --source=py_zipkin/ -m pytest -vv {posargs:tests}
coverage run --source=py_zipkin/ -m pytest -vv --benchmark-skip {posargs:tests}
coverage report -m --show-missing --fail-under 100

[testenv:pre-commit]
Expand All @@ -19,6 +19,17 @@ deps = flake8
commands =
flake8 py_zipkin tests

[testenv:benchmark]
basepython = python3.6
deps =
-rrequirements-dev.txt
commands =
python -m pytest -vv --capture=no {posargs:tests/profiling} \
--benchmark-only --benchmark-min-rounds=15 \
--benchmark-group-by func --benchmark-name short \
--benchmark-save=benchmark --benchmark-save-data \
--benchmark-histogram=.benchmarks/benchmark

[flake8]
exclude = .svn,CVS,.bzr,.hg,.git,__pycache__,.tox,docs,python_zipkin/thrift/zipkinCore
max_line_length = 83