Skip to content

Conversation

@codeflash-ai
Copy link

@codeflash-ai codeflash-ai bot commented Nov 14, 2025

📄 29% (0.29x) speedup for bitmart.parse_deposit_withdraw_fee in python/ccxt/async_support/bitmart.py

⏱️ Runtime : 1.10 milliseconds 858 microseconds (best of 44 runs)

📝 Explanation and details

The optimization focuses on improving the safe_number method in the Exchange base class, which is a critical hot path called frequently during fee parsing operations.

Key Optimization: Fast-path dictionary access

The original safe_number method always called self.safe_string(obj, key) regardless of input type, which adds method call overhead. The optimized version adds a fast path for the most common case - when obj is a dictionary and the key exists:

# Fast path for common dict case to avoid method call overhead
if isinstance(obj, dict) and key in obj:
    value = obj[key]
    if value is None:
        return self.parse_number(value, defaultNumber)
    return self.parse_number(str(value), defaultNumber)

Why this optimization works:

  1. Eliminates method call overhead: Direct dictionary access obj[key] is faster than calling self.safe_string(obj, key) which has function call overhead and additional type checking
  2. Optimizes the common case: Most fee parsing operations work with dictionary objects, so this fast path is taken frequently
  3. Preserves exact behavior: Falls back to original safe_string method for non-dict objects or missing keys

Performance Impact:

The line profiler shows the optimization reduces safe_number execution time from 2.97ms to 2.11ms (28% faster). Test results demonstrate consistent 20-40% speedups across most test cases where the fee exists in the dictionary, with particularly strong gains (36-59% faster) for standard numeric fee values.

Cases with missing keys show slight slowdowns (5-12%) because they now do an extra isinstance check before falling back to the original path, but this is a reasonable trade-off given the substantial gains for the common case.

This optimization is especially valuable since safe_number is called in hot paths during fee parsing operations across many exchange implementations in the CCXT library.

Correctness verification report:

Test Status
⚙️ Existing Unit Tests 🔘 None Found
🌀 Generated Regression Tests 1191 Passed
⏪ Replay Tests 🔘 None Found
🔎 Concolic Coverage Tests 🔘 None Found
📊 Tests Coverage 100.0%
🌀 Generated Regression Tests and Runtime
import pytest
from ccxt.async_support.bitmart import bitmart

# --- Unit Tests ---

@pytest.fixture
def exchange():
    # Provide a fresh instance for each test
    return bitmart()

# -------------------------
# 1. Basic Test Cases
# -------------------------

def test_basic_fee_parsing(exchange):
    # Standard fee object
    fee_obj = {
        "today_available_withdraw_BTC": "100.0000",
        "min_withdraw": "0.005",
        "withdraw_precision": "8",
        "withdraw_fee": "0.0005"
    }
    codeflash_output = exchange.parse_deposit_withdraw_fee(fee_obj); result = codeflash_output # 3.99μs -> 2.90μs (37.7% faster)

def test_basic_fee_parsing_long_decimal(exchange):
    # Withdraw fee as a long decimal string
    fee_obj = {
        "withdraw_fee": "0.000500000000000000000000000000"
    }
    codeflash_output = exchange.parse_deposit_withdraw_fee(fee_obj); result = codeflash_output # 4.08μs -> 3.00μs (36.0% faster)

def test_basic_fee_parsing_zero_fee(exchange):
    # Withdraw fee is zero
    fee_obj = {
        "withdraw_fee": "0"
    }
    codeflash_output = exchange.parse_deposit_withdraw_fee(fee_obj); result = codeflash_output # 3.99μs -> 2.92μs (36.6% faster)

def test_basic_fee_parsing_missing_fee(exchange):
    # Withdraw fee key missing
    fee_obj = {
        "min_withdraw": "0.005"
    }
    codeflash_output = exchange.parse_deposit_withdraw_fee(fee_obj); result = codeflash_output # 3.27μs -> 3.47μs (5.57% slower)

def test_basic_fee_parsing_none_fee(exchange):
    # Withdraw fee is None
    fee_obj = {
        "withdraw_fee": None
    }
    codeflash_output = exchange.parse_deposit_withdraw_fee(fee_obj); result = codeflash_output # 2.72μs -> 1.71μs (59.1% faster)

def test_basic_fee_parsing_empty_string_fee(exchange):
    # Withdraw fee is empty string
    fee_obj = {
        "withdraw_fee": ""
    }
    codeflash_output = exchange.parse_deposit_withdraw_fee(fee_obj); result = codeflash_output # 2.90μs -> 3.63μs (20.2% slower)

def test_basic_fee_parsing_non_numeric_fee(exchange):
    # Withdraw fee is non-numeric string
    fee_obj = {
        "withdraw_fee": "not_a_number"
    }
    codeflash_output = exchange.parse_deposit_withdraw_fee(fee_obj); result = codeflash_output # 5.14μs -> 3.94μs (30.4% faster)

def test_basic_fee_parsing_extra_keys(exchange):
    # Extra irrelevant keys present
    fee_obj = {
        "withdraw_fee": "0.001",
        "foo": "bar",
        "baz": 123
    }
    codeflash_output = exchange.parse_deposit_withdraw_fee(fee_obj); result = codeflash_output # 3.79μs -> 2.74μs (38.1% faster)

# -------------------------
# 2. Edge Test Cases
# -------------------------

def test_edge_negative_fee(exchange):
    # Negative fee value
    fee_obj = {
        "withdraw_fee": "-0.001"
    }
    codeflash_output = exchange.parse_deposit_withdraw_fee(fee_obj); result = codeflash_output # 4.00μs -> 2.89μs (38.5% faster)

def test_edge_large_fee(exchange):
    # Very large fee value
    fee_obj = {
        "withdraw_fee": "123456789.123456789"
    }
    codeflash_output = exchange.parse_deposit_withdraw_fee(fee_obj); result = codeflash_output # 5.28μs -> 4.13μs (27.8% faster)

def test_edge_scientific_notation_fee(exchange):
    # Fee in scientific notation
    fee_obj = {
        "withdraw_fee": "1e-6"
    }
    codeflash_output = exchange.parse_deposit_withdraw_fee(fee_obj); result = codeflash_output # 3.99μs -> 2.97μs (34.3% faster)

def test_edge_fee_is_int(exchange):
    # Fee is integer type, not string
    fee_obj = {
        "withdraw_fee": 42
    }
    codeflash_output = exchange.parse_deposit_withdraw_fee(fee_obj); result = codeflash_output # 4.17μs -> 3.01μs (38.4% faster)

def test_edge_fee_is_float(exchange):
    # Fee is float type, not string
    fee_obj = {
        "withdraw_fee": 0.1234
    }
    codeflash_output = exchange.parse_deposit_withdraw_fee(fee_obj); result = codeflash_output # 6.06μs -> 4.64μs (30.6% faster)

def test_edge_fee_is_bool(exchange):
    # Fee is boolean type
    fee_obj = {
        "withdraw_fee": True
    }
    codeflash_output = exchange.parse_deposit_withdraw_fee(fee_obj); result = codeflash_output # 5.64μs -> 4.59μs (22.9% faster)

def test_edge_fee_is_list(exchange):
    # Fee is a list type
    fee_obj = {
        "withdraw_fee": [0.1]
    }
    codeflash_output = exchange.parse_deposit_withdraw_fee(fee_obj); result = codeflash_output # 8.37μs -> 7.32μs (14.4% faster)

def test_edge_fee_is_dict(exchange):
    # Fee is a dict type
    fee_obj = {
        "withdraw_fee": {"amount": 0.1}
    }
    codeflash_output = exchange.parse_deposit_withdraw_fee(fee_obj); result = codeflash_output # 9.01μs -> 7.67μs (17.3% faster)

def test_edge_fee_is_object(exchange):
    # Fee is a custom object
    class Dummy:
        def __str__(self):
            return "0.123"
    fee_obj = {
        "withdraw_fee": Dummy()
    }
    codeflash_output = exchange.parse_deposit_withdraw_fee(fee_obj); result = codeflash_output # 4.59μs -> 3.45μs (33.0% faster)

def test_edge_fee_is_bytes(exchange):
    # Fee is bytes
    fee_obj = {
        "withdraw_fee": b"0.456"
    }
    codeflash_output = exchange.parse_deposit_withdraw_fee(fee_obj); result = codeflash_output # 5.70μs -> 4.85μs (17.5% faster)

def test_edge_empty_fee_object(exchange):
    # Fee object is empty dict
    fee_obj = {}
    codeflash_output = exchange.parse_deposit_withdraw_fee(fee_obj); result = codeflash_output # 3.14μs -> 3.55μs (11.6% slower)

def test_edge_fee_key_is_none(exchange):
    # Fee key is None
    fee_obj = {None: "0.1"}
    codeflash_output = exchange.parse_deposit_withdraw_fee(fee_obj); result = codeflash_output # 3.14μs -> 3.57μs (12.0% slower)

def test_edge_fee_key_is_wrong_case(exchange):
    # Fee key is wrong case
    fee_obj = {
        "WITHDRAW_FEE": "0.1"
    }
    codeflash_output = exchange.parse_deposit_withdraw_fee(fee_obj); result = codeflash_output # 3.17μs -> 3.37μs (5.88% slower)

def test_edge_fee_key_is_int(exchange):
    # Fee key is integer
    fee_obj = {
        123: "0.1"
    }
    codeflash_output = exchange.parse_deposit_withdraw_fee(fee_obj); result = codeflash_output # 3.24μs -> 3.58μs (9.40% slower)

def test_edge_fee_key_is_float(exchange):
    # Fee key is float
    fee_obj = {
        1.23: "0.1"
    }
    codeflash_output = exchange.parse_deposit_withdraw_fee(fee_obj); result = codeflash_output # 3.23μs -> 3.41μs (5.17% slower)

def test_edge_fee_key_is_tuple(exchange):
    # Fee key is tuple
    fee_obj = {
        ('withdraw_fee',): "0.1"
    }
    codeflash_output = exchange.parse_deposit_withdraw_fee(fee_obj); result = codeflash_output # 3.25μs -> 3.44μs (5.41% slower)

def test_edge_fee_key_is_bytes(exchange):
    # Fee key is bytes
    fee_obj = {
        b"withdraw_fee": "0.1"
    }
    codeflash_output = exchange.parse_deposit_withdraw_fee(fee_obj); result = codeflash_output # 3.37μs -> 3.72μs (9.41% slower)

def test_edge_fee_key_is_list(exchange):
    # Fee key is list
    fee_obj = {
        ['withdraw_fee']: "0.1"
    }
    # Python dict can't have list keys, so skip this test

def test_edge_fee_is_inf(exchange):
    # Fee is infinity
    fee_obj = {
        "withdraw_fee": float('inf')
    }
    codeflash_output = exchange.parse_deposit_withdraw_fee(fee_obj); result = codeflash_output # 4.64μs -> 3.55μs (30.6% faster)

def test_edge_fee_is_nan(exchange):
    # Fee is NaN
    fee_obj = {
        "withdraw_fee": float('nan')
    }
    codeflash_output = exchange.parse_deposit_withdraw_fee(fee_obj); result = codeflash_output # 4.56μs -> 3.52μs (29.5% faster)
    # float('nan') == float('nan') is False, so use isnan
    import math

# -------------------------
# 3. Large Scale Test Cases
# -------------------------

def test_large_scale_many_fees(exchange):
    # Test parsing many fee objects in a loop
    num_items = 500
    fees = []
    for i in range(num_items):
        fees.append({"withdraw_fee": str(i * 0.001)})
    # Parse all and check results
    for i, fee_obj in enumerate(fees):
        codeflash_output = exchange.parse_deposit_withdraw_fee(fee_obj); result = codeflash_output # 407μs -> 288μs (41.1% faster)

def test_large_scale_varied_types(exchange):
    # Test a mix of types for withdraw_fee
    num_items = 300
    for i in range(num_items):
        if i % 5 == 0:
            fee_obj = {"withdraw_fee": str(i * 0.01)}
            expected = i * 0.01
        elif i % 5 == 1:
            fee_obj = {"withdraw_fee": i}
            expected = float(i)
        elif i % 5 == 2:
            fee_obj = {"withdraw_fee": None}
            expected = None
        elif i % 5 == 3:
            fee_obj = {"withdraw_fee": ""}
            expected = None
        else:
            fee_obj = {"withdraw_fee": "not_a_number"}
            expected = None
        codeflash_output = exchange.parse_deposit_withdraw_fee(fee_obj); result = codeflash_output # 259μs -> 201μs (28.8% faster)
        if expected is None:
            pass
        else:
            pass

def test_large_scale_extreme_values(exchange):
    # Test with very large and very small values
    fee_objs = [
        {"withdraw_fee": "1e-100"},
        {"withdraw_fee": "1e+100"},
        {"withdraw_fee": str(2**64)},
        {"withdraw_fee": str(-2**64)},
        {"withdraw_fee": "0.000000000000000000000000000001"},
        {"withdraw_fee": "999999999999999999999999999999.999999999999999999999999999999"},
    ]
    expected = [
        1e-100,
        1e+100,
        float(2**64),
        float(-2**64),
        1e-30,
        1e30,
    ]
    # Note: last value will be parsed as float, which may lose precision
    for fee_obj, exp in zip(fee_objs, expected):
        codeflash_output = exchange.parse_deposit_withdraw_fee(fee_obj); result = codeflash_output # 13.0μs -> 10.3μs (26.5% faster)

def test_large_scale_empty_and_missing(exchange):
    # Mix of empty dicts and missing keys
    num_items = 100
    for i in range(num_items):
        if i % 2 == 0:
            fee_obj = {}
        else:
            fee_obj = {"min_withdraw": "0.1"}
        codeflash_output = exchange.parse_deposit_withdraw_fee(fee_obj); result = codeflash_output # 84.3μs -> 85.3μs (1.09% slower)

def test_large_scale_info_integrity(exchange):
    # Ensure 'info' key always matches input
    num_items = 100
    for i in range(num_items):
        fee_obj = {"withdraw_fee": str(i)}
        codeflash_output = exchange.parse_deposit_withdraw_fee(fee_obj); result = codeflash_output # 83.9μs -> 58.6μs (43.2% faster)
# 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.async_support.bitmart import bitmart

# ----------------------------
# Unit tests for bitmart.parse_deposit_withdraw_fee
# ----------------------------

@pytest.fixture
def bitmart_instance():
    # Create a fresh instance for each test
    return bitmart()

# 1. Basic Test Cases

def test_basic_fee_parsing(bitmart_instance):
    # Standard input as per Bitmart docs
    fee = {
        "today_available_withdraw_BTC": "100.0000",
        "min_withdraw": "0.005",
        "withdraw_precision": "8",
        "withdraw_fee": "0.0005"
    }
    codeflash_output = bitmart_instance.parse_deposit_withdraw_fee(fee); result = codeflash_output # 4.12μs -> 2.99μs (38.1% faster)

def test_basic_fee_parsing_large_number(bitmart_instance):
    fee = {
        "withdraw_fee": "12345.6789"
    }
    codeflash_output = bitmart_instance.parse_deposit_withdraw_fee(fee); result = codeflash_output # 3.93μs -> 2.96μs (32.5% faster)

def test_basic_fee_parsing_zero_fee(bitmart_instance):
    fee = {
        "withdraw_fee": "0"
    }
    codeflash_output = bitmart_instance.parse_deposit_withdraw_fee(fee); result = codeflash_output # 3.97μs -> 2.84μs (39.9% faster)

def test_basic_fee_parsing_none_fee(bitmart_instance):
    fee = {
        "withdraw_fee": None
    }
    codeflash_output = bitmart_instance.parse_deposit_withdraw_fee(fee); result = codeflash_output # 2.79μs -> 1.78μs (56.7% faster)

def test_basic_fee_parsing_missing_fee_key(bitmart_instance):
    fee = {
        "min_withdraw": "0.005"
    }
    codeflash_output = bitmart_instance.parse_deposit_withdraw_fee(fee); result = codeflash_output # 3.18μs -> 3.44μs (7.52% slower)

# 2. Edge Test Cases

def test_fee_as_integer_string(bitmart_instance):
    fee = {
        "withdraw_fee": "42"
    }
    codeflash_output = bitmart_instance.parse_deposit_withdraw_fee(fee); result = codeflash_output # 4.05μs -> 2.95μs (37.3% faster)

def test_fee_as_float_string(bitmart_instance):
    fee = {
        "withdraw_fee": "0.000500000000000000000000000000"
    }
    codeflash_output = bitmart_instance.parse_deposit_withdraw_fee(fee); result = codeflash_output # 4.05μs -> 3.04μs (33.4% faster)

def test_fee_as_invalid_string(bitmart_instance):
    fee = {
        "withdraw_fee": "not_a_number"
    }
    codeflash_output = bitmart_instance.parse_deposit_withdraw_fee(fee); result = codeflash_output # 5.07μs -> 4.05μs (25.3% faster)

def test_fee_as_empty_string(bitmart_instance):
    fee = {
        "withdraw_fee": ""
    }
    codeflash_output = bitmart_instance.parse_deposit_withdraw_fee(fee); result = codeflash_output # 2.85μs -> 3.85μs (26.0% slower)

def test_fee_as_negative_number(bitmart_instance):
    fee = {
        "withdraw_fee": "-0.01"
    }
    codeflash_output = bitmart_instance.parse_deposit_withdraw_fee(fee); result = codeflash_output # 4.07μs -> 3.01μs (35.2% faster)

def test_fee_as_large_decimal(bitmart_instance):
    fee = {
        "withdraw_fee": "0.12345678901234567890"
    }
    codeflash_output = bitmart_instance.parse_deposit_withdraw_fee(fee); result = codeflash_output # 5.24μs -> 4.11μs (27.7% faster)

def test_fee_dict_with_extra_keys(bitmart_instance):
    fee = {
        "withdraw_fee": "0.0007",
        "extra_key": "extra_value",
        "another": 42
    }
    codeflash_output = bitmart_instance.parse_deposit_withdraw_fee(fee); result = codeflash_output # 3.95μs -> 2.93μs (34.9% faster)

def test_fee_dict_empty(bitmart_instance):
    fee = {}
    codeflash_output = bitmart_instance.parse_deposit_withdraw_fee(fee); result = codeflash_output # 3.20μs -> 3.56μs (10.1% slower)

def test_fee_dict_none(bitmart_instance):
    fee = None
    codeflash_output = bitmart_instance.parse_deposit_withdraw_fee(fee); result = codeflash_output # 2.37μs -> 2.64μs (10.2% slower)

def test_fee_dict_with_non_string_fee(bitmart_instance):
    fee = {
        "withdraw_fee": 0.0025
    }
    codeflash_output = bitmart_instance.parse_deposit_withdraw_fee(fee); result = codeflash_output # 5.79μs -> 4.68μs (23.7% faster)

def test_fee_dict_with_boolean_fee(bitmart_instance):
    fee = {
        "withdraw_fee": True
    }
    codeflash_output = bitmart_instance.parse_deposit_withdraw_fee(fee); result = codeflash_output # 5.85μs -> 4.74μs (23.5% faster)

def test_fee_dict_with_false_fee(bitmart_instance):
    fee = {
        "withdraw_fee": False
    }
    codeflash_output = bitmart_instance.parse_deposit_withdraw_fee(fee); result = codeflash_output # 5.58μs -> 4.66μs (19.8% faster)

def test_fee_dict_with_list_fee(bitmart_instance):
    fee = {
        "withdraw_fee": [0.01]
    }
    codeflash_output = bitmart_instance.parse_deposit_withdraw_fee(fee); result = codeflash_output # 8.30μs -> 7.39μs (12.3% faster)

def test_fee_dict_with_dict_fee(bitmart_instance):
    fee = {
        "withdraw_fee": {"amount": "0.01"}
    }
    codeflash_output = bitmart_instance.parse_deposit_withdraw_fee(fee); result = codeflash_output # 7.21μs -> 5.83μs (23.8% faster)

def test_fee_dict_with_multiple_fee_keys(bitmart_instance):
    fee = {
        "withdraw_fee": "0.001",
        "withdraw_fee2": "0.002"
    }
    codeflash_output = bitmart_instance.parse_deposit_withdraw_fee(fee); result = codeflash_output # 3.94μs -> 2.84μs (38.8% faster)

# 3. Large Scale Test Cases

def test_large_scale_fee_dict(bitmart_instance):
    # Test with a dict containing 1000 keys
    fee = {f"key_{i}": str(i) for i in range(1000)}
    fee["withdraw_fee"] = "0.123"
    codeflash_output = bitmart_instance.parse_deposit_withdraw_fee(fee); result = codeflash_output # 4.10μs -> 3.06μs (34.1% faster)

def test_large_scale_fee_dict_missing_fee(bitmart_instance):
    # Test with a dict containing 1000 keys but no withdraw_fee
    fee = {f"key_{i}": str(i) for i in range(1000)}
    codeflash_output = bitmart_instance.parse_deposit_withdraw_fee(fee); result = codeflash_output # 3.27μs -> 3.63μs (9.83% slower)

def test_large_scale_fee_dict_with_long_fee_string(bitmart_instance):
    # Test with a very long withdraw_fee string
    long_fee_str = "0." + "1" * 300
    fee = {"withdraw_fee": long_fee_str}
    codeflash_output = bitmart_instance.parse_deposit_withdraw_fee(fee); result = codeflash_output # 6.08μs -> 4.98μs (22.1% faster)

def test_large_scale_fee_dict_all_types(bitmart_instance):
    # Test with many keys, including withdraw_fee as different types
    fee = {f"key_{i}": i for i in range(999)}
    fee["withdraw_fee"] = "0.456"
    codeflash_output = bitmart_instance.parse_deposit_withdraw_fee(fee); result = codeflash_output # 4.27μs -> 3.10μs (37.9% faster)

def test_large_scale_fee_dict_with_fee_at_start(bitmart_instance):
    # Test with withdraw_fee as the first key
    fee = {"withdraw_fee": "0.789"}
    for i in range(1, 999):
        fee[f"key_{i}"] = i
    codeflash_output = bitmart_instance.parse_deposit_withdraw_fee(fee); result = codeflash_output # 4.05μs -> 3.04μs (33.3% faster)

def test_large_scale_fee_dict_with_fee_at_end(bitmart_instance):
    # Test with withdraw_fee as the last key
    fee = {f"key_{i}": i for i in range(999)}
    fee["withdraw_fee"] = "0.321"
    codeflash_output = bitmart_instance.parse_deposit_withdraw_fee(fee); result = codeflash_output # 4.22μs -> 3.05μs (38.3% faster)

# Additional edge: currency argument is ignored
def test_currency_argument_ignored(bitmart_instance):
    fee = {
        "withdraw_fee": "0.005"
    }
    codeflash_output = bitmart_instance.parse_deposit_withdraw_fee(fee, currency="BTC"); result = codeflash_output # 4.33μs -> 3.13μs (38.2% faster)

# Ensure mutation testing: if withdraw_fee is parsed incorrectly, these will fail
def test_mutation_failures(bitmart_instance):
    fee = {
        "withdraw_fee": "0.1"
    }
    codeflash_output = bitmart_instance.parse_deposit_withdraw_fee(fee); result = codeflash_output # 3.96μs -> 2.82μs (40.6% faster)
    fee2 = {
        "withdraw_fee": "abc"
    }
    codeflash_output = bitmart_instance.parse_deposit_withdraw_fee(fee2); result2 = codeflash_output # 2.81μs -> 2.48μs (13.2% faster)

# Confirm that deposit fee is always None
def test_deposit_fee_always_none(bitmart_instance):
    fee = {
        "deposit_fee": "0.01",
        "withdraw_fee": "0.02"
    }
    codeflash_output = bitmart_instance.parse_deposit_withdraw_fee(fee); result = codeflash_output # 3.77μs -> 2.79μs (35.2% faster)

# Confirm networks is always empty dict
def test_networks_is_empty_dict(bitmart_instance):
    fee = {
        "withdraw_fee": "0.01"
    }
    codeflash_output = bitmart_instance.parse_deposit_withdraw_fee(fee); result = codeflash_output # 3.99μs -> 2.76μs (44.3% faster)

# Confirm info is always the input fee dict
def test_info_is_input_dict(bitmart_instance):
    fee = {
        "withdraw_fee": "0.01"
    }
    codeflash_output = bitmart_instance.parse_deposit_withdraw_fee(fee); result = codeflash_output # 4.05μs -> 2.88μs (40.7% faster)
# 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-bitmart.parse_deposit_withdraw_fee-mhyzmbq6 and push.

Codeflash Static Badge

The optimization focuses on improving the `safe_number` method in the Exchange base class, which is a critical hot path called frequently during fee parsing operations.

**Key Optimization: Fast-path dictionary access**

The original `safe_number` method always called `self.safe_string(obj, key)` regardless of input type, which adds method call overhead. The optimized version adds a fast path for the most common case - when `obj` is a dictionary and the key exists:

```python
# Fast path for common dict case to avoid method call overhead
if isinstance(obj, dict) and key in obj:
    value = obj[key]
    if value is None:
        return self.parse_number(value, defaultNumber)
    return self.parse_number(str(value), defaultNumber)
```

**Why this optimization works:**

1. **Eliminates method call overhead**: Direct dictionary access `obj[key]` is faster than calling `self.safe_string(obj, key)` which has function call overhead and additional type checking
2. **Optimizes the common case**: Most fee parsing operations work with dictionary objects, so this fast path is taken frequently
3. **Preserves exact behavior**: Falls back to original `safe_string` method for non-dict objects or missing keys

**Performance Impact:**

The line profiler shows the optimization reduces `safe_number` execution time from 2.97ms to 2.11ms (28% faster). Test results demonstrate consistent 20-40% speedups across most test cases where the fee exists in the dictionary, with particularly strong gains (36-59% faster) for standard numeric fee values.

Cases with missing keys show slight slowdowns (5-12%) because they now do an extra `isinstance` check before falling back to the original path, but this is a reasonable trade-off given the substantial gains for the common case.

This optimization is especially valuable since `safe_number` is called in hot paths during fee parsing operations across many exchange implementations in the CCXT library.
@codeflash-ai codeflash-ai bot requested a review from mashraf-222 November 14, 2025 15:03
@codeflash-ai codeflash-ai bot added ⚡️ codeflash Optimization PR opened by Codeflash AI 🎯 Quality: Medium Optimization Quality according to Codeflash labels Nov 14, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

⚡️ codeflash Optimization PR opened by Codeflash AI 🎯 Quality: Medium Optimization Quality according to Codeflash

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant