Skip to content
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

Reduce memory per shm string by 8 bytes #465

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

TysonAndre
Copy link
Contributor

Related to #323

This slightly helps performance of apc.serializer=default when there are lots of small strings to unpersist. (and reduces size of serialized data (and cache entry keys) by 8 bytes with other serializers (16 bytes per entry))

With APCu's current design and eviction always being a possibility, strings must always be copied.
(zval flags could be used to check the type if that stopped being the case)

For example, fetching a large array mapping small strings to small strings (CPU running at 2.5GHz):

Before: bench_apcu_fetch_large_config: numValues=     65536
repetitions=       256 elapsed=3.010 shared memory=   9381144
After: bench_apcu_fetch_large_config: numValues=     65536
repetitions=       256 elapsed=2.980 shared memory=   8332560
Benchmark source code (click to expand)
<?php // bench_fetch_large_config.php

printf(
    "%s Results for php %s debug=%s with opcache enabled=%s, apc.serializer=%s\n\n",
    basename(__FILE__),
    PHP_VERSION,
    json_encode(PHP_DEBUG),
    json_encode(function_exists('opcache_get_status') && (opcache_get_status(false)['opcache_enabled'] ?? false)),
    ini_get('apc.serializer')
);

function bench_apcu_fetch_large_config(int $numValues, int $repetitions) {
    $values = [];
    srand(1234);
    apcu_clear_cache();
    for ($i = 0; $i < $numValues; $i++) {
        $values["key" . rand(0, PHP_INT_MAX)] = "value" . rand(0, PHP_INT_MAX);
    }
    if (!apcu_store('config_key', $values)) {
        throw new Exception("Failed to set config_key");
    }
    $expected = count($values);
    $start = hrtime(true);
    for ($i = 0; $i < $repetitions; $i++) {
        $v = apcu_fetch('config_key');
        if (count($v) !== $expected) {
            throw new RuntimeException("Failed to load config");
        }
    }
    $end = hrtime(true);
    printf("%s: numValues=%10d repetitions=%10d elapsed=%.3f shared memory=%10d\n", __FUNCTION__, $numValues, $repetitions, ($end - $start)/1e9, (int)apcu_cache_info()['mem_size']);
}

$settings = [
    [2**16, 2**8],
    [2**12, 2**12],
    [2**8,  2**16],
    [2**3,  2**21],
    [1,     2**22],
];
for ($i = 0; $i < 2; $i++) {
    foreach ($settings as [$n, $repetitions]) {
        bench_apcu_fetch_large_config($n, $repetitions);
    }
}

@TysonAndre TysonAndre force-pushed the reduce-string-memory-usage branch from 4b09a14 to 4c7b0b5 Compare November 5, 2022 21:03
Related to krakjoe#323

This slightly helps performance of `apc.serializer=default`
when there are lots of small strings to unpersist.
(and reduces size of serialized data by 8 bytes with other serializers)

With APCu's current design and eviction always being a possibility,
strings must always be copied.
(zval flags could be used to check the type if that stopped being the case)

For example, fetching an array mapping small strings to small strings:

	Before: bench_apcu_fetch_large_config: numValues=     65536
	repetitions=       256 elapsed=3.010 shared memory=   9381144
	After: bench_apcu_fetch_large_config: numValues=     65536
	repetitions=       256 elapsed=2.980 shared memory=   8332560
@TysonAndre TysonAndre force-pushed the reduce-string-memory-usage branch from 4c7b0b5 to c659f6c Compare November 5, 2022 21:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant