답변:
require_once
그리고 include_once
둘 다 시스템에 이미 포함 / 필요한 내용의 로그를 유지해야합니다. 모든 *_once
통화는 해당 로그를 확인하는 것을 의미합니다. 그래서 확실히 거기에 약간의 여분이 수행되는 작업을하지만, 전체 응용 프로그램의 속도를 손해에 충분?
... 나는 정말로 의심합니다 ... 당신이 정말로 오래된 하드웨어를 사용하거나 많이 하지 않는 한 아닙니다 .
당신 이 수천을하고 있다면 *_once
, 당신은 더 가벼운 방식으로 일을 스스로 할 수 있습니다. 간단한 앱의 바로 만들기는 당신이 단지 그것을 한 번 포함 시켰 한다 충분하지만 여전히 재정의 오류를 얻고, 당신 수 이런 식으로 뭔가 :
if (!defined('MyIncludeName')) {
require('MyIncludeName');
define('MyIncludeName', 1);
}
나는 개인적으로 *_once
진술을 고수 하지만 바보 같은 백만 패스 벤치 마크에서 두 가지의 차이점을 볼 수 있습니다.
php hhvm
if defined 0.18587779998779 0.046600103378296
require_once 1.2219581604004 3.2908599376678
10 ~ 100 ×와 느린 require_once
과 그 호기심의 require_once
겉으로는 느린에서입니다 hhvm
. 다시 말하지만, *_once
수천 번 실행하는 경우에만 코드와 관련이 있습니다 .
<?php // test.php
$LIMIT = 1000000;
$start = microtime(true);
for ($i=0; $i<$LIMIT; $i++)
if (!defined('include.php')) {
require('include.php');
define('include.php', 1);
}
$mid = microtime(true);
for ($i=0; $i<$LIMIT; $i++)
require_once('include.php');
$end = microtime(true);
printf("if defined\t%s\nrequire_once\t%s\n", $mid-$start, $end-$mid);
<?php // include.php
// do nothing.
이 스레드는 이미 "솔루션 게시"가 있었으므로 모든 의도와 목적에 맞지 않기 때문에 나를 비난합니다. 열거하자 :
PHP 에서는 정말 비싸다. 당신은 수 를 찾아 나 스스로를 테스트하지만, PHP에서 전역 상수를 정의하는 유일한 효과적인 방법은 확장을 통해입니다. (클래스 상수는 실제로 현명한 성능이지만 현명한 포인트입니다. 2 때문에)
require_once()
클래스를 포함하기 위해 적절하게 사용 하는 경우 정의가 필요하지 않습니다. 그냥 확인하십시오 class_exists('Classname')
. 포함하는 파일에 코드가 포함 된 경우 (예 : 절차 적 방식으로 코드를 사용하는 require_once()
경우) 반드시 필요한 이유는 없습니다 . 서브 루틴 호출을 할 것으로 추정되는 파일을 포함 할 때마다.
그래서 한동안 많은 사람들이 class_exists()
그들의 포함에이 방법을 사용했습니다 . 난처하기 때문에 마음에 들지 않지만 다음과 같은 이유가 있습니다 : require_once()
최신 버전의 PHP 이전에는 꽤 비효율적이었습니다. 그러나 그것은 고쳐졌고 조건부와 여분의 메소드 호출을 위해 컴파일 해야하는 여분의 바이트 코드가 내부 해시 테이블 검사를 훨씬 능가한다는 주장은 내 주장입니다.
이제, 승인 :이 작업은 실행 시간이 거의 없기 때문에 테스트하기가 어렵습니다.
다음은 고려해야 할 질문입니다. 포함은 일반적으로 PHP에서 비쌉니다. 인터프리터가 적중 할 때마다 구문 분석 모드로 다시 전환하고 opcode를 생성 한 다음 뒤로 건너 뛰어야하기 때문입니다. 100 이상 포함하면 성능에 영향을 미칩니다. require_once를 사용하거나 사용하지 않는 이유는 opcode 캐시를 사용하기가 어렵 기 때문에 중요한 질문입니다. 이에 대한 설명은 여기에서 찾을 수 있지만, 이것으로 요약하면 다음과 같습니다.
구문 분석 시간 동안 요청의 전체 수명 동안 필요한 파일이 무엇인지 정확히 알고 있으면 require()
처음부터 opcode 캐시가 다른 모든 파일을 처리합니다.
opcode 캐시를 실행하지 않는 경우 어려운 위치에 있습니다. 모든 포함을 하나의 파일로 인라인하면 (개발 중, 프로덕션 환경에서만 수행) 시간을 구문 분석하는 데 도움이 될 수 있지만, 처리하는 데 어려움이 있으며, 작업 중에 포함 할 대상을 정확히 알아야합니다. 의뢰.
자동로드는 포함이 완료 될 때마다 자동로드 논리를 실행해야하기 때문에 매우 편리하지만 느립니다. 실제로, 하나의 요청에 대해 여러 특수 파일을 자동로드해도 문제가 많이 발생하지는 않지만 필요한 모든 파일을 자동로드하지 않아야합니다.
포함이 10 개 ( 봉투 계산 의 매우 역임) 인 경우 데이터베이스 쿼리 또는 무언가를 최적화하는 것만으로도 가치가 없습니다.
define()
, require_once()
그리고 defined()
모든 테이크 1-2에 대한 마이크로 내 컴퓨터의 각을.
궁금해서 Adam Backstrom의 Tech Your Universe 링크를 확인했습니다. . 이 기사에서는 require_once 대신 require를 사용해야하는 이유 중 하나에 대해 설명합니다. 그러나 그들의 주장은 내 분석에 영향을 미치지 않았다. 솔루션을 잘못 분석 한 곳을 보는 데 관심이 있습니다. 비교를 위해 PHP 5.2.0을 사용했습니다.
다른 헤더 파일을 포함하기 위해 require_once를 사용하는 100 개의 헤더 파일을 만드는 것으로 시작했습니다. 이 파일들 각각은 다음과 같았습니다 :
<?php
// /home/fbarnes/phpperf/hdr0.php
require_once "../phpperf/common_hdr.php";
?>
빠른 Bash 핵을 사용하여 이것을 만들었습니다.
for i in /home/fbarnes/phpperf/hdr{00..99}.php; do
echo "<?php
// $i" > $i
cat helper.php >> $i;
done
이런 식으로 require_once와 헤더 파일을 포함시킬 때 필요한 것을 쉽게 바꿀 수 있습니다. 그런 다음 app.php를 만들어 100 개의 파일을로드했습니다. 이것은 다음과 같았다 :
<?php
// Load all of the php hdrs that were created previously
for($i=0; $i < 100; $i++)
{
require_once "/home/fbarnes/phpperf/hdr$i.php";
}
// Read the /proc file system to get some simple stats
$pid = getmypid();
$fp = fopen("/proc/$pid/stat", "r");
$line = fread($fp, 2048);
$array = split(" ", $line);
// Write out the statistics; on RedHat 4.5 with kernel 2.6.9
// 14 is user jiffies; 15 is system jiffies
$cntr = 0;
foreach($array as $elem)
{
$cntr++;
echo "stat[$cntr]: $elem\n";
}
fclose($fp);
?>
require_once 헤더를 다음과 같은 헤더 파일을 사용한 require 헤더와 대조했습니다.
<?php
// /home/fbarnes/phpperf/h/hdr0.php
if(!defined('CommonHdr'))
{
require "../phpperf/common_hdr.php";
define('CommonHdr', 1);
}
?>
require와 require_once로 이것을 실행할 때 큰 차이를 찾지 못했습니다. 사실, 초기 테스트는 require_once가 약간 빠르다는 것을 암시하는 것처럼 보였지만 반드시 그렇게 생각하지는 않습니다. 10000 개의 입력 파일로 실험을 반복했습니다. 여기서 나는 일관된 차이를 보았습니다. 테스트를 여러 번 실행했는데 결과는 비슷하지만 require_once는 평균 30.8 개의 사용자 지프와 72.6 개의 시스템 지프를 사용합니다. 평균 39.4 사용자 지프와 72.0 시스템 지프가 필요합니다. 따라서 require_once를 사용하면로드가 약간 낮아집니다. 그러나 벽시계 시간이 약간 증가합니다. 10,000 개의 require_once 호출은 평균 10.15 초를 사용하고 10,000 개의 호출은 평균 9.84 초를 사용합니다.
다음 단계는 이러한 차이점을 살펴 보는 것입니다. 내가 사용 strace를가 만들어지고있는 시스템 콜을 분석 할 수 있습니다.
require_once에서 파일을 열기 전에 다음과 같은 시스템 호출이 이루어집니다.
time(NULL) = 1223772434
lstat64("/home", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
lstat64("/home/fbarnes", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
lstat64("/home/fbarnes/phpperf", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
lstat64("/home/fbarnes/phpperf/h", {st_mode=S_IFDIR|0755, st_size=270336, ...}) = 0
lstat64("/home/fbarnes/phpperf/h/hdr0.php", {st_mode=S_IFREG|0644, st_size=88, ...}) = 0
time(NULL) = 1223772434
open("/home/fbarnes/phpperf/h/hdr0.php", O_RDONLY) = 3
이것은 require와 대조됩니다 :
time(NULL) = 1223772905
lstat64("/home", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
lstat64("/home/fbarnes", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
lstat64("/home/fbarnes/phpperf", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
lstat64("/home/fbarnes/phpperf/h", {st_mode=S_IFDIR|0755, st_size=270336, ...}) = 0
lstat64("/home/fbarnes/phpperf/h/hdr0.php", {st_mode=S_IFREG|0644, st_size=146, ...}) = 0
time(NULL) = 1223772905
open("/home/fbarnes/phpperf/h/hdr0.php", O_RDONLY) = 3
Tech Your Universe는 require_once가 lstat64를 더 많이 호출해야 함을 의미합니다. 그러나 둘 다 동일한 수의 lstat64 호출을 수행합니다. 아마도 차이점은 위의 코드를 최적화하기 위해 APC를 실행하지 않는다는 것입니다. 그러나 다음으로 전체 실행에 대한 strace 출력을 비교했습니다.
[fbarnes@myhost phpperf]$ wc -l strace_1000r.out strace_1000ro.out
190709 strace_1000r.out
210707 strace_1000ro.out
401416 total
require_once를 사용할 때 헤더 파일 당 약 2 개의 더 많은 시스템 호출이 있습니다. 한 가지 차이점은 require_once가 time () 함수를 추가로 호출한다는 것입니다.
[fbarnes@myhost phpperf]$ grep -c time strace_1000r.out strace_1000ro.out
strace_1000r.out:20009
strace_1000ro.out:30008
다른 시스템 호출은 getcwd ()입니다.
[fbarnes@myhost phpperf]$ grep -c getcwd strace_1000r.out strace_1000ro.out
strace_1000r.out:5
strace_1000ro.out:10004
hdrXXX 파일에서 참조되는 상대 경로를 결정했기 때문에 호출됩니다. 이것을 절대 참조로 만들면 유일한 차이점은 코드에서 추가 시간 (NULL) 호출입니다.
[fbarnes@myhost phpperf]$ wc -l strace_1000r.out strace_1000ro.out
190705 strace_1000r.out
200705 strace_1000ro.out
391410 total
[fbarnes@myhost phpperf]$ grep -c time strace_1000r.out strace_1000ro.out
strace_1000r.out:20008
strace_1000ro.out:30008
이것은 상대 경로가 아닌 절대 경로를 사용하여 시스템 호출 수를 줄일 수 있음을 의미합니다. 그 이외의 유일한 차이점은 더 빠른 것을 비교하기 위해 코드를 계측하는 데 사용되는 time (NULL) 호출입니다.
또 다른 참고 사항은 APC 최적화 패키지에 "apc.include_once_override"라는 옵션이 있으며 require_once 및 include_once 호출에 의해 수행되는 시스템 호출 수를 줄입니다 ( PHP 문서 참조 ).
이러한 코딩 관행에 대한 링크를 피할 수 있습니까? 내가 아는 한, 그것은 완전한 비 이슈 입니다. 나는 소스 코드를 직접 보았다하지 않은,하지만 난 사이의 유일한 차이는 상상 것 include
과는 include_once
즉 include_once
배열마다 시간이 지남에 따라 배열 및 검사에 그 파일 이름을 추가합니다. 해당 배열을 정렬 된 상태로 유지하는 것은 쉬운 일이므로 O (log n)를 검색해야하며 중간 규모의 응용 프로그램조차도 수십 가지가 포함됩니다.
더 좋은 방법은 객체 지향 접근 방식을 사용하고 __autoload () 를 사용하는 것입니다 .
__autoload()
낙담하고 그것이 미래에 사용되지 수 있습니다, 당신은 사용해야 spl_autoload_register(...)
요즘 ... PS2가 : 날 오해하지 마세요, 가끔 사용하는 자동로드 기능을 할; )
나쁜 기능을 사용하지 않습니다. 전체 코드 기반에서 사용 방법과시기를 잘못 이해하고 있습니다. 나는 아마도 오해의 여지가있는 개념에 약간 더 많은 맥락을 추가 할 것입니다.
사람들은 require_once가 느린 기능이라고 생각해서는 안됩니다. 코드를 다른 방식으로 포함시켜야합니다. require_once()
대 require()
속도는 문제가되지 않습니다. 맹목적으로 사용하면 발생할 수있는 경고를 막는 성능에 관한 것입니다. 문맥을 고려하지 않고 광범위하게 사용하면 메모리 낭비 나 코드 낭비가 발생할 수 있습니다.
내가 본 사실은 거대한 모 놀리 식 프레임 워크 require_once()
가 잘못된 방식으로, 특히 복잡한 객체 지향 (OO) 환경에서 사용될 때 입니다.
require_once()
많은 라이브러리에서 볼 수 있듯이 모든 클래스의 최상위에서 사용하는 예를 들어보십시오 .
require_once("includes/usergroups.php");
require_once("includes/permissions.php");
require_once("includes/revisions.php");
class User{
// User functions
}
따라서이 User
클래스는 다른 세 가지 클래스를 모두 사용하도록 설계되었습니다. 그럴 수 있지!
그러나 이제 방문자가 사이트를 탐색하고 로그인하지 않고 프레임 워크가로드 require_once("includes/user.php");
될 때마다 : 모든 단일 요청에 대해 어떻게됩니까 ?
특정 요청 중에 사용하지 않을 1 + 3 개의 불필요한 클래스를 포함합니다. 이는 부풀린 프레임 워크가 5MB 이하가 아닌 요청 당 40MB를 사용하는 방식입니다.
오용 될 수있는 다른 방법은 다른 많은 사람들이 수업을 재사용 할 때입니다! helper
함수 를 사용하는 약 50 개의 클래스가 있다고 가정하십시오 . helpers
클래스가로드 될 때 해당 클래스를 사용할 수 있게하려면 다음을 얻습니다.
require_once("includes/helpers.php");
class MyClass{
// Helper::functions(); // etc..
}
여기에는 아무런 문제가 없습니다. 그러나 한 페이지 요청에 15 개의 유사한 클래스가 포함되는 경우. 당신은 require_once
15 번 실행 하거나 멋진 시각을 위해 :
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once ()를 사용하면 불필요한 행을 구문 분석해야하는 것 외에도 해당 함수를 14 번 실행하는 성능에 기술적으로 영향을 미칩니다. 비슷한 문제를 가진 10 개의 다른 클래스가 사용되기 때문에 무의미한 반복 코드의 100 줄 이상을 차지할 수 있습니다.
이를 require("includes/helpers.php");
통해 응용 프로그램 또는 프레임 워크의 부트 스트랩에서 사용 하는 것이 좋습니다. 그러나 모든 것이 상대적이기 때문에 클래스 의 무게 대 사용 빈도 가 15-100 줄을 절약 할 가치가 있는지 여부에 달려 있습니다. 그러나 주어진 요청 에서 파일을 사용하지 않을 확률이 없으면 주 클래스에 있어야합니다. 데 각 클래스에서 별도로 자원의 낭비가된다.helpers
require_once()
helpers
require
require_once
이 require_once
함수는 필요할 때 유용하지만 모든 클래스를로드하기 위해 어디서나 사용할 수있는 단일 솔루션으로 간주해서는 안됩니다.
PEAR2 위키 (존재 하는 경우)는 최소한 라이브러리 코드에 대해 자동로드 를 위해 모든 require / include 지시문 을 포기해야하는 적절한 이유 를 나열하는 데 사용되었습니다 . 이것들은 phar 와 같은 대체 패키징 모델 이 수평선에 있을 때 견고한 디렉토리 구조와 연결됩니다 .
업데이트 : 위키의 웹 보관 버전이 눈에 띄게 추악하므로 아래에서 가장 매력적인 이유를 복사했습니다.
- (PEAR) 패키지를 사용하려면 include_path가 필요합니다. 따라서 PEAR 패키지를 다른 응용 프로그램 내에 자체 include_path와 번들로 묶어 필요한 클래스가 포함 된 단일 파일을 작성하고 광범위한 소스 코드 수정없이 PEAR 패키지를 phar 아카이브로 이동하기가 어렵습니다.
- 최상위 레벨 require_once가 조건부 require_once와 혼합되면 APC와 같은 opcode 캐시로 캐시 할 수없는 코드가 생길 수 있습니다 .PHP 6과 함께 번들로 제공됩니다.
- relative require_once는 include_path가 올바른 값으로 설정되어 있어야하며, 올바른 include_path없이 패키지를 사용할 수 없습니다
이 *_once()
함수 는 포함 된 파일이 이미 포함 된 파일과 동일하지 않도록 모든 상위 디렉토리를 통계 합니다. 이것이 둔화 이유의 일부입니다.
벤치마킹에는 Siege 와 같은 도구를 사용하는 것이 좋습니다 . 제안 된 모든 방법론을 시도하고 응답 시간을 비교할 수 있습니다.
자세한 내용 require_once()
은 Tech Your Universe 입니다.
설사 require_once
하고 include_once
있습니다 보다 느리게 require
및 include
(또는 대안이있을 수 있습니다 무엇이든), 우리는 여기에 마이크로 최적화의 가장 작은 수준에 대해 얘기하고. 잘못 작성된 루프 또는 데이터베이스 쿼리를 최적화하는 데 시간을 투자하는 것보다 시간이 훨씬 낫습니다 require_once
.
이제 require_once
포함을 깨끗하고 체계적으로 유지하는 데주의를 기울일 필요는 없지만 함수 자체 와는 아무런 관련이 없기 때문에 잘못된 코딩 관행 을 허용 한다고 주장 할 수 있습니다. 와 속도 .
분명히, 자동 로딩은 코드의 청결 함과 유지 보수의 편의를 위해 더 낫지 만 이것이 속도 와 관련이 없음을 분명히하고 싶습니다 .
PEAR 문서에는 require, require_once, include 및 include_once에 대한 권장 사항이 있다고 생각합니다. 나는 그 지침을 따릅니다. 응용 프로그램이 더 명확합니다.
속도와 관련이 없습니다. 우아하게 실패하는 것입니다.
require_once ()가 실패하면 스크립트가 완료된 것입니다. 다른 것은 처리되지 않습니다. include_once ()를 사용하면 나머지 스크립트는 계속 렌더링을 시도하므로 사용자는 스크립트에서 실패한 것에 대해 더 현명하지 않을 것입니다.