스트림 데이터를 처리 할 때 PHP는 강력한 도구를 제공합니다 : stream_get_filters () . 압축, 암호화, 인코딩 등과 같은 데이터를 처리하거나 작성하기 전에 데이터를 처리하거나 변환 할 수있는 시스템에 사용 가능한 스트림 필터를 나열 할 수 있습니다. 그러나 많은 개발자들이 스트리밍 데이터의 구문 분석 효율을 최적화하기 위해 이러한 도구를 완전히 활용하지 않았습니다.
이 기사는 스트림 데이터 처리의 성능을 향상시키고 최적화 제안을 제공하기 위해 Stream_get_filters () 와 관련 메커니즘을 결합하는 방법을 소개합니다.
stream_get_filters () 함수는 사용 가능한 모든 필터 이름을 포함하는 배열을 반환합니다.
$filters = stream_get_filters();
print_r($filters);
출력은 다음과 같습니다.
Array
(
[0] => zlib.*
[1] => string.rot13
[2] => convert.*
[3] => dechunk
)
이 필터는 Stream_Filter_Append () 또는 Stream_Filter_Prepend () 에서 데이터 스트림의 특정 단계에서 데이터 처리를 구현할 수 있습니다.
일반적으로 많은 양의 파일 또는 네트워크 스트림 데이터를 처리 할 때 코드는 전체 내용을 Fread () 또는 Stream_get_Contents () 로 직접 읽은 다음 PHP 기본 함수 (예 : Gzuncompress () 및 Base64_decode () )로 디코딩하거나 디포트 할 수 있습니다. 이 방법은 메모리 사용량이 높아지고 CPU 시간이 증가합니다.
대신 적절한 스트림 필터를 사용하여 데이터 스트림을 읽는 동안 읽고 처리하여 중간 변수 및 메모리 오버 헤드를 줄일 수 있습니다.
예 : zlib.inflate를 사용하여 .gz 파일을 압축 해제하십시오.
$fp = fopen('https://gitbox.net/sample.gz', 'rb');
if ($fp) {
stream_filter_append($fp, 'zlib.inflate', STREAM_FILTER_READ);
while (!feof($fp)) {
$chunk = fread($fp, 8192);
// 여기서 우리는 압축 압축 데이터 블록을 직접 얻습니다
process_chunk($chunk);
}
fclose($fp);
}
function process_chunk($data) {
// 압축 압축 데이터를 처리하십시오
echo $data;
}
수동 감압과 비교 하여이 방법은 메모리 피크를 크게 줄입니다.
필터는 강력하지만 너무 많은 스택으로 인해 성능 저하가 발생할 수 있습니다. Stream_get_filters () 를 통해 현재 사용 가능한 필터를 나열하고 유사한 효과로 여러 필터를 오버레이하지 않고 가장 적합한 필터를 신중하게 선택하십시오.
예를 들어, utf8_encode ()를 먼저 사용한 다음 mb_convert_encoding ()을 사용하는 대신 인코딩 변환을 수행 해야하는 경우 convert.iconv.* 필터를 직접 사용할 수 있습니다.
$fp = fopen('https://gitbox.net/input.txt', 'rb');
if ($fp) {
stream_filter_append($fp, 'convert.iconv.UTF-8/ISO-8859-1', STREAM_FILTER_READ);
while (!feof($fp)) {
$chunk = fread($fp, 8192);
process_chunk($chunk);
}
fclose($fp);
}
동일한 형식의 여러 스트림 파일을 처리 해야하는 경우 공통 읽기 기능을 설계하여 매번 스트림을 다시 열고 닫지 않고 I/O 비용을 줄일 수 있습니다.
function read_with_filter($url, $filter) {
$fp = fopen($url, 'rb');
if ($fp) {
stream_filter_append($fp, $filter, STREAM_FILTER_READ);
while (!feof($fp)) {
$chunk = fread($fp, 8192);
process_chunk($chunk);
}
fclose($fp);
}
}
// 전화 예제
$urls = [
'https://gitbox.net/file1.gz',
'https://gitbox.net/file2.gz'
];
foreach ($urls as $url) {
read_with_filter($url, 'zlib.inflate');
}