2016-08-17 2 views
1

나는 처리해야하는 매우 긴 라인을 가진 파일을 가지고 있는데, 버퍼가 너무 크지 않거나 매우 처리하기 때문에 긴 줄에는 시간이 좀 걸릴 수 있습니다. 코드 샘플은 다음과 같습니다.<> 연산자 버퍼 크기

open FH, "<$fname" or die "..."; 
while (<FH>) { 
    my @arr = split //, $_; 
    pop @arr; 
    pop @arr; 
    ... for some "limited small portion of the string length" number of times ... 
    pop @arr; 
    if ($arr[-1] eq '0') { 
     print "done!\n"; 
     last; 
    } 
    push @big_arr, join('', @arr); 
} 

줄 처리가 "무겁지"않습니다.

나는 그것을 해결하기 위해 무언가를 찾았으며 PerlIO::buffersize을 보았습니다. 그러나 지금은 잠시 동안 유지되지 않았기 때문에 버전 0.001의 모듈을 사용하고 싶지 않습니다. <> 연산자 버퍼 크기를 어떻게 수정할 수 있습니까? 또는, 선 길이를 알기 전에 <>으로 읽는 방법이 있습니까?

+0

여기에서 말하는 회선의 길이는 얼마나됩니까? 나는 '버퍼'크기가 특히 문제가되는 어떤 특별한 이유가 있다고 생각하지 않는다. - 필자는 레코드 분리 기호로이 구조체를 사용했다. 꽤 긴 '줄'이긴하지만 잘 작동한다. 당신이 느려지고있는 'while'루프가 확실합니까? – Sobrique

+0

@Sobrique 나는이 코드를 훨씬 더 짧은 줄이있는 파일에서 돌렸을 때, 그것을 마술처럼 작동 시켰고 정말 빨리 끝내었다. 줄이 너무 깁니다. 마치 하나 또는 두 줄로 압축 된 큰 텍스트 파일을 가진 것처럼 생각하십시오 (필자는 이러한 파일의 형식을 제어 할 수 없습니다). – yonyon100

+0

하지만 레코드 분리 기호'$ /'를 설정할 수 있습니다. 거기에 라인을 쪼갤 수있는 것이 있습니까? – Sobrique

답변

3

그것은 당신이 필요로하는 것은이 것을 할 수있다 :

$/ - 파일에서 읽을 바이트의 번호를, 숫자 값으로 설정할 수 있습니다. 스칼라 문자의 참조 정수되는 최대 레코드 크기, 대신 라인의 기록을 읽으려고합니다 정수로 변환의 정수, 또는 스칼라를 포함, 정수에 대한 참조로 $/설정

.

출처 : perlvar

+2

Perl의 내부 버퍼 크기는 변경되지 않지만 어쨌든 문제가되지는 않습니다. – Borodin

+1

OP는 여전히 데이터를 라인으로 읽으 려하므로 실제로 C에서 Perl로 어셈블하는 라인을 옮길 때 약간 더 느려집니다. – ikegami

3

변경 펄의 읽기 버퍼 크기는 프로그램의 속도에 상당한 차이를 만들 가능성이있다, 당신이보고있는 영향은 더 이상 읽기의 결과로 훨씬 더 가능성이 높습니다 디스크 드라이브 자체로부터의 시간. 에 Perl Read-Ahead I/O Buffering를 살펴 보자 perlmonks.org

또한, read를 사용하거나 고정 된 크기로 레코드 분리 $/을 설정하여 자신 만의 버퍼링을 구현, 당신은 여전히를 가지고, 프로그램을 느리게 할 가능성이보다 더 읽은 것을 별도의 줄로 나누지 만 이제 perl이 C에서 대신 할 펄 코드로 처리해야한다.

$/을 고정 레코드 크기로 변경하는 방법은 여전히 ​​Perl의 표준 , 아마 8KB, 버퍼. 만약 바이트 카운트 대신 세퍼레이터 문자열 난 <> 운영자 버퍼 크기를 수정하는 방법

1

의 위치에 따라 결정된다 유일한 차이점은 데이터 량이 다시 핸드이다?

<>는 어떤 크기로 성장할 수있는 스칼라로 읽고, 그래서 당신이 read 시스템 호출에 전달 된 버퍼의 크기를 언급하는 것 같아요.

5.14 이전에는 4KB의 청크 파일 핸들에서 Perl을 읽었습니다. 5.14에서는이 설정을 구성 할 수 있으며 기본값은 8KB입니다.

$ perl -e'print("x" x 9_999, "\n") for 1..2' >large_lines 

$ strace 5.10.1t/bin/perl -e'my $line = <>' large_lines 2>&1 | grep read.*xxx 
read(3, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"..., 4096) = 4096 
read(3, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"..., 4096) = 4096 
read(3, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"..., 4096) = 4096 

$ strace 5.14.2t/bin/perl -e'my $line = <>' large_lines 2>&1 | grep read.*xxx 
read(3, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"..., 8192) = 8192 
read(3, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"..., 8192) = 8192 
단지 다음 명령이 ( <> 별칭되는) readline read 포함하는 모든 버퍼링 된 읽기 기능에 적용

./Configure -Accflags=-DPERLIOBUF_DEFAULT_BUFSIZ=8192 

를 사용 perl가 구축 될 때 구성 될 수

, readpipeeof이지만 sysread은 아닙니다.


참고 번호에 대한 레퍼런스를 설정하는 단계를 $/readline (<>)가 여전히 버퍼링 read, 역할을 일으킬 것이다.

$ strace perl -e'$/ = \8193; my $block = <>' large_lines 2>&1 | grep read.*xxx 
read(3, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"..., 8192) = 8192 
read(3, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"..., 8192) = 8192 

실제로 하나의 read 시스템 호출을 수행 할 경우

, 당신은 sysread를 사용해야합니다.

$ strace perl -e'sysread(STDIN, $buf, 8193)' <large_lines 2>&1 | grep read.*xxx 
read(0, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"..., 8193) = 8193