2009-10-19 3 views
5

파일에서 데이터베이스로 데이터를로드하는 성숙한 코드 본문이 있습니다. 몇 가지 파일 형식이 있습니다. 그것들은 모두 고정 너비 필드입니다.Perl의 고정 폭 데이터 처리 속도를 높이려면 어떻게해야합니까?

코드의 일부는 Perl unpack() 함수를 사용하여 입력 데이터의 필드를 패키지 변수로 읽습니다. 비즈니스 로직은 이러한 필드를 '사람이 읽을 수있는'방식으로 참조 할 수 있습니다.

파일 읽기 코드는 파일을 읽기 전에 한 번 형식 설명에서 생성됩니다. 스케치 형태에서

는, 생성 된 코드는 다음과 같습니다

while (<>) { 

    # Start of generated code. 

    # Here we unpack 2 fields, real code does around 200. 
    ($FIELDS::transaction_date, $FIELDS::customer_id) = unpack q{A8 A20}; 

    # Some fields have leading space removed 
    # Generated code has one line like this per affected field. 
    $FIELDS::customer_id =~ s/^\s+//; 

    # End of generated code. 

    # Then we apply business logic to the data ... 
    if ($FIELDS::transaction_date eq $today) { 
     push @fields, q{something or other}; 
    } 

    # Write to standard format for bulk load to the database. 
    print $fh join('|', @fields) . q{\n} or die; 
} 

코드를 프로파일 링 시간의 약 35 %가 압축을 풀고에서 소비와 최고의 공간 스트립 것을 알 수있다. 남은 시간은 데이터의 유효성을 확인하고 변형하고 출력 파일에 쓰는 데 소요됩니다.

런타임의 1 ~ 2 % 이상 소요되는 비즈니스 로직의 단일 부분이없는 것처럼 보입니다.

질문은 - 언 패킹과 공간 제거에서 조금 더 빠른 속도를 낼 수 있습니까? 가급적이면 FIELDS 패키지 변수를 참조하는 모든 코드를 리팩터링하지 않아도됩니다.

편집 :이 차이를 만드는

경우

$ perl -v 
This is perl, v5.8.0 built for PA-RISC1.1 
+0

압축 해제의 왼쪽에 패키지 변수 목록을 사용하는 것이 최적 일 수 있는지 알고 싶습니다. –

답변

1

예. substr을 사용하여 추출하는 것이 가장 빠른 방법입니다. 즉,

$FIELDS::transaction_date = substr $_, 0, 8; 
$FIELDS::customer_id  = substr $_, 8, 20; 

이 더 빠를 수 있습니다. 자,이 코드를 필자가 작성했다면, 나는 unpack을 포기하지 않을 것입니다. 그러나 코드를 생성하는 경우, 코드를 작성하고 측정 할 수도 있습니다.

는 선행 공백을 제거에 관해서는 Is Perl’s unpack() ever faster than substr()?

에 대한 답변을 참조 s/^\s+// 가장 빠른 방법이 될 가능성이 높습니다.

업데이트 : 벤치 마크를 실행할 수 없으면 명확한 말을하기가 어렵습니다. 그러나, 방법에 대한 : 모든 트리밍과 트리밍이 필요합니까

my ($y) = substr($_, 8, 20) =~ /\A\s+(.+?)\s+\z/; 

필요하지 않은 분야에 대한

my $x = substr $_, 0, 8; 

?

+0

실험하고보고 해 드리겠습니다. –

+3

한 가지주의해야 할 점은 'A'는 '공짜로'공백을 제거한다는 것입니다. –

+0

지금까지 유망 해 보인다. 기본 벤치마킹은 일련의 per-field substrs와 strip trailing regexes가 하나의 언팩을 사용하는 것보다 약 50 % 더 빠르다는 것을 보여줍니다. 테스트는 끝났지 만 화면은 Perlish 경고로 가득차 있기 때문에 아직 그다지 좋지 않습니다. –

7

나는 실제로이 문제를 반복해서 다뤘다. Unpack is better than substr.

박리 공간이가는 한, 당신은 거의 망했다. 정규식 해킹은 그것을 수행하는 "공식적인"방법입니다. 압축 해제 문을 수정하면 효율성을 높일 수 있습니다 (데이터가 4 자리 이상 있다고 가정하고 필드의 12 자리 전체를 압축 해제하는 이유는 무엇입니까?). 그렇지 않으면 파싱은 단지 p.i.t.a입니다.

평이한 데이터로 행운을 비네. 내가 그것을 싫어하는 방법, 레크 리 에이션 정크를 Fricking.

3

이 작업에 프로세서가 연결되어 있습니까? 계산은 전체 프로세스가 I/O 경계 일 가능성이 높습니다. 이 경우 빠른 압축 풀기를 위해 최적화하면 시간이 많이 걸리지 않습니다.

사실 프로세서에 바인딩되어있는 경우에 설명 된 문제는 거의 병렬 처리가 가능하지만 악마는 비즈니스 계산의 세부 사항에 있습니다.

+0

예, 확실합니다. 실제 코드에서는 위의 화분에 표시된 예제와 달리 I/O 및 압축 풀기가 구분되어 있습니다. 병렬 처리는 좋은 호출입니다. 우리는 이미 그렇게했습니다. 그래도 문자열을 잘게 자르기에 더 적은 시간을 보내고 싶습니다. –

+2

나를 위해 가장 큰 병목은 데이터베이스 자체입니다. 편평한 데이터를 다루는 경우, 끔찍한 고대의 평범한 데이터베이스를 다루는 것일 수도 있습니다. 나는 간격을두고 현대 데이터베이스로 데이터를 끌어 와서 문제를 해결하지만, "실시간"데이터의 경우 거의 항상 느려짐을 야기하는 데이터베이스입니다. – Satanicpuppy

+0

동의합니다. 전반적으로 우리의 프로세스는 대부분의 시간을 데이터를 데이터베이스에 쏟아 붓고 있습니다.우리는 이것을 가속화하기 위해 병렬 프로세스를 사용할 수 있습니다. 'Perl-time'의 상당 부분이 코드의 작은 부분에 사용 되었기 때문에 여기서 쉽게 최적화 할 수있는 범위가 될 수 있다고 생각했습니다. –

1

이것은 또한 XS에서 뭔가 일 수 있습니다. 따라서 C 함수를 사용하여 데이터를 변경할 수 있습니다. 데이터가 실제로 복사 될 때 수동으로 제어 할 수 있기 때문에 이것이 다른 어떤 것보다 훨씬 빠르다는 것을 상상할 수 있습니다.
C 컴파일러에 종속되므로 빌드 프로세스가 더 어려워지고 추가 통합 단계가 필요합니다.

+0

감사합니다. 아마 내 프로젝트에 이득이 추가 복잡성을 정당화하지 않을 것입니다. 사탄 픽스피 (Satanicpuppy)가 말한 것처럼, 이보다 더 비싼 과정의 다른 부분들이 있습니다. 그래도 비슷한 문제가있는 다른 사람을 위해 일할 수 있습니다. –

+3

CPU 시간의 대부분이 정규식 엔진과 내장 함수에 소비되면 대부분의 시간은 C 랜드에서 사용됩니다 (즉, 옵트 리를 보거나 펄 데이터 구조를 처리하지 않음). 그리고 Perl VM을 작성한 사람들을 이기기 위해서는 좋은 프로그래머가 필요합니다. 포장을 풀면 빠릅니다! – tsee

1

간단히 병렬 처리하십시오. 그것은 사소한 일이며, 멀리 떨어져있는 현대의 머신이라면 더 빠를 것입니다.

0

우리 코드의 substr 기반 버전의 벤치 마크는 기존 포장 풀기보다 약 50 % 빠르다는 것을 제안했습니다. 실제 응용 프로그램에서 코드를 비교할 때 substr 버전은 런타임에서 16 % 감소했습니다. 이것은 벤치 마크와이 질문에서 언급 한 프로파일 링을 기반으로 우리가 바라는 것에 가깝습니다.

이 최적화가 유용 할 수 있습니다. 그러나 우리는 새로운 OS 로의 이전을 기다리고 있으므로 진행하기 전에 코드가 어떻게 실행되는지 기다릴 것입니다. 우리는 비교 벤치 마크에 주목하기위한 테스트를 추가했습니다.

우리가 지금 가지고있는 관용구는 다음과 같습니다

$FIELDS::transaction_date = substr($_, 0, 8) || ''; 
$FIELDS::transaction_date =~ s/\s+\z//; 
$FIELDS::customer_id = substr($_, 8, 20) || ''; 
$FIELDS::customer_id =~ s/\s+\z//; 

가 이전과 선택적 선행 공백 제거 하였다.

지금까지 모든 답변 주셔서 감사합니다. 시안 (Sinan 's)은 ​​우리에게 도움이 되었기 때문에 시안 (Sinan 's)을 받아 들일 것입니다.