PHP in_array() 내장함수 퍼포먼스 이슈

PHP 배열에서 특정값이 있는지 확인을 위해 아래와 같이 in_array() 내장함수를 많이 이용합니다. 

<?php
$arr = [1, 3, 55, 88];
if (in_array(55, $arr)) { ... }

위 방식은 사용이 간편하지만 회사에서 대량의 데이터를 생성하는 배치를 개발하던 도중에 심각한 퍼포먼스 저하 현상을 겪었습니다.

특정 기간 내의 데이터를 조회하여 일/월별로 중복제거 또는 합산을 처리하는 코드를 작성 중이었는데, 중복제거를 위한 배열에 값을 넣어두고 루프를 돌 때마다 값이 있는지 확인하는 로직이었는데요,

in_array() 대신 아래와 같은 방식을 활용하여 퍼포먼스 개선을 할 수 있었습니다.

<?php
$arr = [
    1 => true,
    3 => true,
    55 => true,
    88 => true
];

if(isset($arr[55])) { ... }

위 현상에 대한 ChatGPT 답변은 아래와 같습니다.

두 코드 조각은 모두 주어진 배열에서 특정 요소가 존재하는지 확인하는 방법을 보여주고 있지만, 두 번째 코드 조각이 성능 면에서 더 효율적인 이유는 다음과 같습니다.

첫 번째 코드 조각에서 in_array 함수를 사용하면 배열을 순회하면서 특정 요소를 찾아야 합니다. 배열의 크기에 따라서 성능이 저하될 수 있습니다. 이 함수의 시간 복잡도는 O(n)입니다. 따라서 배열의 크기가 크면 성능 저하가 발생할 수 있습니다.

두 번째 코드 조각에서는 연관 배열(associative array)을 사용하여 각 요소를 키로 가지고 있는데, 이렇게 하면 배열 내에서 특정 요소를 바로 접근할 수 있습니다. 연관 배열에서 요소를 접근하는 시간 복잡도는 O(1)이므로 매우 빠릅니다. 따라서 특정 키의 값에 접근하는 작업은 상수 시간만큼 걸리며, 배열의 크기와 무관합니다.

따라서 두 번째 코드 조각은 특정 키의 값에 접근하는 과정에서 상대적으로 더 빠르며, 큰 배열에서도 성능을 유지할 가능성이 높습니다. 하지만 이러한 성능 차이는 배열의 크기와 사용하는 컴퓨터 환경에 따라 달라질 수 있으므로, 실제 사용 시에는 성능 테스트를 통해 확인하는 것이 좋습니다.

PHP 알고리즘

NativePHP + Ubuntu 22.04 환경 오류

 

https://nativephp.com

  • PHP로 크로스 플랫폼 데스크탑 어플리케이션 작성
  • OS 기능을 사용할 수 있게 해주는 클래스들 모음 + Electron 또는 Tauri + 스태틱 PHP 런타임
  • 윈도우/메뉴/파일 관리
  • DB(SQLite) 지원
  • 네이티브 Notification

 

PHP로 데스크탑 어플리케이션을 개발할 수 있는 프레임워크가 출시되었다고 하길래, 냅다 설치해봤습니다.

현재 맥/우분투 환경만 지원하며, 맥 장비가 없는 관계로 우분투 22.04 환경에서 설치를 시도해봤습니다.

 

NativePHP는 단독으로 구성할 수 없으며, 사전에 Laravel 설치가 필요합니다.

아래와 같은 절차로 진행합니다.

$ composer create-project laravel/laravel test-app
$ cd test-app
$ composer require nativephp/electron
$ php artisan native:install

 

하지만, php artisan native:install 실행시 아래와 같은 오류가 발생합니다.

 

 

오류 내용으로 미루어 볼 때, 리눅스 환경임에도 불구하고 Mac용 PHP 바이너리를 참조하려고 시도하는것으로 보입니다.

 

 

해당 디렉토리에는 x64 디렉토리도 존재하지 않는것을 알 수 있습니다.

아직 우분투에서는 개발할 수 있는 환경이 갖추어지지 않은 것으로 보입니다.

 

나중에 Mac 장비를 구하게 되면 다시 시도해보거나, 우분투 대응 업데이트를 해주길 기다리는 방법밖에 없을듯 합니다.

PHP NativePHP Ubuntu

서비스 응답속도 저하시 php-fpm 로그로 원인분석하기

php-fpm 기반의 웹 서비스에서 알 수 없는 문제로 응답속도가 저하되는 현상이 발생 할 경우가 종종 있다.

원인은 여러가지일 수 있다. 몇 가지를 꼽자면,

  1. DBMS의 SQL 응답속도 저하 (Slow Query)
  2. 네트워크 지연
  3. 서버 리소스 점유율 (CPU, RAM 등)
  4. Disk 입출력 문제

등이 있다.

하지만, 서버 리소스나 네트워크에 별 다른 문제가 없고, Slow Query 로그에도 별다른 이상징후가 없다면,
원인분석을 해야 하는데, 이 경우 Web Application에서 어느 로직에서 문제가 발생하는지 원인을 찾아야 한다.

개발환경이라면 Xdebug를 활용 수 있겠지만, 실 서비스 중인 서버에는 적용할 수 없는 방법이다.

이 때는 php-fpm의 slowlog를 찍어서 확인하는 방법이 있다.

php-fpm.conf 파일을 열어보면 아래와 같은 설정을 확인할 수 있다.

......
request_slowlog_timeout = 30s
slowlog = /var/log/php-fpm/slow.log
......

여기서 request_slowlog_timeout을 3~5s 정도로 낮추고, php-fpm 서비스를 재시작한다.

그 후 tail 명령으로 /var/log/php-fpm/slow.log 를 확인 후 응답속도가 느린 페이지에 접속을 계속 시도해보면 다음과 같은 로그가 찍힌다.

[10-Nov-2018 11:30:22]  [pool www] pid 8260
script_filename = ******************
[0x00007f1a47de79a8] fopen() ****.php:422
[0x00007f1a47de6500] +++ dump failed

이 로그에는 응답속도 저하의 원인이 되는 파일과 해당 function까지 추적해주기 때문에 원인을 금방 파악할 수 있다.

DevOps 장애조치 PHP php-fpm Linux