⚡️ Speed up method bitteam.parse_transaction by 31%
#47
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
📄 31% (0.31x) speedup for
bitteam.parse_transactioninpython/ccxt/bitteam.py⏱️ Runtime :
18.4 milliseconds→14.0 milliseconds(best of49runs)📝 Explanation and details
The optimization significantly improves performance by eliminating redundant type checks and method lookups in the
safe_*utility methods that are heavily used throughout the codebase.Key optimizations:
Fast-path for dictionary access: The original code called
Exchange.key_exists()which performs expensivehasattr(),isinstance(), and exception handling for every access. The optimized version usesisinstance(dictionary, dict)once, thendictionary.get(key)for direct O(1) lookup, avoiding the overhead entirely for the common dictionary case.Reduced method lookups in
iso8601(): Instead of repeatedly accessingdatetime.datetime.fromtimestampanddatetime.timezone.utc, these are cached as local variables (dt_fromtimestamp,dt_timezone_utc), eliminating attribute lookup overhead on each call.Type checking optimization: The original
isinstance(timestamp, int)is replaced withtype(timestamp) is not int, which is faster for exact type matching.Streamlined error handling: The optimized
safe_integer()andsafe_value()methods handle the most common case (dictionaries) first with minimal checks, then fall back to the original logic for edge cases like lists.Performance impact: The 31% speedup is particularly significant because these methods are called extensively during transaction parsing -
safe_stringalone is called 17,365 times in the profiler results. The optimizations are most effective for dictionary-heavy workloads (which cryptocurrency exchanges primarily use), where the fast-path eliminates expensive type checking and exception handling on every field access.Test results show consistent improvements: 7-20% faster per transaction across various scenarios, with larger improvements (up to 34%) for batch operations where the cumulative effect of these micro-optimizations becomes substantial.
✅ Correctness verification report:
🌀 Generated Regression Tests and Runtime
import copy
import time
imports
import pytest
from ccxt.bitteam import bitteam
Helper: minimal valid currency dict for tests
def make_currency(symbol="usdt", decimals=6, blockChain="Ethereum"):
return {
"symbol": symbol,
"decimals": decimals,
"blockChain": blockChain,
"links": [
{
"tx": "https://etherscan.io/tx/",
"address": "https://etherscan.io/address/",
"blockChain": "Ethereum"
}
]
}
Helper: minimal valid transaction dict for tests
def make_transaction(**kwargs):
tx = {
"id": 123,
"orderId": None,
"transactionCoreId": "561418",
"userId": 1,
"recipient": "0xabc",
"sender": None,
"symbolId": 3,
"CommissionId": None,
"amount": "100000000",
"params": {"tx_id": "0xdeadbeef"},
"reason": None,
"timestamp": 1700594180417,
"status": "success",
"statusDescription": None,
"type": "deposit",
"message": None,
"blockChain": "Ethereum",
"before": 0,
"after": 100000000,
"currency": make_currency(),
"description": "Deposit completed"
}
tx.update(kwargs)
return tx
@pytest.fixture
def exchange():
return bitteam({})
------------------------------
1. Basic Test Cases
------------------------------
def test_parse_transaction_basic_deposit(exchange):
"""Basic: parses a standard deposit transaction correctly"""
tx = make_transaction()
codeflash_output = exchange.parse_transaction(tx); result = codeflash_output # 50.5μs -> 47.0μs (7.59% faster)
def test_parse_transaction_basic_withdraw(exchange):
"""Basic: parses a standard withdrawal transaction correctly"""
tx = make_transaction(type="withdraw", status="approving")
codeflash_output = exchange.parse_transaction(tx); result = codeflash_output # 50.1μs -> 45.2μs (10.9% faster)
def test_parse_transaction_basic_custom_currency(exchange):
"""Basic: parses a transaction with a custom currency symbol/case"""
tx = make_transaction(currency=make_currency(symbol="btc", decimals=8, blockChain="Bitcoin"))
tx["amount"] = "123456789" # 1.23456789 BTC
codeflash_output = exchange.parse_transaction(tx); result = codeflash_output # 49.1μs -> 44.6μs (10.0% faster)
def test_parse_transaction_basic_sender_and_tag(exchange):
"""Basic: parses sender and tag fields"""
tx = make_transaction(sender="0xsender", message="memo123")
codeflash_output = exchange.parse_transaction(tx); result = codeflash_output # 49.7μs -> 45.5μs (9.24% faster)
def test_parse_transaction_basic_missing_optional_fields(exchange):
"""Basic: handles missing optional fields gracefully"""
tx = make_transaction()
del tx["description"]
del tx["params"]
del tx["blockChain"]
tx["currency"]["links"] = [
{
"tx": "https://etherscan.io/tx/",
"address": "https://etherscan.io/address/",
"blockChain": "Ethereum"
}
]
codeflash_output = exchange.parse_transaction(tx); result = codeflash_output # 52.0μs -> 47.8μs (8.92% faster)
------------------------------
2. Edge Test Cases
------------------------------
def test_parse_transaction_edge_amount_as_zero(exchange):
"""Edge: amount is zero"""
tx = make_transaction(amount="0")
codeflash_output = exchange.parse_transaction(tx); result = codeflash_output # 48.3μs -> 43.8μs (10.4% faster)
def test_parse_transaction_edge_amount_as_none(exchange):
"""Edge: amount is None"""
tx = make_transaction(amount=None)
codeflash_output = exchange.parse_transaction(tx); result = codeflash_output # 37.1μs -> 32.0μs (15.7% faster)
def test_parse_transaction_edge_currency_missing(exchange):
"""Edge: currency field is missing"""
tx = make_transaction()
del tx["currency"]
codeflash_output = exchange.parse_transaction(tx); result = codeflash_output # 35.3μs -> 32.5μs (8.50% faster)
def test_parse_transaction_edge_currency_decimals_missing(exchange):
"""Edge: currency.decimals is missing"""
tx = make_transaction()
del tx["currency"]["decimals"]
codeflash_output = exchange.parse_transaction(tx); result = codeflash_output # 37.2μs -> 33.4μs (11.5% faster)
def test_parse_transaction_edge_currency_symbol_missing(exchange):
"""Edge: currency.symbol is missing"""
tx = make_transaction()
del tx["currency"]["symbol"]
codeflash_output = exchange.parse_transaction(tx); result = codeflash_output # 49.5μs -> 45.3μs (9.37% faster)
def test_parse_transaction_edge_params_missing(exchange):
"""Edge: params is missing"""
tx = make_transaction()
del tx["params"]
codeflash_output = exchange.parse_transaction(tx); result = codeflash_output # 50.3μs -> 46.2μs (8.92% faster)
def test_parse_transaction_edge_params_txid_missing(exchange):
"""Edge: params exists but tx_id missing"""
tx = make_transaction(params={})
codeflash_output = exchange.parse_transaction(tx); result = codeflash_output # 49.6μs -> 45.6μs (8.96% faster)
def test_parse_transaction_edge_status_unexpected(exchange):
"""Edge: status is an unexpected value"""
tx = make_transaction(status="foobar")
codeflash_output = exchange.parse_transaction(tx); result = codeflash_output # 49.3μs -> 45.1μs (9.33% faster)
def test_parse_transaction_edge_type_unexpected(exchange):
"""Edge: type is an unexpected value"""
tx = make_transaction(type="bonus")
codeflash_output = exchange.parse_transaction(tx); result = codeflash_output # 49.5μs -> 45.2μs (9.50% faster)
def test_parse_transaction_edge_network_missing_everywhere(exchange):
"""Edge: blockChain and links missing, network should be None"""
tx = make_transaction()
del tx["blockChain"]
del tx["currency"]["links"]
codeflash_output = exchange.parse_transaction(tx); result = codeflash_output # 49.7μs -> 45.8μs (8.51% faster)
def test_parse_transaction_edge_links_empty(exchange):
"""Edge: links is an empty list, network should be None"""
tx = make_transaction()
tx["blockChain"] = None
tx["currency"]["links"] = []
codeflash_output = exchange.parse_transaction(tx); result = codeflash_output # 50.1μs -> 44.8μs (11.8% faster)
def test_parse_transaction_edge_timestamp_none(exchange):
"""Edge: timestamp is None"""
tx = make_transaction(timestamp=None)
codeflash_output = exchange.parse_transaction(tx); result = codeflash_output # 33.9μs -> 30.7μs (10.6% faster)
def test_parse_transaction_edge_id_is_int_and_str(exchange):
"""Edge: id is int or string, output should always be string"""
tx = make_transaction(id=987)
codeflash_output = exchange.parse_transaction(tx); result = codeflash_output # 49.9μs -> 45.7μs (9.20% faster)
tx2 = make_transaction(id="abc123")
codeflash_output = exchange.parse_transaction(tx2); result2 = codeflash_output # 24.1μs -> 20.7μs (16.8% faster)
def test_parse_transaction_edge_currency_symbol_case(exchange):
"""Edge: currency symbol is mixed case, output code is uppercase"""
tx = make_transaction(currency=make_currency(symbol="eTh", decimals=18, blockChain="Ethereum"))
tx["amount"] = "1230000000000000000" # 1.23 ETH
codeflash_output = exchange.parse_transaction(tx); result = codeflash_output # 50.0μs -> 45.7μs (9.57% faster)
def test_parse_transaction_edge_large_amount(exchange):
"""Edge: very large amount, high precision"""
tx = make_transaction(currency=make_currency(symbol="usdt", decimals=6), amount="123456789012345678")
codeflash_output = exchange.parse_transaction(tx); result = codeflash_output # 50.9μs -> 45.6μs (11.4% faster)
def test_parse_transaction_edge_negative_amount(exchange):
"""Edge: negative amount (should be parsed as negative float)"""
tx = make_transaction(amount="-1000000")
codeflash_output = exchange.parse_transaction(tx); result = codeflash_output # 49.7μs -> 45.2μs (10.1% faster)
def test_parse_transaction_edge_currency_links_multiple(exchange):
"""Edge: currency.links has multiple entries, blockChain missing, should use first link's blockChain"""
links = [
{"tx": "https://etherscan.io/tx/", "address": "https://etherscan.io/address/", "blockChain": "Ethereum"},
{"tx": "https://tronscan.org/#/transaction/", "address": "https://tronscan.org/#/address/", "blockChain": "Tron"}
]
tx = make_transaction(blockChain=None)
tx["currency"]["links"] = links
codeflash_output = exchange.parse_transaction(tx); result = codeflash_output # 51.2μs -> 47.1μs (8.83% faster)
def test_parse_transaction_edge_currency_links_first_missing_blockchain(exchange):
"""Edge: first link missing blockChain, should fallback to None"""
links = [
{"tx": "https://etherscan.io/tx/", "address": "https://etherscan.io/address/"},
{"tx": "https://tronscan.org/#/transaction/", "address": "https://tronscan.org/#/address/", "blockChain": "Tron"}
]
tx = make_transaction(blockChain=None)
tx["currency"]["links"] = links
codeflash_output = exchange.parse_transaction(tx); result = codeflash_output # 49.1μs -> 44.6μs (9.87% faster)
------------------------------
3. Large Scale Test Cases
------------------------------
def test_parse_transaction_large_batch(exchange):
"""Large: parse a batch of 500 transactions efficiently and accurately"""
batch = []
for i in range(500):
tx = make_transaction(
id=i,
amount=str(1000000 * (i + 1)),
currency=make_currency(symbol="usdt", decimals=6),
params={"tx_id": f"txid_{i}"},
timestamp=1700000000000 + i * 1000
)
batch.append(tx)
results = [exchange.parse_transaction(tx) for tx in batch] # 57.2μs -> 51.2μs (11.7% faster)
for i, result in enumerate(results):
pass
def test_parse_transaction_large_batch_varied(exchange):
"""Large: parse a batch of 100 transactions with varied types, currencies, and statuses"""
batch = []
for i in range(100):
symbol = "btc" if i % 2 == 0 else "eth"
decimals = 8 if symbol == "btc" else 18
tx_type = "deposit" if i % 3 == 0 else "withdraw"
status = "success" if i % 4 == 0 else "approving"
tx = make_transaction(
id=f"tx{i}",
amount=str(10**decimals * (i + 1)),
currency=make_currency(symbol=symbol, decimals=decimals, blockChain=symbol.upper()),
type=tx_type,
status=status,
params={"tx_id": f"txid_{i}"},
timestamp=1700000000000 + i * 1000
)
batch.append(tx)
results = [exchange.parse_transaction(tx) for tx in batch] # 52.4μs -> 47.7μs (9.83% faster)
for i, result in enumerate(results):
symbol = "BTC" if i % 2 == 0 else "ETH"
decimals = 8 if symbol == "BTC" else 18
expected_amount = float(i + 1)
if i % 3 == 0:
pass
else:
pass
if i % 4 == 0:
pass
else:
pass
def test_parse_transaction_performance_large(exchange):
"""Large: ensure that parsing 1000 transactions runs within reasonable time (performance test)"""
batch = []
for i in range(1000):
tx = make_transaction(
id=i,
amount=str(1000000 * (i + 1)),
currency=make_currency(symbol="usdt", decimals=6),
params={"tx_id": f"txid_{i}"},
timestamp=1700000000000 + i * 1000
)
batch.append(tx)
start = time.time()
results = [exchange.parse_transaction(tx) for tx in batch] # 61.3μs -> 55.4μs (10.5% faster)
end = time.time()
codeflash_output is used to check that the output of the original code is the same as that of the optimized code.
#------------------------------------------------
import pytest
from ccxt.bitteam import bitteam
Instantiate the bitteam exchange for tests
exchange = bitteam()
-----------------------------
Basic Test Cases
-----------------------------
def test_basic_deposit_transaction():
# Test a typical deposit transaction
tx = {
"id": 1,
"orderId": None,
"transactionCoreId": "abc",
"userId": 2,
"recipient": "0xabc",
"sender": None,
"symbolId": 3,
"CommissionId": None,
"amount": "100000000",
"params": {"tx_id": "0x123"},
"reason": None,
"timestamp": 1700594180417,
"status": "success",
"statusDescription": None,
"type": "deposit",
"message": None,
"blockChain": "Ethereum",
"before": 0,
"after": 100000000,
"currency": {
"symbol": "usdt",
"decimals": 6,
"blockChain": "",
"links": [
{"tx": "https://etherscan.io/tx/", "address": "https://etherscan.io/address/", "blockChain": "Ethereum"}
]
}
}
codeflash_output = exchange.parse_transaction(tx); result = codeflash_output # 49.7μs -> 44.6μs (11.4% faster)
def test_basic_withdraw_transaction():
# Test a typical withdrawal transaction
tx = {
"id": "42",
"recipient": "0xdef",
"sender": "0xsender",
"amount": "500000",
"params": {"tx_id": "0x456"},
"timestamp": 1700594180417,
"status": "approving",
"type": "withdraw",
"currency": {"symbol": "eth", "decimals": 18}
}
codeflash_output = exchange.parse_transaction(tx); result = codeflash_output # 40.1μs -> 35.1μs (14.0% faster)
def test_basic_missing_optional_fields():
# Transaction missing optional fields
tx = {
"id": 99,
"amount": "123",
"params": {},
"timestamp": 1700594180417,
"status": "success",
"type": "deposit",
"currency": {"symbol": "btc", "decimals": 8}
}
codeflash_output = exchange.parse_transaction(tx); result = codeflash_output # 36.3μs -> 32.9μs (10.2% faster)
-----------------------------
Edge Test Cases
-----------------------------
def test_edge_zero_amount():
# Amount is zero
tx = {
"id": 2,
"amount": "0",
"params": {},
"timestamp": 1700594180417,
"status": "success",
"type": "deposit",
"currency": {"symbol": "usdt", "decimals": 6}
}
codeflash_output = exchange.parse_transaction(tx); result = codeflash_output # 35.7μs -> 31.2μs (14.5% faster)
def test_edge_negative_amount():
# Amount is negative
tx = {
"id": 3,
"amount": "-1000000",
"params": {},
"timestamp": 1700594180417,
"status": "success",
"type": "deposit",
"currency": {"symbol": "usdt", "decimals": 6}
}
codeflash_output = exchange.parse_transaction(tx); result = codeflash_output # 36.4μs -> 32.8μs (11.0% faster)
def test_edge_missing_currency():
# No currency object
tx = {
"id": 4,
"amount": "100",
"params": {},
"timestamp": 1700594180417,
"status": "success",
"type": "deposit"
}
codeflash_output = exchange.parse_transaction(tx); result = codeflash_output # 25.6μs -> 23.8μs (7.79% faster)
def test_edge_missing_amount():
# No amount field
tx = {
"id": 5,
"params": {},
"timestamp": 1700594180417,
"status": "success",
"type": "deposit",
"currency": {"symbol": "usdt", "decimals": 6}
}
codeflash_output = exchange.parse_transaction(tx); result = codeflash_output # 26.6μs -> 22.2μs (19.9% faster)
def test_edge_missing_decimals():
# No decimals field
tx = {
"id": 6,
"amount": "1000000",
"params": {},
"timestamp": 1700594180417,
"status": "success",
"type": "deposit",
"currency": {"symbol": "usdt"}
}
codeflash_output = exchange.parse_transaction(tx); result = codeflash_output # 27.2μs -> 22.5μs (21.1% faster)
def test_edge_missing_timestamp():
# No timestamp field
tx = {
"id": 8,
"amount": "1000000",
"params": {},
"status": "success",
"type": "deposit",
"currency": {"symbol": "usdt", "decimals": 6}
}
codeflash_output = exchange.parse_transaction(tx); result = codeflash_output # 39.3μs -> 33.5μs (17.4% faster)
def test_edge_invalid_status_and_type():
# Unknown status and type
tx = {
"id": 9,
"amount": "1000000",
"params": {},
"timestamp": 1700594180417,
"status": "unknown_status",
"type": "unknown_type",
"currency": {"symbol": "usdt", "decimals": 6}
}
codeflash_output = exchange.parse_transaction(tx); result = codeflash_output # 45.2μs -> 40.6μs (11.3% faster)
def test_edge_network_fallback():
# No blockChain field, but links[0].blockChain exists
tx = {
"id": 10,
"amount": "1000000",
"params": {},
"timestamp": 1700594180417,
"status": "success",
"type": "deposit",
"currency": {
"symbol": "usdt",
"decimals": 6,
"links": [
{"tx": "url", "address": "url", "blockChain": "Binance"}
]
}
}
codeflash_output = exchange.parse_transaction(tx); result = codeflash_output # 41.0μs -> 36.0μs (13.8% faster)
def test_edge_missing_links():
# No blockChain and no links
tx = {
"id": 11,
"amount": "1000000",
"params": {},
"timestamp": 1700594180417,
"status": "success",
"type": "deposit",
"currency": {
"symbol": "usdt",
"decimals": 6,
}
}
codeflash_output = exchange.parse_transaction(tx); result = codeflash_output # 37.6μs -> 32.3μs (16.2% faster)
def test_edge_comment_field():
# Description field present
tx = {
"id": 12,
"amount": "1000000",
"params": {},
"timestamp": 1700594180417,
"status": "success",
"type": "deposit",
"currency": {"symbol": "usdt", "decimals": 6},
"description": "This is a test comment"
}
codeflash_output = exchange.parse_transaction(tx); result = codeflash_output # 36.5μs -> 32.1μs (13.7% faster)
def test_edge_tag_field():
# Message field present
tx = {
"id": 13,
"amount": "1000000",
"params": {},
"timestamp": 1700594180417,
"status": "success",
"type": "deposit",
"currency": {"symbol": "usdt", "decimals": 6},
"message": "tag123"
}
codeflash_output = exchange.parse_transaction(tx); result = codeflash_output # 36.5μs -> 32.0μs (13.9% faster)
-----------------------------
Large Scale Test Cases
-----------------------------
def test_large_scale_many_transactions():
# Test with 1000 transactions
base_tx = {
"id": None,
"amount": "1000000",
"params": {"tx_id": "txid"},
"timestamp": 1700594180417,
"status": "success",
"type": "deposit",
"currency": {"symbol": "usdt", "decimals": 6}
}
for i in range(1000):
tx = dict(base_tx)
tx["id"] = str(i)
tx["params"] = {"tx_id": f"txid_{i}"}
codeflash_output = exchange.parse_transaction(tx); result = codeflash_output # 14.7ms -> 10.9ms (34.5% faster)
def test_large_scale_varied_decimals():
# Test with varied decimals
for decimals in range(0, 7):
tx = {
"id": "id",
"amount": "1000000",
"params": {},
"timestamp": 1700594180417,
"status": "success",
"type": "deposit",
"currency": {"symbol": "usdt", "decimals": decimals}
}
codeflash_output = exchange.parse_transaction(tx); result = codeflash_output # 151μs -> 125μs (20.4% faster)
expected = float("1000000") * float(exchange.parse_precision(str(decimals)))
def test_large_scale_varied_amounts():
# Test with varied amounts
for amount in ["1", "10", "100", "1000", "10000", "100000", "1000000"]:
tx = {
"id": "id",
"amount": amount,
"params": {},
"timestamp": 1700594180417,
"status": "success",
"type": "deposit",
"currency": {"symbol": "usdt", "decimals": 6}
}
codeflash_output = exchange.parse_transaction(tx); result = codeflash_output # 142μs -> 114μs (23.8% faster)
expected = float(amount) * 1e-6
def test_large_scale_stress_varied_fields():
# Stress test with varied missing fields
for i in range(100):
tx = {
"id": str(i),
"amount": str(i * 1000),
"params": {},
"timestamp": 1700594180417 + i,
"status": "success" if i % 2 == 0 else "approving",
"type": "deposit" if i % 2 == 0 else "withdraw",
"currency": {"symbol": "usdt", "decimals": 6}
}
codeflash_output = exchange.parse_transaction(tx); result = codeflash_output # 1.57ms -> 1.19ms (32.1% faster)
expected = float(tx['amount']) * 1e-6
codeflash_output is used to check that the output of the original code is the same as that of the optimized code.
To edit these changes
git checkout codeflash/optimize-bitteam.parse_transaction-mhuyocvkand push.