PHP 성능 최적화 팁

인터넷에는 PHP 성능에 대한 수많은 최적화 팁이 있으며, 참고용 목록을 만드는 것이 필요합니다.

저자가 수집한 이러한 기술은 다양한 출처에서 나오므로 그 완전성은 보장할 수 없습니다. 높은 볼륨으로 인해 이러한 최적화 기술은 테스트되지 않았습니다. 사용하기 전에 직접 테스트해 보시기 바랍니다. 결국 이러한 기술이 도움이 될 수 있는지 여부는 PHP가 위치한 고유한 환경에 따라 다릅니다.

1. 병목 현상 찾기 (Finding the Bottleneck)

성능 문제에 직면했을 때 첫 번째 단계는 항상 트릭 목록을 보는 것이 아니라 문제의 원인을 찾는 것입니다 . 병목 현상의 원인을 파악하고 대상을 찾아 수정 사항을 구현한 후 다시 테스트하세요. 병목 현상을 찾는 것은 장정의 첫 번째 단계일 뿐이며, 가장 중요한 첫 번째 단계에서 병목 현상을 찾는 데 도움이 되기를 바라는 몇 가지 일반적인 기술은 다음과 같습니다.

  • 모니터링 방법(예: 모니터링 보물)을 사용하여 벤치마크(벤치마크 테스트) 및 모니터링을 수행합니다. 네트워크, 특히 네트워크 상태는 빠르게 변화하므로 잘 수행하면 5분 안에 병목 현상을 찾을 수 있습니다.
  • 코드를 분석하세요. 코드의 어느 부분이 가장 많은 시간을 소비하는지 이해하고, 이러한 부분에 더 많은 주의를 기울일 필요가 있습니다.
  • 병목 현상을 찾으려면 각 리소스 요청 (예: 네트워크, CPU, 메모리, 공유 메모리, 파일 시스템, 프로세스 관리, 네트워크 연결 등)을 확인하세요.
  • 먼저 반복 구조 와 복잡한 코드를 벤치마킹합니다.
  • 실제 로드 상태에서 실제 데이터로 실제 테스트를 수행하십시오 . 가능한 경우 프로덕션 서버를 사용하는 것이 좋습니다.

2. 캐싱

어떤 사람들은 캐싱이 성능 문제에 대한 가장 효과적인 솔루션 중 하나라고 생각합니다 . 다음을 시도해 보십시오.

  • 스크립트가 액세스될 때마다 다시 컴파일되지 않도록 OPCODE(작업 코드) 캐싱을 사용합니다. 예: Windows 플랫폼에서 Windows 캐시 확장을 활성화합니다. opcode, 파일, 상대 경로, 세션 데이터 및 사용자 데이터를 캐시할 수 있습니다.
  • 다중 서버 환경에서는 분산 캐시 사용을 고려하세요.
  • imap_header()를 호출하기 전에 imap_headers()를 호출하십시오.

3. 컴파일 vs. 해석(컴파일 vs. 해석)

PHP 소스 코드를 기계어 코드로 컴파일합니다. 동적 해석은 동일한 컴파일을 수행하지만 한 줄씩 수행합니다. opcode로 컴파일하는 것은 절충안 선택으로, PHP 소스 코드를 opcode로 변환한 다음 opcode를 기계어 코드로 변환할 수 있습니다. 다음은 컴파일 및 해석과 관련된 팁입니다.

  • 라이브로 전환하기 전에 PHP 코드를 기계어 코드로 컴파일하세요. Opcode 캐시가 최선의 선택은 아니지만 해석된 캐시보다 여전히 좋습니다. 또는 PHP 코드를 C 확장으로 컴파일하는 것을 고려해보세요.
  • PHP의 opcode 컴파일러(bcompiler)는 아직 프로덕션 환경에서 사용할 수 없지만 개발자는 http://php.net/manual/en/book.bcompiler.php를 따라야 합니다.

4. 콘텐츠 축소

더 적고 더 빠릅니다. 다음 팁은 코드를 줄이는 데 도움이 될 수 있습니다.

  • 페이지당 기능이 적음
  • 웹 콘텐츠 정리
  • 해석적으로 실행되는 경우 주석 및 기타 공백을 정리하십시오.
  • 데이터베이스 쿼리 감소

5. 멀티스레딩 및 멀티프로세싱

빠른 것부터 느린 것까지:

  • 멀티스레드(단일 프로세스)
  • 다중 처리(예: pcntl_fork, 예약된 작업)
  • 단일 프로세스(한 줄씩)

PHP는 멀티스레딩을 지원하지 않지만 C에서 멀티스레드 PHP 확장을 작성할 수 있습니다. 여러 프로세스를 사용하거나 여러 프로세스를 시뮬레이션하는 방법이 있지만 지원이 그다지 좋지 않고 단일 프로세스보다 느릴 수 있습니다.

6. 문자열

문자열 조작은 대부분의 프로그래밍 언어에서 가장 일반적으로 사용되는 작업 중 하나입니다. 문자열 처리 속도를 좀 더 빠르게 만드는 데 도움이 되는 몇 가지 요령은 다음과 같습니다.

  • PHP의 연결 연산(포인트 연산)이 가장 빠른 연결 방식입니다.
  • 인쇄 시 문자열 연결을 피하고, 쉼표로 구분한 후 ECHO를 사용하세요.
  • 가능하면 정규 표현식 대신 str_ 접두사가 붙은 문자열 함수를 사용하세요.
  • pos()는 preg_mach()와 ereg()보다 빠릅니다.
  • 어떤 사람들은 문자열을 큰따옴표보다 작은따옴표로 묶는 것이 더 빠르다고 말하고, 어떤 사람들은 차이가 없다고 말합니다. 물론, 문자열에서 변수를 인용하려면 작은따옴표는 쓸모가 없습니다.
  • 문자열 길이가 특정 값(예: 5)보다 작은지 확인하려면 isset($s[4])<5를 사용하세요.
  • 여러 개의 작은 문자열을 하나의 큰 문자열로 연결해야 하는 경우 먼저 ob_start 출력 버퍼를 활성화한 다음 echo를 사용하여 버퍼에 출력하고 ob_get_contents를 사용하여 완료 후 문자열을 읽으십시오.

7. 정규식

정규식은 문자열을 비교하고 찾는 유연하고 다양한 방법을 제공하지만 성능 오버헤드 는 실제로 낮지 않습니다.

  • 가능하면 정규식 대신 STR_ 접두사가 붙은 문자열 처리 함수를 사용하세요.
  • [aeiou]를 사용하지 않음(a|e|i|o|u)
  • 간단한 정규 표현식이 더 빠릅니다.
  • 가능하면 PCRE_DOTALL 수정자를 설정하지 마세요.
  • 대신 ^.를 사용하세요 .
  • 정규식을 단순화합니다. (예: (a+) 대신 a를 사용하세요.

8. 반복 구문(for, while)

반복(반복, 반복)은 구조화된 프로그래밍의 가장 기본적인 방법이며 , 이를 사용하지 않는 프로그램은 상상하기 어렵습니다. 다음은 반복 구조의 성능을 향상시키는 데 도움이 되는 몇 가지 요령입니다 .

  • 가능한 한 많이 루프 밖으로 코드를 이동하십시오(함수 호출, SQL 쿼리 등...)
  • for(i=0;i<maxval;i++) 대신 i=maxval;while(i–)를 사용하면 한 번의 작업을 줄일 수 있으며 maxval이 함수 호출인지가 더 분명합니다.
  • foreach를 사용하여 컬렉션 및 배열 반복

9. 선택 구성(if, switch)

반복 구조와 마찬가지로 선택 구조도 가장 기본적인 구조적 프로그래밍 방법입니다 . 다음 기술을 사용하면 성능이 향상될 수 있습니다.

  • 스위치와 else-if에서는 최근에 자주 true로 나타나는 항목을 먼저 나열하고, 거의 true로 나타나지 않는 항목을 나중에 나열해야 합니다.
  • 어떤 사람들은 if-else가 swtich/case보다 빠르다고 말합니다. 물론 어떤 사람들은 이에 동의하지 않습니다.
  • else if를 elseif로 바꾸세요.

10. 기능 및 매개변수

함수의 코드를 더 작은 함수 코드로 나누면 중복이 제거되고 코드를 더 읽기 쉽게 만들 수 있지만 비용은 얼마나 듭니까? 다음은 기능을 더 잘 사용하는 데 도움이 되는 몇 가지 팁입니다.

객체와 배열은 값이 아닌 참조로 전달되므로
한 곳에서만 사용하는 경우 인라인을 사용하세요. 여러 곳에서 호출되는 경우 인라인을 고려하되 유지 관리에 주의하고
사용하는 함수의 복잡성을 이해하세요. 예를 들어, 유사_텍스트()는 O(N^3)이므로 문자열 길이가 2배로 늘어나 처리 시간이 8배로 늘어난다. 성능 향상을 위해 "참조 반환"을 사용하지 않으면 엔진
이 자동으로 최적화합니다.
call_user_func_array() 또는 eval()을 사용하는 대신 일반적인 방법으로 함수를 호출합니다.

11. 객체지향 구조

PHP의 객체 지향적 특성은 성능에 영향을 미칠 수 있습니다 . 다음 팁은 이러한 영향을 최소화하는 데 도움이 될 수 있습니다.

  • 모든 것이 OO일 필요는 없으며 성능 저하가 이점보다 클 수 있습니다.
  • 객체 생성 속도가 느립니다.
  • 가능하다면 객체 대신 배열을 사용하세요.
  • 메서드를 정적으로 만들 수 있으면 정적으로 선언하세요.
  • 함수 호출은 파생 클래스 메서드 호출보다 빠르고, 파생 클래스 메서드 호출은 기본 클래스 호출보다 빠릅니다.
  • 가장 일반적으로 사용되는 코드를 기본 클래스에서 파생 클래스로 복사하는 것을 고려하세요. 하지만 유지 관리의 함정에 유의하세요.
  • 기본 getter 및 setter를 사용하지 마세요. 필요하지 않고 속성이 공개된 경우 제거하세요.
  • 복잡한 PHP 클래스를 만들 때 싱글톤 패턴 사용을 고려하세요.

12. 세션 처리

세션을 생성하면 많은 이점이 있지만 때로는 불필요한 성능 오버헤드가 발생합니다 . 다음 팁은 성능 오버헤드를 최소화하는 데 도움이 될 수 있습니다.

  • auto_start를 사용하지 마십시오
  • use_trans_sid를 활성화하지 마세요.
  • session_cache_limited를 private_no_expire로 설정합니다.
  • 가상 호스트(vhost)의 각 사용자에게 고유한 디렉터리를 할당합니다.
  • 파일 기반 세션 처리 대신 메모리 기반 세션 처리 사용

13. 타입 캐스팅

한 유형에서 다른 유형으로 변환하려면 비용이 필요합니다.

14. 압축

전송하기 전에 텍스트와 데이터를 압축합니다.

  • 코드 시작 부분에 ob_start()를 사용하세요.
  • 더 빠르게 다운로드하려면 ob_gzhandler()를 사용하세요. 하지만 CPU 오버헤드에 주의하세요.
  • Apache의 mod_gzip 모듈은 다음과 같은 경우에도 압축할 수 있습니다.

15. 오류 처리

오류 처리는 성능에 영향을 미칩니다 . 우리가 할 수 있는 일은:

  • 오류 로그를 기록하고, 오류 보고를 억제하기 위해 "@"를 사용하지 마십시오. 억제는 성능에 영향을 미칩니다.
  • 오류 로그만 확인하지 말고 경고 로그도 처리해야 합니다.

16. 선언, 정의 및 범위

변수, 배열 또는 객체를 생성하면 성능에 영향을 미칩니다.

  • 어떤 사람들은 전역 변수/객체를 선언하고 사용하는 것이 지역 변수/객체보다 빠르다고 말하고 어떤 사람들은 객체를 사용합니다. 테스트 해보고 결정해주세요.
  • 모든 변수는 사용하기 전에 선언하고, 사용하지 않는 변수는 선언하지 마세요.
  • 루프에서 가능할 때마다 a[]를 사용하고 , a[]를 피하고, 피하십시오.a [ ] , a=array(…)

17. 메모리 누수

메모리가 할당되었지만 해제되지 않은 경우 이는 확실히 문제가 됩니다 .

  • 리소스 해제를 고집하고 내장/자동 가비지 수집에 의존하지 마세요.
  • 사용 후 변수, 특히 리소스 클래스 및 대규모 배열 유형을 설정 해제(설정 해제)해 보세요.
  • 사용 후 데이터베이스 연결을 닫습니다.
  • ob_start()를 사용할 때마다 ob_end_flush() 또는 ob_end_clean()을 기억하세요.

18. 바퀴를 재발명하지 마세요(Don't Reinvent the Wheel)

왜 다른 사람들이 이미 해결한 문제를 해결하는데 시간을 소비합니까?

  • PHP와 그 기능 및 확장에 대해 알아보세요. 모르면 기본 제공되는 일부 기능을 활용하지 못할 수도 있습니다.
  • 내장된 배열 및 문자열 함수를 사용하면 확실히 최고의 성능을 발휘합니다.
  • 이전 세대가 발명한 휠은 에너지 흡수가 귀하의 환경에서 가장 좋다는 것을 의미하지 않습니다. 더 테스트해 보세요.

19. 코드 최적화

  • Opcode 최적화 도구 사용
  • 해석해서 실행하게 된다면 소스코드를 단순화해주세요.

20, 사용 RAM(Using RAM Instead of DASD)

RAM은 disk보다 훨씬 빠르며 RAM을 사용하면 성능이 향상될 수 있습니다.

  • 파일을 Ramdisk로 이동
  • 파일 기반 세션 처리 대신 메모리 기반 세션 처리 사용

21. 서비스 사용(예: SQL)

SQL은 관계형 데이터베이스에 액세스하는 데 자주 사용되지만 PHP 코드는 다양한 서비스에 액세스할 수 있습니다. 다음은 염두에 두어야 할 몇 가지 액세스 서비스입니다.

  • 서버에게 계속해서 동쪽으로 가도록 요청하지 마십시오. 메모이제이션을 사용하여 첫 번째 결과를 캐시한 다음 액세스 후 바로 캐시로 이동합니다.
  • SQL에서는 mysql_fetch_array() 대신 mysql_fetch_assoc()을 사용하여 결과 집합의 정수 인덱스를 줄입니다. 인덱스 번호 대신 필드 이름으로 결과 집합에 액세스합니다.
  • Oracle 데이터베이스의 경우 사용 가능한 메모리가 충분하지 않으면 oci8.default_prefetch를 늘리십시오. oci8.statement_cache_size를 애플리케이션의 명령문 수로 설정합니다.
  • 결과 세트가 처리를 위해 다른 레이어로 전송되지 않는 한 mysqli_fetch_all() 대신 mysqli_fetch_array()를 사용하십시오.

22. 설치 및 구성

PHP를 설치하고 구성할 때 성능을 고려하십시오.

  • 메모리를 더 추가하세요
  • 경쟁 앱 및 서비스 제거
  • 필요한 확장만 컴파일
  • PHP를 정적으로 APACHE로 컴파일
  • 모든 컴파일러 최적화를 활성화하려면 -O3 CFLAGS를 사용하세요.
  • 필요한 모듈만 설치하세요
  • 최신 마이너 버전으로 업그레이드하세요. 메인보드 업그레이드, 첫 번째 버그가 수정될 때까지 기다리세요. 물론 너무 오래 기다리지는 마세요.
  • 다중 CPU 환경을 위한 구성
  • 使용 -인라인 최적화 활성화
  • session.save_handler=mm 설정, -with-mmto로 컴파일, 공유 메모리 사용
  • RAM 디스크 사용
  • resistancer_global 및 Magic_quotes_* 끄기
  • 노출_php 닫기
  • 사용해야 하는 경우가 아니면 Always_populate_raw_post_data를 비활성화하세요.
  • 명령줄 모드가 아닌 모드에서 Register_argc_argv를 닫으세요.
  • .php 파일에서만 PHP를 사용하세요.
  • max_execution_time, max_input_time, memory_limit 및 output_buffering의 매개변수를 최적화합니다.
  • 파일/디렉터리 액세스 속도를 향상하려면 Apache 구성 파일에서 허용 재정의를 없음으로 설정하세요.
  • -march, -mcpu, -msse, -mmmx 및 -mfpmath=sseto를 사용한 CPU 최적화
  • libmysql, mysqli 확장 및 PDO MYSQL 드라이버를 MySQL 기본 드라이버(mysqlnd)로 교체
  • Register_globals, Register_long_arrays 및 Register_argc_argv를 비활성화합니다. auto_globals_jit를 활성화합니다.

23. 기타

분류하기 어려운 몇 가지 트릭도 있습니다.

  • include(), require()를 사용하고, include_once() 및 require_once()는 피하세요.
  • include()/require()에서 절대 경로를 사용하세요.
  • 정적 HTML은 PHP로 생성된 HTML보다 빠릅니다.
  • 정규식 대신 ctype_alnum, ctype_alpha 및 ctype_digit를 사용하세요.
  • 간단한 서블릿 또는 CGI 사용
  • 프로덕션 환경에서 코드를 사용할 때는 최대한 로그를 작성하세요.
  • 출력 버퍼링 사용
  • 비교 대신 a) 비교 대신 isset( a )를 사용하십시오.a ) a==null을 비교하는 대신 isul 대신 === null을사용하십시오===i 대신n u ll내가 ( 에)
  • 스크립트 시작 실행 시간이 필요합니다. time()을 사용하는 대신 $_SERVER['REQUEST_TIME']을 직접 읽어보세요.
  • 인쇄 대신 에코 사용
  • 사후 증가(i++) 대신 사전 증가(++i)를 사용하면 대부분의 컴파일러가 이제 최적화하지만 그렇지 않은 경우에는 그대로 유지합니다.
  • XML을 처리하려면 DOM이나 SAX 대신 정규식을 사용하세요.
  • HASH 알고리즘: md4, md5, crc32, crc32b, sha1은 다른 해싱 속도보다 빠릅니다.
  • spl_autoload_extensions를 사용할 때 가장 일반적으로 사용되는 파일 확장자 -> 가장 덜 사용되는 파일 확장자의 순서를 따르고 전혀 사용되지 않는 확장자를 제외하도록 노력하십시오.
  • fsockopen이나 fopen을 사용할 때는 도메인 이름 대신 IP 주소를 사용하고, 도메인 이름이 하나만 있는 경우에는 gethostbyname()을 사용하여 IP 주소를 얻습니다. cURL을 사용하는 것이 더 빠릅니다.
  • 가능하다면 동적 콘텐츠를 정적 콘텐츠로 바꾸세요.

추천

출처blog.csdn.net/heshihu2019/article/details/132070415