Skip to content

memcache 사용시 opcache가 무력화되는 문제 #2299

@kijin

Description

@kijin

#2189 문제 해결을 위해 적용된 소스 중 config/config.inc.php

/**
 * Invalidates a cached script of OPcache when version is changed.
 * @see https://github.com/xpressengine/xe-core/issues/2189
 **/
if(
	!is_dir(_XE_PATH_ . 'files/cache/store/' . __XE_VERSION__)
	&& function_exists('opcache_get_status')
	&& function_exists('opcache_invalidate')
)
{
	foreach($GLOBALS['__xe_autoload_file_map'] as $script) {
		opcache_invalidate(_XE_PATH_ . $script, true);
	}
	opcache_invalidate(_XE_PATH_ . 'config/func.inc.php', true);
}

그런데 apc, memcache(d) 등을 사용하는 경우 files/cache/store/버전 폴더가 존재하지 않습니다. 따라서 위의 조건이 항상 참이 되어, PHP 요청할 때마다 매번 opcache_invalidate()가 발생합니다.

오브젝트 캐시를 쓰는 사이트라면 상당히 규모가 크거나 운영자가 성능을 중요하게 여기는 곳일 텐데, 저렇게 자꾸 캐시를 지워버리는 바람에 opcache의 성능 개선 효과를 별로 보지 못하고 있습니다.

몇몇 파일을 opcache_invalidate()하는 것만으로도 뜻밖에 큰 문제가 되는 이유는 opcache가 무척 단순한 구조로 되어 있기 때문입니다. opcache_invalidate()를 자주 사용하면 wasted memory가 늘어나는데, 이것을 가비지컬렉션하여 다른 데이터를 캐싱하는 데 재사용하는 것이 아니라, 그냥 일정 비율 이상이 되면 opcache를 통째로 초기화해 버립니다. 위의 코드에 해당되는 파일들만 몇 번씩 opcache_invalidate()해도 초기화가 일어날 만큼 기본값(128M 중 5%)이 낮기 때문에, 실제로 모 사이트에서 약 10초 주기로 계속 초기화되는 것을 목격했습니다. 캐시 사용 효과가 사실상 제로인 셈이지요.

설상가상으로 PHP 자체의 버그 (1, 2) 때문에 opcache를 너무 자주 초기화하면 corruption이 발생하여 엉뚱한 곳에서 에러가 나기까지 합니다. 총체적인 난국인데 그렇다고 성능에 어마어마한 영향을 주는 opcache를 쓰지 않을 수도 없고... 최대한 아껴쓰는 방법밖에 없겠습니다.

  1. file 이외의 오브젝트 캐시를 사용하는 경우에도 조건을 제대로 파악하도록 해주세요.
  2. 특별한 문제가 없는 사이트라면 아예 저 코드를 사용하지 않도록 했으면 좋겠습니다. opcache 관련 문제가 잦은 특정한 환경에서만 상수를 넣어서 컨트롤하면 어떨까요?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions