Tôi tò mò về hiệu suất của các phương thức khác nhau cho một int trong phạm vi [0, 255]
, vì vậy tôi quyết định thực hiện một số thử nghiệm thời gian.
Dựa trên timings dưới đây, và từ xu hướng chung tôi quan sát thấy từ cố gắng nhiều giá trị và cấu hình khác nhau, struct.pack
có vẻ là nhanh nhất, tiếp theo là int.to_bytes
, bytes
và với str.encode
(gì ngạc nhiên) là chậm nhất. Lưu ý rằng kết quả cho thấy một số biến thể nhiều hơn so với được trình bày int.to_bytes
và bytes
đôi khi chuyển đổi thứ hạng tốc độ trong quá trình thử nghiệm, nhưng struct.pack
rõ ràng là nhanh nhất.
Kết quả trong CPython 3.7 trên Windows:
Testing with 63:
bytes_: 100000 loops, best of 5: 3.3 usec per loop
to_bytes: 100000 loops, best of 5: 2.72 usec per loop
struct_pack: 100000 loops, best of 5: 2.32 usec per loop
chr_encode: 50000 loops, best of 5: 3.66 usec per loop
Mô-đun kiểm tra (có tên int_to_byte.py
):
"""Functions for converting a single int to a bytes object with that int's value."""
import random
import shlex
import struct
import timeit
def bytes_(i):
"""From Tim Pietzcker's answer:
https://stackoverflow.com/a/21017834/8117067
"""
return bytes([i])
def to_bytes(i):
"""From brunsgaard's answer:
https://stackoverflow.com/a/30375198/8117067
"""
return i.to_bytes(1, byteorder='big')
def struct_pack(i):
"""From Andy Hayden's answer:
https://stackoverflow.com/a/26920966/8117067
"""
return struct.pack('B', i)
# Originally, jfs's answer was considered for testing,
# but the result is not identical to the other methods
# https://stackoverflow.com/a/31761722/8117067
def chr_encode(i):
"""Another method, from Quuxplusone's answer here:
https://codereview.stackexchange.com/a/210789/140921
Similar to g10guang's answer:
https://stackoverflow.com/a/51558790/8117067
"""
return chr(i).encode('latin1')
converters = [bytes_, to_bytes, struct_pack, chr_encode]
def one_byte_equality_test():
"""Test that results are identical for ints in the range [0, 255]."""
for i in range(256):
results = [c(i) for c in converters]
# Test that all results are equal
start = results[0]
if any(start != b for b in results):
raise ValueError(results)
def timing_tests(value=None):
"""Test each of the functions with a random int."""
if value is None:
# random.randint takes more time than int to byte conversion
# so it can't be a part of the timeit call
value = random.randint(0, 255)
print(f'Testing with {value}:')
for c in converters:
print(f'{c.__name__}: ', end='')
# Uses technique borrowed from https://stackoverflow.com/q/19062202/8117067
timeit.main(args=shlex.split(
f"-s 'from int_to_byte import {c.__name__}; value = {value}' " +
f"'{c.__name__}(value)'"
))
3 .to_bytes