PHP 애플리케이션의 성능 최적화
PHP 프로그래밍의 가장 큰 이점은 이 프로그래밍 언어와 풍부한 라이브러리를 배우기가 쉽다는 것입니다. 사용해야 하는 기능에 대해 많이 알지 못하더라도 특정 작업을 수행하는 방법을 추측할 수 있습니다.
PHP는 매우 간단하고 배우기 쉽지만, PHP의 일부 프로그래밍 기술, 특히 성능 및 메모리 사용과 관련된 기술을 배우는 데 약간의 시간이 필요합니다. PHP에는 메모리 사용량을 줄이고 애플리케이션 성능을 향상시킬 수 있는 많은 트릭이 있습니다. 이번 글에서는 PHP 애플리케이션 분석, 스크립트 코드 변경 방법, 최적화 전후의 다양한 매개변수 값 비교 등을 간략하게 소개하겠습니다.
프로그램에서 타이밍 절차를 설정하고 이러한 코드를 반복적으로 실행함으로써 프로그램의 실행 속도에 대한 일련의 데이터를 얻을 수 있습니다. 이 데이터는 프로그램의 병목 현상을 발견하고 이를 최적화하여 성능을 향상시키는 방법에 사용할 수 있습니다. 애플리케이션.
아마도 독자들은 PEAR 라이브러리에 대해 들어본 적이 있을 것입니다. PEAR 라이브러리를 사용하여 분석 중에 사용해야 하는 예제를 만들겠습니다. 이는 기존 코드를 분석하는 가장 쉬운 방법이기도 합니다. 이를 통해 상용 제품을 사용하지 않고도 코드를 분석할 수 있습니다.
우리가 사용할 라이브러리의 이름은 PEAR::Benchmark이며 코드 프로파일링 및 성능 테스트에 매우 유용합니다. 이 라이브러리는 한 함수 호출과 다음 함수 호출 사이의 시간을 기록할 수 있는 Benchmark_Timer()라는 클래스를 제공합니다. 코드의 성능을 테스트할 때 상세한 스크립트 실행 결과를 얻을 수 있는데, 이는 다음과 같이 매우 간단합니다.
include_once("벤치마크/Timer.php");
$bench = 새로운 Benchmark_Timer;
$벤치->시작();
$bench-> setMarker('스크립트 시작');
// 이제 몇 분 동안 절전 상태에 있습니다.
수면(5);
$벤치->중지();
// 타이머로부터 분석 정보를 얻습니다.
print_r($bench->getProfiling());
?>
위 코드를 실행한 후의 출력은 다음과 같습니다.
정렬
(
[0] => 배열
(
[이름] => 시작
[시간] => 1013214253.05751200
[차이점] => -
[합계] => 0
)
[1] => 배열
(
[이름] => 스크립트 시작
[시간] => 1013214253.05761100
[차이점] => 9.8943710327148E-05
[합계] => 9.8943710327148E-05
)
[2] => 배열
(
[이름] => 중지
[시간] => 1013214258.04920700
[차이점] => 4.9915959835052
[합계] => 4.9916949272156
)
)
위의 숫자는 연결되지 않은 숫자 집합처럼 보일 수 있지만 프로그램 크기가 더 큰 경우 이 숫자는 매우 유용할 수 있습니다.
아마도 대부분의 독자는 배열의 첫 번째 항목이 Benchmark_Timer() 클래스를 호출하는 실제 메소드라고 추측할 수도 있습니다. 예를 들어
$bench->start(), $bench->setMarker() 및 $bench->stop() 이러한 항목과 관련된 숫자는 매우 간단합니다.
[0] => 배열
(
[이름] => 시작
[시간] => 1013214253.05751200
[차이점] => -
[합계] => 0
)
시간 항목은 Benchmark_Timer()의 start() 메서드가 호출될 때의 UNIX 타임스탬프를 참조합니다. diff 항목은 이 호출과 마지막 호출 사이의 시간 간격을 나타냅니다. 여기에는 이전 호출이 없으므로 전체 항목인 대시가 표시됩니다. 테스트 시작부터 이 특정 호출까지 코드가 실행된 총 시간을 나타냅니다. 다음 배열의 출력을 살펴보겠습니다.
[1] => 배열
(
[이름] => 스크립트 시작
[시간] => 1013214253.05761100
[차이점] => 9.8943710327148E-05
[합계] => 9.8943710327148E-05
)
위의 숫자에서 우리는 $bench->start()를 호출한 후 $bench->setMarker(….)를 호출하기 전에 프로그램이 9.8943710327148E-05초(즉, 0.0000989초) 동안 실행된다는 것을 알 수 있습니다.
실제 성능 테스트 경험
위의 예는 좋지만 사이트의 코드 디자인을 최적화하는 방법을 결정하는 데는 실제로 좋은 예는 아닙니다. 아래에서는 웹 사이트 기술자로서 개인적인 경험을 바탕으로 성능 문제를 해결하는 방법을 설명하겠습니다.
웹사이트에서 사용되는 코드를 잘 이해하지 못합니다. 특정 요구에 따라 수년에 걸쳐 개발되었기 때문입니다. 한 모듈에는 웹사이트 전환 코드가 포함되어 있고, 다른 모듈에는 웹사이트 사용을 기록하고, 다른 모듈에는 자체 코드가 있습니다. 각자의 역할. 웹사이트의 주요 개발자와 저는 둘 다 웹사이트의 코드를 최적화해야 한다는 것을 깨달았지만 문제가 무엇인지는 몰랐습니다.
작업을 최대한 빨리 완료하기 위해 웹 사이트의 기본 스크립트 코드를 연구하기 시작했고 모든 스크립트 코드와 포함된 파일에 $bench->setMarker() 명령 몇 개를 추가한 다음 $bench의 출력을 분석했습니다. ->getProfiling(), 그리고 그 결과에 문제가 수백 번 사용된 특정 언어 이름(예: 영어의 경우 en)을 얻기 위한 변환 코드와 관련된 함수 호출에 있는 것으로 밝혀졌습니다. 각 페이지에. 이 함수가 호출될 때마다 스크립트 코드는 MySQL 데이터베이스를 쿼리하여 데이터베이스 테이블에서 실제 언어 이름을 얻습니다.
그래서 우리는 이러한 유형의 정보에 대한 버퍼링 시스템을 만듭니다. 단 2일의 작업 후에 시스템 성능이 크게 향상되었으며, 첫 주에 페이지 조회수가 40% 증가했습니다. 물론 이는 코드 분석이 어떻게 인터넷 애플리케이션이나 인터넷 웹 사이트의 성능을 향상시킬 수 있는지 보여주는 한 가지 예일 뿐입니다.
성능 테스트 함수 호출
Benchmark_Timer()는 스크립트나 웹 페이지(및 포함된 파일)를 분석할 때 특히 유용하지만, 분석된 데이터를 얻으려면 스크립트를 여러 번 로드해야 하고 특정 클래스나 함수에 국한되지 않기 때문에 과학적이지 않습니다. . 라고 불리는.
Benchmark_Iterator라는 PEAR::Benchmark 라이브러리의 또 다른 클래스는 이 문제를 매우 효과적으로 해결할 수 있습니다. 이는 특정 함수나 클래스 메서드에 대한 분석 정보를 표시할 수 있습니다. 그 목적은 스크립트를 한 번 실행하고 실행하는 데 10초가 걸린다고 해서 매번 실행하는 데 항상 10초가 걸린다는 의미는 아니라는 것을 알고 있기 때문에 테스트에서 일관된 결과를 얻을 수 있도록 하는 것입니다.
어쨌든 몇 가지 예를 살펴보겠습니다.
// 데이터베이스에 연결하는 코드
include_once("DB.php");
$dsn = 배열(
'phptype' => 'mysql',
'hostspec' => '로컬호스트',
'데이터베이스' => '데이터베이스_이름',
'사용자 이름' => '사용자 이름',
'비밀번호' => '비밀번호'
);
$dbh = DB::연결($dsn);
함수 getCreatedDate($id)
{
글로벌 $dbh;
> $stmt = "ID=$id인 사용자로부터 생성된 날짜를 선택하세요.";
// 여기서는 PEAR::DB를 사용하세요.
$created_date = $dbh-> getOne($stmt);
if ((PEAR::isError($created_date)) ||
(비어 있음($created_date))) {
거짓을 반환;
} 또 다른 {
$created_date를 반환합니다.
}
}
include_once 'Benchmark/Iterate.php';
$bench = 새로운 Benchmark_Iterate;
//getDate 함수를 10번 실행합니다.
$bench-> run(10, 'getCreatedDate', 1);
//분석정보 출력
print_r($bench->get());
?>
위 코드를 실행하면 다음과 유사한 결과가 생성됩니다.
정렬
(
[1] => 0.055413007736206
[2] => 0.0012860298156738
[3] => 0.0010279417037964
[4] => 0.00093603134155273
[5] => 0.00094103813171387
[6] => 0.00092899799346924
[7] => 0.0010659694671631
[8] => 0.00096404552459717
[9] => 0.0010690689086914
[10] => 0.00093603134155273
[평균] => 0.0064568161964417
[반복] => 10
)
위의 숫자는 이해하기 쉽습니다. 평균 항목은 getCreatedDate() 함수가 10회 실행되는 평균 시간을 나타냅니다. 실제 테스트에서는 최소한 1000번 이상 실행해야 하지만 이 예제의 결과만으로도 문제를 설명하기에 충분합니다.