8000 fix(php): is_associative fix by ttodua · Pull Request #26277 · ccxt/ccxt · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

fix(php): is_associative fix #26277

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

Merged
merged 3 commits into from
Jun 23, 2025
Merged

Conversation

ttodua
Copy link
Member
@ttodua ttodua commented Jun 22, 2025

I've started checking efficiency of some methods (I will also go through lib's other places too a bit later).
at this moment, I only touched is_associative and deep_extend implementations in php.

To test it on your side, please run this script. it shows around 10-15x performance improvement.

the first class Original includes our existing implementations, while class Optimized includes the new approach.

<?php



class Original {
    public static function is_associative($array) {
        return is_array($array) && (count(array_filter(array_keys($array), 'is_string')) > 0);
    }

    public static function deep_extend() {
        $out = null;
        $args = func_get_args();
        foreach ($args as $arg) {
            if (static::is_associative($arg) || (is_array($arg) && (count($arg) === 0))) {
                if (!static::is_associative($out)) {
                    $out = array();
                }
                foreach ($arg as $k => $v) {
                    $out[$k] = static::de
8000
ep_extend(isset($out[$k]) ? $out[$k] : array(), $v);
                }
            } else {
                $out = $arg;
            }
        }
        return $out;
    }
}

class Optimized {
    public static function is_associative($array) {
        return is_array($array) && !array_is_list($array);
    }

    public static function deep_extend() {
        $out = null;
        $args = func_get_args();

        foreach ($args as $arg) {
            if (is_array($arg)) {
                if (empty($arg) || !array_is_list($arg)) {
                    // It's associative or empty
                    if (!is_array($out) || array_is_list($out)) {
                        $out = [];
                    }
                    foreach ($arg as $k => $v) {
                        $out[$k] = isset($out[$k]) && is_array($out[$k]) && is_array($v) && 
                                  (empty($v) || !array_is_list($v)) && (empty($out[$k]) || !array_is_list($out[$k]))
                            ? static::deep_extend($out[$k], $v)
                            : $v;
                    }
                } else {
                    $out = $arg;
                }
            } else {
                $out = $arg;
            }
        }
        return $out;
    }
}


// Generate test data - 3-dimensional arrays 
function generateTestArray($size = 14) {
    $arr = [];

    for ($i = 0; $i < $size; $i++) {
        $level1_key = "level1_" . $i;
        $arr[$level1_key] = [];

        for ($j = 0; $j < min($size, 3); $j++) {
            $level2_key = "level2_" . $j;
            $arr[$level1_key][$level2_key] = [];

            for ($k = 0; $k < min($size, 3); $k++) {
                $level3_key = "level3_" . $k;
                $arr[$level1_key][$level2_key][$level3_key] = "value_" . $i . "_" . $j . "_" . $k;
            }
        }
    }

    return $arr;
}


function generateConflictingArray($size = 10) {
    $arr = [];

    for ($i = 0; $i < $size; $i++) {
        $level1_key = "level1_" . ($i % 10); // Some overlap with first array
        $arr[$level1_key] = [];

        for ($j = 0; $j < min($size, 2); $j++) {
            $level2_key = "level2_" . ($j % 25);
            $arr[$level1_key][$level2_key] = [];

            for ($k = 0; $k < min($size, 2); $k++) {
                $level3_key = "level3_" . ($k % 15);
                $arr[$level1_key][$level2_key][$level3_key] = "updated_" . $i . "_" . $j . "_" . $k;
            }
        }
    }

    return $arr;
}




// Benchmark function
function benchmark($iterations = 10000) {
    $first = generateTestArray();
    $second = generateConflictingArray();

    // Benchmark original version
    $start = microtime(true);
    for ($i = 0; $i < $iterations; $i++) {
        $result = Original::deep_extend($first, $second);
    }
    $originalTime = microtime(true) - $start;
    echo "Original time: " . number_format($originalTime, 4) . " seconds\n";

    // Benchmark optimized version
    $start = microtime(true);
    for ($i = 0; $i < $iterations; $i++) {
        $result = Optimized::deep_extend($first, $second);
    }
    $optimizedTime = microtime(true) - $start;

    echo "Optimized time: " . number_format($optimizedTime, 4) . " seconds\n";

    // Verify results are identical
    $result1 = Original::deep_extend($first, $second);
    $result2 = Optimized::deep_extend($first, $second);

    echo "\nResults identical: " . ($result1 === $result2 ? "✅ YES" : "❌ NO") . "\n";
}


benchmark();

@ttodua ttodua marked this pull request as ready for review June 22, 2025 11:20
@carlosmiei carlosmiei merged commit e407c36 into ccxt:master Jun 23, 2025
10 of 11 checks passed
@carlosmiei carlosmiei deleted the php-deep-extend-optimize branch June 23, 2025 07:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants
0