lib/ 전체를 불러오는 값은 실제로 얼마인가
이 글의 내용
이 서비스의 유일한 진입 파일 46번째 줄:
foreach (glob(__DIR__ . '/lib/*.php') as $f) { require_once $f; }
파일 65개, 1.5메가바이트이고, 요청마다 불러옵니다. 카운터 그림이든, 통계 페이지든, 404이든 모두 같습니다. 어제 그 일이 20,734번 있었습니다.
중요한 숫자는 작은 쪽입니다
옵코드 캐시를 끄고 전부를 처음부터 불러오면 약 132밀리초가 듭니다. 이것을 문제로 만들 숫자가 그것이고, 서버가 치르는 숫자는 그것이 아닙니다.
옵코드가 이미 컴파일되어 공유 메모리에 있으면 남는 것은 디렉터리 목록과 파일마다 stat() 한 번입니다. 시각 검증이 켜져 있기 때문입니다. 0.33밀리초입니다. 어제의 통행량이면 하루 전체에 7초가 안 되는 일입니다.
그 사이에 세 번째 측정 18.2밀리초가 있고, 옵코드 캐시가 메모리 대신 디스크에서 읽을 때 잰 값입니다. 진짜 수치가 아니라 상한입니다 — 캐시가 있되 진짜 캐시보다 느릴 때 일어나는 일입니다. 명령줄에서 잴 수 있는 유일한 따뜻한 숫자라서 보고하고, 아닌 척하는 것이 쉬운 잘못일 테니까요.
그러니 이것은 거의 값을 치르지 않고, 그렇게 되는 것은 전적으로 다른 무언가 덕분입니다. 옵코드 캐시를 끄면 같은 줄이 사백 배를 치릅니다. 실재하는 의존이고, 업그레이드 도중에 발견하기보다 있다는 것을 알아 두는 편이 낫습니다.
1.5메가바이트에 실제로 무엇이 들었는가
그 47퍼센트 — 파일 26개에 715킬로바이트 — 가 카운터 디자인 가족입니다. 카운터 그림을 그리는 데는 정확히 하나가 필요합니다. 나머지 25개는 불러와지고, 선언되고, 한 번도 건드려지지 않습니다.
그다음: 지리 페이지에서 필요한 국기 데이터 189킬로바이트, 무언가 그래프를 그릴 때 필요한 그래프 라이브러리 158킬로바이트입니다. 어느 쪽도 카운터 그림을 내보내는 데 관여하지 않고, 그것이 이 서비스가 다른 무엇보다 자주 답하는 요청입니다.
그 눈에 보이는 값은 시간이 아니라 메모리입니다. 요청당 최대 메모리가 약 4메가바이트 오르고, 모든 프로세스가 나눠 쓰는 옵코드와 달리 그 부분은 요청마다, 동시에, 모든 작업자가 따로 치릅니다.
이미 누군가 알아챘습니다
glob은 lib/*.php입니다. 재귀가 아니고, 바로 그 아래에 디렉터리 둘이 있습니다. lib/live/이 229킬로바이트, lib/recht/이 182킬로바이트입니다. 예전에는 불러오기 경로에 있었고 이제는 아닌 사백 킬로바이트입니다.
크고 드물게 필요해서 옮겼습니다. 통계 영역과 법적 문서입니다. 디렉터리 한 단계 아래에 있다는 것이 메커니즘 전부입니다. 설정도, 지연 로더도, 자동 로드 지도도 없습니다 — 파일은 glob 안에 있거나 없거나입니다.
실재하는 해법이고 그렇게 말해 둘 값어치가 있습니다. 뻔한 다음 단계는 자동 로더일 텐데, 여기서 자동 로더는 mkdir 하나가 이미 두 번 푼 문제를 풀려고 하는 큰 변경일 테니까요.
왜 그대로 두는가
glob 하나는 작동할 수 있는 가장 단순한 것이고, 증거로 보면 작동합니다. 밀리초의 3분의 1, 작은 서버에서, 빨라야 하는 경로에서 말입니다. 파일별 require로 바꾸면 새 파일마다 어딘가에 한 줄이 필요하고, 잊힌 그 한 줄은 조금 큰 불러오기가 아니라 운영 중의 치명적 오류를 냅니다.
필요한 것은 애초에 그것을 견딜 만하게 만든 그것을 적어 두는 일입니다. 만약 lib/의 파일이 커지면 하위 디렉터리로 옮기고 쓰이는 자리에서 require 한다. 그 두 디렉터리가 따르고 있던 규칙이고, 지금까지 어디에도 적혀 있지 않았습니다.
일반적인 판본은 측정보다 밋밋합니다. "모든 것이 모든 것을 불러온다"는 대개 잘못된 모양이고, 다시 짓기 전에 값이 얼마인지 재 볼 값어치가 있습니다. 여기서는 0.33밀리초와 4메가바이트이고, 지켜볼 대목은 4메가바이트입니다. 그것은 동시성과 함께 커지고 밀리초는 그렇지 않기 때문입니다.