PHP 세그먼트 에서 큰 파일 읽 기 및 통계
7511 단어 PHP
때때로 우 리 는 로그 의 한 IP 가 최근 에 사 이 트 를 방문 한 상황 을 통계 하기 위해 큰 파일 을 조작 하고 분석한다.nginx 의 assess. log 파일 은 방문 로 그 를 기록 하지만 이 파일 은 일반적으로 매우 크다.PHP 를 사용 하면 어떻게 안에 있 는 정 보 를 집계 합 니까?여기 서 스스로 학습 총 결 을 하나 하 다.
이론 적 방법:
1. 파일 을 한꺼번에 메모리 에 읽 은 다음 한 줄 한 줄 분석 합 니 다. 예 를 들 어 함수 fileget_contents, fread, file 모두 조작 할 수 있 습 니 다.
2. 단계별 로 내용 을 메모리 에 읽 고 한 단락 씩 분석 합 니 다. 예 를 들 어 함수 fgets
이 두 가지 방법 은 모두 우리 의 조작 을 현실 화 할 수 있다.먼저 첫 번 째, 한꺼번에 내용 을 읽는다.이 방법 은 비교적 간단 하 다. 로 그 를 메모리 에 읽 은 후에 배열 로 변환 한 다음 에 배열 의 모든 열 을 분석 하 는 것 이다.코드 는 다음 과 같 습 니 다:
", $content);
$writeres = fopen(WRITE_FILE_A, 'a+');
// WRITE_FILE
flock($writeres, LOCK_EX);
foreach($content_arr as $row)
{
if( strpos($row, "192.168.10.10") !== false )
{
fwrite($writeres, $row . "
");
}
}
$em = memory_get_usage();
flock($writeres, LOCK_UN);
fclose($writeres);
$et = microtime( true );
echo " file_get_contents: :" . ($et - $st) . "
";
echo " file_get_contents: :" . ($em - $sm) . "
";
}
writeLogA();
상기 코드 가 실 행 된 후에 IP 가 192.168.10.10 인 사용자 방문 로 그 를 임시 파일 에 쓸 수 있 습 니 다. 그러나 이때 문 제 는 코드 가 실 행 된 시간 과 소 모 된 메모리 가 매우 크다 는 것 입 니 다.특별 설명: 제 assets. log 는 크 지 않 습 니 다. 10 만 줄 정도 입 니 다. 여 기 는 프 리 젠 테 이 션 만 을 위 한 것 입 니 다. 실행 결 과 는 그림 과 같다.
현재 이 access. log 파일 은 크 지 않 습 니 다. 이미 이렇게 많은 시간 과 이렇게 큰 메모 리 를 소 모 했 습 니 다. 더 큰 파일 이 라면 요? 그래서 이런 방법 은 실 용적 이지 않 습 니 다.
또 다른 함수 fread 를 보십시오. fread 는 한 파일 의 내용 을 문자열 로 읽 는 것 입 니 다.
string fread ( resource $handle , int $length )
첫 번 째 매개 변 수 는 파일 시스템 포인터 입 니 다. fopen 에서 만 들 고 돌아 오 는 값 입 니 다. 두 번 째 매개 변 수 는 읽 을 크기 입 니 다.값 을 정확하게 읽 은 내용 으로 되 돌려 줍 니 다.
우 리 는 지금 위의 코드 중의 file 을get_contents 가 free ad 로 바 뀌 었 습 니 다.코드 는 다음 과 같 습 니 다:
", $content);
$writeres = fopen(WRITE_FILE_B, 'a+');
// WRITE_FILE
flock($writeres, LOCK_EX);
foreach($content_arr as $row)
{
if( strpos($row, "[error]") !== false )
{
fwrite($writeres, $row . "
");
}
}
$em = memory_get_usage();
flock($writeres, LOCK_UN);
fclose($writeres);
fclose($fopenres);
$et = microtime( true );
echo " fread: :" . ($et - $st) . "
";
echo " fread: :" . ($em - $sm) . "
";
}
writeLogB();
특별한 상황 이 없 으 면 이전 코드 보다 메모리 소모 가 더 클 것 이다.결과 그림 은 다음 과 같다.
이 점 은 PHP 공식 사이트 에서 도 한 파일 의 내용 을 문자열 에 읽 으 려 면 fileget_contents (), fread 보다 성능 이 훨씬 좋 습 니 다.https://www.php.net/manual/zh/function.fread.php
file 함수 도 할 수 있 습 니 다. 원 하 는 결 과 는 여기 서 프 리 젠 테 이 션 을 하지 않 습 니 다.file 함 수 는 하나의 파일 을 하나의 배열 에 읽 는 것 입 니 다.사실 위의 세 함수 의 원 리 는 모두 같다. 바로 큰 파일 을 한꺼번에 메모리 에 읽 는 것 이다. 분명히 이런 방식 은 메모 리 를 소모 하고 큰 파일 을 처리 할 때 이 방법 은 바람 직 하지 않다.
우 리 는 이론의 두 번 째 방법 을 다시 보고 단락 을 나 누 어 읽 었 다.이 방법 은 하나의 큰 문 서 를 몇 개의 작은 단락 으로 나 누 어 매번 한 단락 의 분석 을 읽 고 마지막 에 통합 시 켜 통 계 를 분석 하 는 것 이다.fgets 는 매번 한 줄 을 읽 는데, 마치 우리 가 원 하 는 것 같다.
string fgets ( resource $handle [, int $length ] )
첫 번 째 매개 변 수 는 파일 시스템 포인터 입 니 다. fopen 에서 만 들 고 돌아 오 는 값 입 니 다. 두 번 째 매개 변 수 는 읽 을 크기 입 니 다.length 가 지정 되 지 않 으 면 기본 값 은 1K 또는 1024 바이트 이 며, 값 을 정확하게 읽 은 내용 으로 되 돌려 줍 니 다.
지금 위의 코드 를 다시 한 번 수정 하 세 요.다음 과 같다.
";
echo " fgets: :" . ($em - $sm) . "
";
}
writeLogC();
실행 한 후에 메모리 가 많이 떨 어 진 것 을 발 견 했 지만 시간 은 여전히 같은 것 같 았 다.실행 결 과 는 다음 과 같 습 니 다.
왜 그 랬 을 까? 사실은 간단 하 다. 지금 은 한 줄 씩 메모리 에 읽 을 때마다 메모리 가 높 지 않 기 때문이다.그러나 어쨌든 상기 세 가지 방법 은 전체 파일 (10 만 줄) 을 한 번 순환 해 야 하기 때문에 시간 이 지나 면 세 가지 방법 은 크게 다 르 지 않다.그럼 더 좋 은 방법 없 을까요?다 중 스 레 드 를 사용 하여 큰 파일 을 작은 파일 로 나 누고 모든 스 레 드 에서 작은 파일 을 처리 하 는 것 입 니 다. 그러면 시간 이 많이 줄 어 들 것 입 니 다.
PHP 는 기본적으로 다 중 스 레 드 모듈 이 설치 되 어 있 지 않 습 니 다. 스스로 설치 해 야 합 니 다.설치 되 어 있 지 않 습 니 다. 확인 하 십시오. https://www.yduba.com/biancheng-6852262344.html
지금 위의 방법 에 따라 코드 를 다음 과 같은 방법 으로 바 꿉 니 다.
i = $i;
}
public function run()
{
$filename = "temp_log_" . Thread::getCurrentThreadId();
$cutline = ($this->i - 1) * 40000 + 1 . ", " . ($this->i * 40000);
exec("sed -n '" . $cutline . "p' " . READ_FILE . " > " . $filename);
$this->_writeTemp( $filename );
}
private function _writeTemp( $readfile = '' )
{
if( !$readfile || !file_exists($readfile) ) return;
$fileres = fopen($readfile, 'r');
$writeres = fopen(WRITE_FILE_D, 'a+');
// WRITE_FILE
flock($writeres, LOCK_EX);
while( $row = fgets($fileres) )
{
if( strpos($row, "[error]") !== false )
{
fwrite($writeres, $row);
}
}
flock($writeres, LOCK_UN);
fclose($fileres);
fclose($writeres);
unlink( $readfile );
}
}
function writeLogd()
{
$st = microtime( true );
$sm = memory_get_usage();
$count_line = 0;
//
$content = exec('wc -l ' . READ_FILE);
$content_arr = explode(" ", $content);
$count_line = $content_arr[0];
//
$count_thread = ceil($count_line / 40000);
$worker = array();
for($i=1; $i<=$count_thread; $i++)
{
$worker[$i] = new Mythread( $i );
$worker[$i]->start();
}
$em = memory_get_usage();
$et = microtime( true );
echo " : :" . ($et - $st) . "
";
echo " : :" . ($em - $sm) . "
";
}
writeLogd();
운행 해 보 니 시간 이 수직 으로 떨 어 지 는 것 을 발견 했다.메모리 도 줄 었 다.실행 결과 그림:
특히 스 레 드 수가 많 을 수록 좋 은 것 은 아니다.스 레 드 수량 이 많 으 면 모든 스 레 드 에서 처리 하 는 시간 이 적 습 니 다. 그러나 스 레 드 를 만 들 때 도 시간 을 낭비 합 니 다. 저 는 여기 서 스 레 드 마다 4 만 개의 기록 을 처리 합 니 다. 이 수 를 줄 이거 나 증가 시 켜 결 과 를 테스트 할 수 있 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
laravel에 yo에서 angularJs&coffeescript를 사용할 수 있도록 한다.먼저 yo 명령을 사용할 수 있어야하므로 아래에서 설치 global에 설치한 곳에서 laravel의 프로젝트 루트로 이동. 클라이언트 코드를 관리하는 디렉토리를 만들고 이동합니다. 클라이언트 환경 만들기 이것으로 히...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.