Skip to content

Conversation

@codeflash-ai
Copy link

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

📄 153% (1.53x) speedup for bitmart.get_currency_id_from_code_and_network in python/ccxt/async_support/bitmart.py

⏱️ Runtime : 1.19 milliseconds 472 microseconds (best of 5 runs)

📝 Explanation and details

The optimized code achieves a 153% speedup by eliminating expensive operations and reducing function call overhead in critical paths:

Key Optimizations Applied

1. Eliminated List Creation in currency() Method

  • Original: Created list(self.currencies.keys()) and called len() on every invocation (41% of runtime)
  • Optimized: Direct dictionary membership check with if not self.currencies:
  • Impact: Converts O(n) list creation to O(1) dictionary check

2. Streamlined Safe Dictionary Operations

  • Original: safe_dict() called nested safe_dict_n() which performed complex type checking
  • Optimized: Direct dict.get() with inline type validation for guaranteed dictionary types
  • Impact: Reduces function call overhead by ~60% in safe operations

3. Fast-Path Optimization in safe_string() and safe_value()

  • Original: Always called Exchange.key_exists() which handles edge cases for lists/strings
  • Optimized: Direct dictionary membership check when type is known to be dict
  • Impact: Eliminates redundant type checking in the common case

4. Reduced Attribute Access in default_network_code()

  • Original: Multiple self.safe_string() calls and repeated options access
  • Optimized: Single options.get() call with direct fallback
  • Impact: Cuts method call overhead by avoiding safe_string wrapper

5. Iterator Optimization for Network Selection

  • Original: list(networks.keys()) then index access
  • Optimized: next(iter(networks)) for first key retrieval
  • Impact: Avoids list creation when only first element needed

Performance Benefits by Test Case

The optimizations show strongest gains (100-250% speedup) in scenarios with:

  • Multiple network lookups: Direct dict access vs. list creation
  • Large-scale operations: 500+ currencies benefit most from O(1) vs O(n) improvements
  • Default network resolution: Reduced function call chains

Moderate gains (60-90% speedup) occur in:

  • Single network operations: Still benefit from reduced overhead
  • Edge cases with missing data: Faster fallback paths

The optimization maintains full compatibility while dramatically improving performance in this cryptocurrency exchange library's core currency resolution logic.

Correctness verification report:

Test Status
⚙️ Existing Unit Tests 🔘 None Found
🌀 Generated Regression Tests 325 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


# Minimal stub for bitmart and dependencies, only what's needed for testing
class ExchangeError(Exception):
    pass
from ccxt.async_support.bitmart import bitmart

# ------------------- UNIT TESTS START HERE -------------------

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

# ------------------- BASIC TEST CASES -------------------

def test_basic_single_network(bitmart_instance):
    # Test with a currency that has a single network, networkCode provided
    bitmart_instance.currencies = {
        'USDT': {
            'id': 'usdt',
            'networks': {
                'ERC20': {'info': {'currency': 'usdt-erc20'}},
            }
        }
    }
    codeflash_output = bitmart_instance.get_currency_id_from_code_and_network('USDT', 'ERC20') # 7.89μs -> 3.99μs (97.7% faster)

def test_basic_single_network_no_network_code(bitmart_instance):
    # Test with a currency that has a single network, networkCode not provided
    bitmart_instance.currencies = {
        'USDT': {
            'id': 'usdt',
            'networks': {
                'ERC20': {'info': {'currency': 'usdt-erc20'}},
            }
        }
    }
    # Should fallback to the only network
    codeflash_output = bitmart_instance.get_currency_id_from_code_and_network('USDT', None) # 10.3μs -> 6.39μs (61.2% faster)

def test_basic_multiple_networks_with_network_code(bitmart_instance):
    # Test with a currency that has multiple networks, networkCode provided
    bitmart_instance.currencies = {
        'USDT': {
            'id': 'usdt',
            'networks': {
                'ERC20': {'info': {'currency': 'usdt-erc20'}},
                'TRC20': {'info': {'currency': 'usdt-trc20'}},
            }
        }
    }
    codeflash_output = bitmart_instance.get_currency_id_from_code_and_network('USDT', 'TRC20') # 8.11μs -> 3.94μs (106% faster)
    codeflash_output = bitmart_instance.get_currency_id_from_code_and_network('USDT', 'ERC20') # 3.26μs -> 1.46μs (124% faster)

def test_basic_multiple_networks_no_network_code(bitmart_instance):
    # Test with a currency that has multiple networks, no networkCode provided
    bitmart_instance.currencies = {
        'USDT': {
            'id': 'usdt',
            'networks': {
                'ERC20': {'info': {'currency': 'usdt-erc20'}},
                'TRC20': {'info': {'currency': 'usdt-trc20'}},
            }
        }
    }
    # Should fallback to first network (sorted order not guaranteed, but only one will be returned)
    codeflash_output = bitmart_instance.get_currency_id_from_code_and_network('USDT', None); result = codeflash_output # 9.37μs -> 5.01μs (87.1% faster)

def test_basic_default_network_in_options(bitmart_instance):
    # Test with default network in options['defaultNetworks']
    bitmart_instance.currencies = {
        'USDT': {
            'id': 'usdt',
            'networks': {
                'ERC20': {'info': {'currency': 'usdt-erc20'}},
                'TRC20': {'info': {'currency': 'usdt-trc20'}},
            }
        }
    }
    bitmart_instance.options['defaultNetworks'] = {'USDT': 'TRC20'}
    codeflash_output = bitmart_instance.get_currency_id_from_code_and_network('USDT', None) # 8.82μs -> 4.83μs (82.7% faster)

def test_basic_default_network_global(bitmart_instance):
    # Test with default network in options['defaultNetwork']
    bitmart_instance.currencies = {
        'USDT': {
            'id': 'usdt',
            'networks': {
                'ERC20': {'info': {'currency': 'usdt-erc20'}},
                'TRC20': {'info': {'currency': 'usdt-trc20'}},
            }
        }
    }
    bitmart_instance.options['defaultNetworks'] = {}  # clear
    bitmart_instance.options['defaultNetwork'] = 'ERC20'
    codeflash_output = bitmart_instance.get_currency_id_from_code_and_network('USDT', None) # 10.1μs -> 5.24μs (93.4% faster)

def test_basic_network_code_not_found(bitmart_instance):
    # Test with a network code that doesn't exist for the currency
    bitmart_instance.currencies = {
        'USDT': {
            'id': 'usdt',
            'networks': {
                'ERC20': {'info': {'currency': 'usdt-erc20'}},
            }
        }
    }
    # Should fall back to id + '-' + networkCode
    codeflash_output = bitmart_instance.get_currency_id_from_code_and_network('USDT', 'TRC20') # 9.48μs -> 5.54μs (71.2% faster)

def test_basic_network_code_to_id_mapping(bitmart_instance):
    # Test with a mapping in options['networks']
    bitmart_instance.currencies = {
        'USDT': {
            'id': 'usdt',
            'networks': {
                'ERC20': {'info': {'currency': 'usdt-erc20'}},
            }
        }
    }
    bitmart_instance.options['networks'] = {'TRC20': 'trc20id'}
    # Should use id + '-' + network id from mapping
    codeflash_output = bitmart_instance.get_currency_id_from_code_and_network('USDT', 'TRC20') # 8.71μs -> 5.08μs (71.6% faster)

# ------------------- EDGE TEST CASES -------------------


def test_edge_networks_empty_dict(bitmart_instance):
    # Currency exists but networks is empty
    bitmart_instance.currencies = {
        'BTC': {
            'id': 'btc',
            'networks': {}
        }
    }
    # Should return the id, since no network info is available
    codeflash_output = bitmart_instance.get_currency_id_from_code_and_network('BTC', None) # 10.9μs -> 6.35μs (72.4% faster)
    codeflash_output = bitmart_instance.get_currency_id_from_code_and_network('BTC', 'ERC20') # 4.02μs -> 1.93μs (109% faster)

def test_edge_network_info_missing(bitmart_instance):
    # Network exists but 'info' missing
    bitmart_instance.currencies = {
        'ETH': {
            'id': 'eth',
            'networks': {
                'ERC20': {},  # No 'info'
            }
        }
    }
    # Should return id, since info/currency is missing
    codeflash_output = bitmart_instance.get_currency_id_from_code_and_network('ETH', 'ERC20') # 8.14μs -> 3.65μs (123% faster)

def test_edge_network_currency_field_missing(bitmart_instance):
    # Network info exists but 'currency' field missing
    bitmart_instance.currencies = {
        'ETH': {
            'id': 'eth',
            'networks': {
                'ERC20': {'info': {}},
            }
        }
    }
    codeflash_output = bitmart_instance.get_currency_id_from_code_and_network('ETH', 'ERC20') # 8.03μs -> 3.58μs (124% faster)

def test_edge_network_code_is_same_as_currency_code(bitmart_instance):
    # Network code is the same as currency code
    bitmart_instance.currencies = {
        'BTC': {
            'id': 'btc',
            'networks': {
                'BTC': {'info': {'currency': 'btc-btc'}},
                'BRC20': {'info': {'currency': 'btc-brc20'}},
            }
        }
    }
    # Should pick the 'BTC' network if code is None
    codeflash_output = bitmart_instance.get_currency_id_from_code_and_network('BTC', None) # 9.26μs -> 5.19μs (78.4% faster)

def test_edge_network_code_case_sensitivity(bitmart_instance):
    # Network code case sensitivity
    bitmart_instance.currencies = {
        'USDT': {
            'id': 'usdt',
            'networks': {
                'erc20': {'info': {'currency': 'usdt-erc20-lower'}},
                'ERC20': {'info': {'currency': 'usdt-erc20-upper'}},
            }
        }
    }
    # Should match exactly, not case-insensitive
    codeflash_output = bitmart_instance.get_currency_id_from_code_and_network('USDT', 'erc20') # 7.94μs -> 3.98μs (99.6% faster)
    codeflash_output = bitmart_instance.get_currency_id_from_code_and_network('USDT', 'ERC20') # 3.35μs -> 1.47μs (128% faster)

def test_edge_network_code_to_id_with_replacement(bitmart_instance):
    # Test defaultNetworkCodeReplacements logic
    bitmart_instance.currencies = {
        'ETH': {
            'id': 'eth',
            'networks': {
                'ERC20': {'info': {'currency': 'eth-erc20'}},
            }
        }
    }
    bitmart_instance.options['networks'] = {'ERC20': 'erc20id'}
    # Should use replacement mapping for 'ETH' and 'ERC20'
    codeflash_output = bitmart_instance.get_currency_id_from_code_and_network('ETH', 'ETH') # 11.8μs -> 5.93μs (98.6% faster)

def test_edge_network_code_to_id_with_replacement_fallback(bitmart_instance):
    # Test replacement logic fallback to networkCode if mapping not found
    bitmart_instance.currencies = {
        'CRO': {
            'id': 'cro',
            'networks': {
                'CRC20': {'info': {'currency': 'cro-crc20'}},
            }
        }
    }
    # No mapping in options['networks']
    codeflash_output = bitmart_instance.get_currency_id_from_code_and_network('CRO', 'CRONOS') # 11.7μs -> 5.80μs (102% faster)


def test_edge_networks_is_none(bitmart_instance):
    # Test when networks is None
    bitmart_instance.currencies = {
        'USDT': {
            'id': 'usdt',
            'networks': None
        }
    }
    # Should return id or id-networkCode
    codeflash_output = bitmart_instance.get_currency_id_from_code_and_network('USDT', None) # 10.5μs -> 6.42μs (63.2% faster)
    codeflash_output = bitmart_instance.get_currency_id_from_code_and_network('USDT', 'ERC20') # 3.26μs -> 1.81μs (80.2% faster)

def test_edge_networks_is_missing(bitmart_instance):
    # Test when networks key is missing
    bitmart_instance.currencies = {
        'USDT': {
            'id': 'usdt'
        }
    }
    # Should return id or id-networkCode
    codeflash_output = bitmart_instance.get_currency_id_from_code_and_network('USDT', None) # 10.5μs -> 6.63μs (57.7% faster)
    codeflash_output = bitmart_instance.get_currency_id_from_code_and_network('USDT', 'ERC20') # 3.46μs -> 1.61μs (115% faster)

# ------------------- LARGE SCALE TEST CASES -------------------

def test_large_many_currencies_and_networks(bitmart_instance):
    # Test with 500 currencies, each with 2 networks
    currencies = {}
    for i in range(500):
        code = f'CUR{i}'
        currencies[code] = {
            'id': f'curid{i}',
            'networks': {
                'NETA': {'info': {'currency': f'curid{i}-neta'}},
                'NETB': {'info': {'currency': f'curid{i}-netb'}},
            }
        }
    bitmart_instance.currencies = currencies
    # Test random spot
    codeflash_output = bitmart_instance.get_currency_id_from_code_and_network('CUR123', 'NETA') # 12.8μs -> 5.28μs (142% faster)
    codeflash_output = bitmart_instance.get_currency_id_from_code_and_network('CUR456', 'NETB') # 5.68μs -> 1.58μs (258% faster)
    # Test fallback to first network
    codeflash_output = bitmart_instance.get_currency_id_from_code_and_network('CUR321', None); result = codeflash_output # 9.61μs -> 4.15μs (132% faster)

def test_large_many_networks_per_currency(bitmart_instance):
    # Test with 1 currency, 1000 networks
    networks = {}
    for i in range(1000):
        networks[f'NET{i}'] = {'info': {'currency': f'usdt-net{i}'}}
    bitmart_instance.currencies = {
        'USDT': {
            'id': 'usdt',
            'networks': networks
        }
    }
    # Test a few
    codeflash_output = bitmart_instance.get_currency_id_from_code_and_network('USDT', 'NET0') # 9.59μs -> 5.19μs (85.0% faster)
    codeflash_output = bitmart_instance.get_currency_id_from_code_and_network('USDT', 'NET999') # 3.72μs -> 1.72μs (116% faster)
    # Fallback to first network
    codeflash_output = bitmart_instance.get_currency_id_from_code_and_network('USDT', None); result = codeflash_output # 6.16μs -> 4.45μs (38.3% faster)

def test_large_options_networks_mapping(bitmart_instance):
    # Test with options['networks'] mapping for 1000 networks
    bitmart_instance.currencies = {
        'FOO': {
            'id': 'foo',
            'networks': {
                'BAR': {'info': {'currency': 'foo-bar'}},
            }
        }
    }
    bitmart_instance.options['networks'] = {f'NET{i}': f'netid{i}' for i in range(1000)}
    # Should use id + '-' + mapped id
    codeflash_output = bitmart_instance.get_currency_id_from_code_and_network('FOO', 'NET500') # 9.62μs -> 5.65μs (70.3% faster)

def test_large_default_networks(bitmart_instance):
    # Test with 100 currencies, each with its own default network in options['defaultNetworks']
    currencies = {}
    defaultNetworks = {}
    for i in range(100):
        code = f'CUR{i}'
        net = f'NET{i}'
        currencies[code] = {
            'id': f'curid{i}',
            'networks': {
                net: {'info': {'currency': f'curid{i}-{net.lower()}'}},
                'OTHER': {'info': {'currency': f'curid{i}-other'}},
            }
        }
        defaultNetworks[code] = net
    bitmart_instance.currencies = currencies
    bitmart_instance.options['defaultNetworks'] = defaultNetworks
    # Should pick the default network for each
    for i in range(100):
        code = f'CUR{i}'
        net = f'NET{i}'
        codeflash_output = bitmart_instance.get_currency_id_from_code_and_network(code, None) # 353μs -> 137μs (157% faster)

def test_large_missing_networks_and_ids(bitmart_instance):
    # 100 currencies, half with missing networks, half with missing info
    currencies = {}
    for i in range(50):
        code = f'CUR{i}'
        currencies[code] = {
            'id': f'curid{i}',
            # Missing networks
        }
    for i in range(50, 100):
        code = f'CUR{i}'
        currencies[code] = {
            'id': f'curid{i}',
            'networks': {
                'NET': {}  # info missing
            }
        }
    bitmart_instance.currencies = currencies
    # Should return id for all
    for i in range(100):
        code = f'CUR{i}'
        codeflash_output = bitmart_instance.get_currency_id_from_code_and_network(code, None) # 400μs -> 145μs (175% 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

# --- Minimal implementation of bitmart and dependencies for testing ---

class ExchangeError(Exception):
    pass
from ccxt.async_support.bitmart import bitmart

# --- Unit tests ---

@pytest.fixture
def exchange():
    return bitmart()

# 1. Basic Test Cases

















def test_large_number_of_networks(exchange):
    # Add a currency with 999 networks
    large_networks = {}
    for i in range(999):
        large_networks[f'NET{i}'] = {'info': {'currency': f'BIG-{i}'}}
    exchange.currencies['BIG'] = {'id': 'BIG', 'networks': large_networks}
    # Should be able to retrieve the correct currency id for any network
    for i in range(0, 999, 100):  # test a subset for speed
        codeflash_output = exchange.get_currency_id_from_code_and_network('BIG', f'NET{i}') # 32.2μs -> 14.7μs (119% faster)

def test_large_number_of_currencies(exchange):
    # Add 500 currencies, each with 2 networks
    for i in range(500):
        code = f'CUR{i}'
        exchange.currencies[code] = {
            'id': code,
            'networks': {
                'A': {'info': {'currency': f'{code}-A'}},
                'B': {'info': {'currency': f'{code}-B'}},
            }
        }
    # Test a subset for speed
    for i in range(0, 500, 50):
        code = f'CUR{i}'
        codeflash_output = exchange.get_currency_id_from_code_and_network(code, 'A') # 52.9μs -> 14.6μs (262% faster)
        codeflash_output = exchange.get_currency_id_from_code_and_network(code, 'B')

def test_performance_large_scale(exchange):
    # Add 500 currencies, each with 2 networks
    for i in range(500):
        code = f'CURX{i}'
        exchange.currencies[code] = {
            'id': code,
            'networks': {
                'X': {'info': {'currency': f'{code}-X'}},
                'Y': {'info': {'currency': f'{code}-Y'}},
            }
        }
    # Should complete quickly for random lookups
    for i in range(0, 500, 100):
        code = f'CURX{i}'
        codeflash_output = exchange.get_currency_id_from_code_and_network(code, 'X') # 30.4μs -> 9.24μs (229% faster)
        codeflash_output = exchange.get_currency_id_from_code_and_network(code, 'Y')

# Additional edge: networkCode=None, but currencyCode matches a network key

def test_none_network_code_currency_code_matches_network(exchange):
    # Add a currency where the code matches a network key
    exchange.currencies['MATCH'] = {
        'id': 'MATCH',
        'networks': {
            'MATCH': {'info': {'currency': 'MATCH-COIN'}},
            'OTHER': {'info': {'currency': 'MATCH-OTHER'}},
        }
    }
    # Should pick the network with key 'MATCH'
    codeflash_output = exchange.get_currency_id_from_code_and_network('MATCH', None) # 10.4μs -> 5.31μs (96.0% faster)

# Additional: If networkCode is None and no networks, fallback to id

def test_none_network_code_no_networks(exchange):
    exchange.currencies['EMPTY'] = {'id': 'EMPTY', 'networks': {}}
    codeflash_output = exchange.get_currency_id_from_code_and_network('EMPTY', None) # 10.6μs -> 5.08μs (108% 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.get_currency_id_from_code_and_network-mhyyvxz7 and push.

Codeflash

The optimized code achieves a **153% speedup** by eliminating expensive operations and reducing function call overhead in critical paths:

## Key Optimizations Applied

**1. Eliminated List Creation in `currency()` Method**
- **Original**: Created `list(self.currencies.keys())` and called `len()` on every invocation (41% of runtime)
- **Optimized**: Direct dictionary membership check with `if not self.currencies:`
- **Impact**: Converts O(n) list creation to O(1) dictionary check

**2. Streamlined Safe Dictionary Operations**
- **Original**: `safe_dict()` called nested `safe_dict_n()` which performed complex type checking
- **Optimized**: Direct `dict.get()` with inline type validation for guaranteed dictionary types
- **Impact**: Reduces function call overhead by ~60% in safe operations

**3. Fast-Path Optimization in `safe_string()` and `safe_value()`**
- **Original**: Always called `Exchange.key_exists()` which handles edge cases for lists/strings
- **Optimized**: Direct dictionary membership check when type is known to be dict
- **Impact**: Eliminates redundant type checking in the common case

**4. Reduced Attribute Access in `default_network_code()`**
- **Original**: Multiple `self.safe_string()` calls and repeated options access
- **Optimized**: Single `options.get()` call with direct fallback
- **Impact**: Cuts method call overhead by avoiding safe_string wrapper

**5. Iterator Optimization for Network Selection**
- **Original**: `list(networks.keys())` then index access
- **Optimized**: `next(iter(networks))` for first key retrieval
- **Impact**: Avoids list creation when only first element needed

## Performance Benefits by Test Case

The optimizations show **strongest gains** (100-250% speedup) in scenarios with:
- **Multiple network lookups**: Direct dict access vs. list creation
- **Large-scale operations**: 500+ currencies benefit most from O(1) vs O(n) improvements  
- **Default network resolution**: Reduced function call chains

**Moderate gains** (60-90% speedup) occur in:
- **Single network operations**: Still benefit from reduced overhead
- **Edge cases with missing data**: Faster fallback paths

The optimization maintains full compatibility while dramatically improving performance in this cryptocurrency exchange library's core currency resolution logic.
@codeflash-ai codeflash-ai bot requested a review from mashraf-222 November 14, 2025 14:42
@codeflash-ai codeflash-ai bot added the ⚡️ codeflash Optimization PR opened by Codeflash AI label 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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant