2017-11-16 1 views
0

저는 현재 펄 프로그램의 마이크로 최적화를하고 있으며 일부 게터를 최적화하려고합니다. GetABC 호출Perl, 변수의 별칭

package Test; 

our $ABC; 

sub GetABC { $ABC } # exported sub... 

() 부와 관련된 오버 헤드가 많이 생성한다

는 I이 게터 구조의 패키지가있다. $ Test :: ABC를 통해 직접 변수에 액세스하는 것은 매우 빠릅니다.

변수를 직접 호출하는 것처럼 동일한 성능 향상을 얻으려면 변수에 getter의 별명을 지정하는 방법이 있습니까? "()"로 힌트를 사용하면 작동하지 않는 것 같습니다 ...

+1

얼마나 자주이 차이가 실제로 중요합니까? – Sobrique

+0

약 100k :-) 그것은 30-40ms의 차이입니다 (현재의 시나리오에서는 상당히 큽니다). – xsign

+0

값을 현재 네임 스페이스에 아마도 가져올 수 있습니까? '$ Test :: ABC'를 참조하는 것과 관련된 이슈는 무엇입니까? – Sobrique

답변

5

변수를 접근 자 sub로 바꾸거나 하위를 변수 액세스로 바꾸는 방법은 없습니다. 오버 헤드를 가지고 살아야합니다. 이 프로토 타입은 단지 인라인 잠재적 자격이 하위 을 만들기 때문에 일정 액세스에 대한 귀하의 하위에 전화를 설정하지 않는 () 프로토 타입을 사용

  • :

    비 솔루션을 제공합니다. 하위의 본문 자체는 상수가 아니므로이 하위는 상수가 될 수 없습니다.

  • 오버 헤드는 perl이 각 호출에 대해 상당한 부기를 수행해야하므로 호출 당 오버 헤드입니다. 따라서 XS에서 해당 액세서를 다시 작성하면 많은 도움이되지 않습니다.

  • constant을 생성하면 상수가 변수의 별칭이 아니기 때문에 도움이되지 않습니다.

그러나 constant.pm source code은 흥미로운 해결책을 제시합니다. 참고로 해킹 해킹이 가능하며 모든 버전의 Perl에서 작동하지 않을 수 있습니다 : 심볼 테이블 엔트리에 스칼라 심판을 할당 할 때 그 엔트리가 아직 타입 그램을 포함하지 않는 경우, 인라인 가능 서브가 자리에 튀어 나옵니다 :

package Foo; 
use strict; 
use warnings; 
use feature 'say'; 

my $x = 7; 
BEGIN { $Foo::{GetX} = \$x } # don't try this at home 
say GetX; #=> 7 
$x = 3; 
say GetX; #=> 3 

현재 설치된 대부분의 perl 버전 (5.14, 5.22, 5.24, 5.26)에서 작동합니다. 그러나 "5.20-multi 및 5.26-multi는"읽기 전용 값의 수정을 시도했습니다. " 이는 참조 대상을 읽기 전용으로 만들고 (더 중요하게는) 결코 변수를 수정하지 않기 때문에 상수 모듈에서는 문제가되지 않습니다.

이렇게하면 안정적으로 작동하지 않을뿐만 아니라 상수 폴딩이 완전히 엉망이됩니다. 함수 호출 오버 헤드 (예를 들어 당신의 처리 시간의 두 자릿수 비율 소요) 참으로 참기 어려운 경우


, 다음 하여 소스 코드에서 자신을 인라인하는 것이 가장 좋은 될 것입니다 일. 전화 위치가 많더라도 쉬운 케이스를 수정하는 간단한 스크립트를 만들 수 있습니다. 모듈을 가져 오는 모든 파일을 선택하고 단 하나의 package 선언 만 있습니다. 이러한 파일 내에서 GetABC (괄호 포함 또는 제외)에 대한 호출을 정규화 된 변수 액세스로 바꿉니다. 그 토큰이 어떤 문자열에서도 언급되지 않기를 바랍니다. 그런 다음 이러한 호출의 남은 발생을 수동으로 검사 할 수 있습니다.

+0

아주 좋은 답변을 주셔서 감사합니다. 내 5.12.3-multi는 그 변수를 쓰는 것을 허용하지 않습니다 ... 나는 행운이없이 여러 가지 다른 것들로 몇 시간을 보았습니다. 모든 패키지에서 메소드 호출을 검색하고 바꾸는 것이 가장 좋은 방법입니다 (적어도 현재는 필요합니다). – xsign

관련 문제