모듈:타이밍.
Module| 이 모듈은 베타 등급으로 널리 사용될 준비가 되었습니다.아직 새 제품이므로 결과가 예상대로 나오도록 주의하여 사용해야 합니다. |
이 모듈의 목적은 Lua-기능의 성능 튜닝을 위한 간단한 타이밍 분석 방법, 즉 기능의 프로파일링을 제공하는 것입니다.일반적으로 함수 호출의 지속 시간을 측정하는 것은 병목 현상과 문제가 있는 코드를 식별하기 위한 더 큰 노력의 일부입니다.현재 설정에서는 라인 추적(콜 그래프 프로파일링)을 수행할 수 없으므로 이는 완전한 프로파일러가 아닙니다.실행 시간(플랫 프로파일링)을 측정하고 디버그 콘솔(즉, 단일 기능)에서 대화식으로 실행하는 것이 유일한 목적입니다.
이 텍스트에서 여러 번 언급했듯이 타이밍은 정확하지 않으며 함수의 대략적인 실행 시간과 부하에 대한 대략적인 측정으로만 사용해야 합니다.모듈을 모듈의 최대 허용 시간 슬롯에 맞게 미세 조정하려고 하지 마십시오. 제한치를 훨씬 밑돌아야 합니다!
타이밍 분석은 실행 가능한 함수를 사용하여 호출되며, 선택적으로 각 테스트 세트의 카운트(크기, 기본값 100)와 이러한 테스트 세트의 수(기본값 10)를 사용할 수 있습니다.총 호출 수는 카운트 × 집합이며 함수의 평균 런타임을 제공합니다.표준 편차는 집합 수에서 계산되며 대략적인 추정치만 됩니다.단일 세트로만 실행할 경우 표준 편차는 사라지지만 측정되지 않더라도 실행 시간은 계속 달라집니다.
프로파일러는 총 호출에 대해 두 번의 패스를 수행합니다. 하나는 더미 함수이고 다른 하나는 실제 함수입니다.이를 통해 추가 코드의 무게에 대한 기준선을 얻을 수 있으며 나중에 테스트 중인 함수의 측정에서 이 값을 뺄 수 있습니다.테스트 대상 함수가 너무 단순하면 실행 시간이 가까워지고 차이의 불확실성이 높을 수 있습니다.실행 시간이 표준 편차와 유사한 경우에는 더 크거나 더 많은 집합으로 분석을 다시 실행해야 합니다.
개발 과정에서 일반적으로 10개 세트에 100개의 통화가 있으면 좋은 추정치를 얻기에 충분하지만, 이러한 수치에 지나치게 많은 비중을 두지는 않는다는 것이 분명해졌습니다.한 기능이 두 번, 트리 시간이 두 번, 심지어 10배 더 느리더라도 일정한 시간 또는 선형 시간으로 실행되는 한 신경 쓰지 마십시오.무언가가 100배 더 느리거나 지수 시간에 실행된다는 징후가 있는 경우 다른 알고리즘을 고려해야 합니다.
사용.
이 모듈은 일반 템플릿이나 페이지에서 모듈 페이지의 편집 창 아래 디버그 콘솔에서 사용할 수 없습니다.샌드박스 환경에서 모듈을 사용하려면 아래를 자세히 살펴보십시오.
일반 함수 테스트
예를 들어 Module: 페이지를 연다고 가정합니다.예를 들어, 우리는 p.hello() 함수를 프로파일링하기 위해 호출을 작성할 수 있습니다.페이지의 코드는 아래 예시와 비슷하지만, 로컬 버전은 조금 다를 수 있습니다. (현재 비슷한 코드는 w:no:에 있습니다.)모듈:Hello World2.)
다음 코드는 모듈의 분해된 버전입니다.예를 들면.전체 버전은 페이지를 참조하십시오.
현지의 p = {}; p.안녕하세요. = 기능.( 틀 ) 현지의 스트르 = "헬로 월드!" 돌아가다 스트르 끝. 돌아가다 p 이 코드에 대한 액세스는 디버그 콘솔의 일반 p를 통해 이루어집니다.프로파일러가 다음과 같이 호출될 수 있다고 가정합니다.
=요구하다 '모듈:타이밍'(p.안녕하세요.) 같은 유형의 모듈에 대해 생성된 것과 같은 통화는 엔위키에서 다음과 같은 보고서입니다.
= '모듈:Timing'(p.hello) 각 통화는 약 1.2e-09초 동안 실행되었습니다.각 세트의 평균 런타임은 1.2e-07초였고 표준 편차는 1.9e-06초, 최소 8.9e-06초, 최대 1.5e-05초였습니다.총 소요 시간은 약 2.5e-04초였습니다.상대 하중은 1.0으로 추정됩니다.
여기서 중요한 정보는 입니다.이것은 기능이 실제로 실행되는 시간을 나타냅니다.
이 함수는 매우 간단하므로 함수의 실행 시간이 기준선의 실행 시간에 가깝습니다.따라서 각 세트의 실행 시간이 표준 편차에 가까워집니다.
인수를 사용한 테스트
테스트 호출에는 추가 인수가 필요할 수 있습니다.테스트 중인 기능에 변경되지 않은 항목을 전달합니다.가장 중요한 것은 복제되지 않았다는 것입니다. 즉, 그대로 전달되므로 테스트 중인 함수가 이를 변경하면 오류가 누적됩니다.이 문제는 함수, 테이블, 사용자 데이터 및 스레드 유형에 대해 발생할 수 있습니다.우리는 위키피디아에서 사용자 데이터와 스레드를 사용하지 않습니다.이렇게 하면 값에 의해 전달된 0, 부울, 숫자 및 문자열이 그대로 유지되며 변경에 대해 안전합니다.
문자열은 참조로 전달되지만, 불변이며 쓰기 시 복사본이 있습니다.
인수를 전달하는 방법에 대한 일반적인 예는 현재 프레임에 대해 이 작업을 수행하는 방법입니다.
=요구하다 '모듈:타이밍'(p.안녕하세요., mw.현재 프레임 가져오기()) 그러면 다음과 같은 출력이 생성됩니다.
= '모듈:Timing'(p.hello, mw.getCurrentFrame()) 각 통화는 약 3.0e-09초 동안 실행되었습니다.각 세트의 평균 런타임은 3.0e-07초였고 표준 편차는 2.0e-07초, 최소 4.8e-06, 최대 5.2e-06이었습니다.총 소요 시간은 약 1.2e-04초였습니다.상대 하중은 1.1로 추정됩니다.
이와 같은 인수를 사용하는 것은 추가적인 부하를 크게 부과하지 않으며, 대부분은 인수 분해될 수 있습니다.
래퍼 함수를 사용한 테스트
호출에 추가 설정 또는 매개 변수가 필요한 경우 래퍼 기능으로 제공할 수 있습니다.이는 다음과 같은 추가 함수로 함수를 마무리한 다음 결과 함수의 타이밍을 조정하여 수행할 수 있습니다.
매우 간단한 기능에 포장지를 추가하지 마십시오. 이러한 예에서 분명히 알 수 있듯이 타이밍이 많이 멀어질 것입니다.
디버거의 래퍼
래퍼 함수는 디버깅을 위해 텍스트 영역에 추가되는 디버거에서 정의할 수 있습니다.다음과 같은 별도의 기능을 추가합니다.
기능. 싼다() 돌아가다 p.안녕하세요.(mw.현재 프레임 가져오기()) 끝. =요구하다 '모듈:타이밍'(싼다) 그와 같은 통화 시퀀스는 다음과 같은 출력을 생성했습니다.
function wrap () p.hello(mw.getCurrentFrame()) end =require '모듈:Timing'(랩) 각 통화는 약 1.9e-07초 동안 실행되었습니다.각 세트의 평균 런타임은 1.9e-05초였으며 표준 편차는 3.4e-07초, 최소 6.7e-06, 최대 7.3e-06이었습니다.총 소요 시간은 약 3.7e-04초였습니다.상대 하중은 3.7로 추정됩니다.
통화 시간은 맨 기능 자체보다 훨씬 더 길다는 점에 유의하십시오.검사된 기능이 약간 무거워야 합니다. 그렇지 않으면 포장지가 결과를 지배하게 됩니다.
익명 기능이 있는 대체 양식은 다음과 같습니다.
=요구하다 '모듈:타이밍'(기능.() 돌아가다 p.안녕하세요.(mw.현재 프레임 가져오기()) 끝.) 일반적으로 당신은 이와 같이 루프 내부에서 불필요한 계산을 피하기 위해 가능한 한 사전 계산을 해야 합니다.
나의_틀=mw.현재 프레임 가져오기() =요구하다 '모듈:타이밍'(기능.() 돌아가다 p.안녕하세요.(나의_틀) 끝.) 모듈의 래퍼
때때로 포장지를 모듈 자체에 넣는 것이 더 좋습니다.
나의 목적 = {}; 나의 목적.안녕하세요. = 기능.( 틀 ) 현지의 스트르 = "헬로 월드!" 돌아가다 스트르 끝. 나의 목적.싼다 = 기능. () 돌아가다 나의 목적.안녕하세요.(mw.현재 프레임 가져오기()) 끝. 돌아가다 나의 목적 그것은 다음과 같은 결과를 낳았습니다.
= '모듈:Timing'(p.wrap) 각 통화는 약 1.9e-07초 동안 실행되었습니다.각 세트의 평균 런타임은 1.9e-05초였으며 표준 편차는 7.0e-06초, 최소 6.3e-06초, 최대 7.1e-06초였습니다.총 소요 시간은 약 3.7e-04초였습니다.상대 하중은 4.0으로 추정됩니다.
또한 이 포장지는 테스트된 기능 자체에 비해 상당히 무겁습니다.
일반적으로 당신은 이와 같이 루프 내부에서 불필요한 계산을 피하기 위해 가능한 한 사전 계산을 해야 합니다.
나의 목적 = {}; 나의 목적.안녕하세요. = 기능.( 틀 ) 현지의 스트르 = "헬로 월드!" 돌아가다 스트르 끝. 나의 목적.틀 = mw.현재 프레임 가져오기() 나의 목적.싼다 = 기능. () 돌아가다 나의 목적.안녕하세요.(나의 목적.틀) 끝. 돌아가다 나의 목적 샌드박스 환경에서 테스트
테스트 중인 모듈이 샌드박스로 설정된 경우 이는 특수:MyPage/sandbox의 경우 디버거를 직접 사용할 수 없으므로 모듈 자체에 테스트를 넣어야 합니다.교체 모듈이 있는 경우 요구 사항 및 도우미 기능을 추가합니다.
때때로 포장지를 검사 대상 모듈 자체에 넣는 것이 좋습니다.
현지의 타이밍. = 요구하다 '모듈:타이밍' 나의 목적 = {}; 나의 목적.안녕하세요. = 기능.( 틀 ) 현지의 스트르 = "안녕, 세상!" 돌아가다 스트르 끝. 나의 목적.타이밍. = 기능. (틀) 돌아가다 타이밍.(나의 목적.안녕하세요.) 끝. 돌아가다 나의 목적 특수에서 사용할 수 있습니다.특수의 접두사가 있는 템플릿 샌드박스:MyPage/sandbox 및 "Render Page"는 목적에 적합합니다.Wikidata 항목과 같은 추가 데이터에 액세스할 수 있는 특정 페이지가 필요한 경우가 많습니다.도우미 기능에 대한 호출을 입력합니다.
{{#호출 HelloWorld TIMING}}그리고 우리는 모듈에 도우미 호출에 대한 타이밍 보고서를 가질 것입니다.
가젯
추가 가젯이 있습니다(계속...).
이것이 정말 유용한지 확실하지 않습니다. 다시 이 문제로 돌아갈 것입니다.
주의사항
단순한 함수는 실행 시간에 기준에 가까워지고 그 때문에 매우 시끄러울 것입니다.평균을 계산할 때 우리는 실제로 저주파 필터링을 수행하여 고주파 노이즈를 제거합니다.그래도 노이즈가 발생할 수 있으며 이를 방지할 수 있는 유일한 방법은 더 긴 주행(더 큰 세트와 더 많은 세트)을 수행하는 것입니다.최대 실행 시간과 최소 실행 시간이 서로 너무 멀거나 표준 편차가 커지면 서버의 로드 상황이 양호한 결과를 얻기 어려울 가능성이 매우 높습니다.
한 줄 또는 두 줄로 구성된 함수는 기준 함수보다 분수가 느릴 수 있지만 함수 호출을 몇 개 추가하면 부하가 폭발합니다.
기능이 매우 간단한 경우에는 타이밍 정보를 사용합니다.함수가 다소 복잡할 경우 상대 부하 정보를 사용합니다.
측정값이 수상해 보이면 신뢰하지 말고 본능을 믿으십시오.특히, 단순한 경우에 매우 유망해 보이더라도 철저한 조사 없이 고차 기능을 사용하지 마십시오!
참고 항목
- w:en:평균 코드는 산술 평균을 사용합니다.
- w:en:표준 편차 코드는 분산 및 표준 편차를 사용합니다.
- w:en:정규 분포 랜덤 변수의 합 코드는 지연이 독립적인 무작위 발생이라고 가정하지만, 이는 그다지 옳지 않습니다.
모듈 타이밍 개별 기능 @라이센스(CC-BY-SA-3.0) @john Erling Blad <jeblad@gmail.com > 기자 @var 이 모듈이 들어 있는 테이블에서 멤버를 내보냈습니다. 현지의 p = { ['_count'] = 100, ['_sets'] = 10, } 각 세트의 항목 수에 대한 액세스 함수 @param number 각 세트의 새 항목 수 @각 세트의 항목 반환 수 기능. p.세어보세요( 번호 ) 한다면 번호 그리고나서 주장하다(번호>0, "'num'의 값은\'t는 0이 됩니다.") p._카운트 = 번호 끝. 돌아가다 p._카운트 끝. 세트 수에 대한 액세스 함수 @param number 새 집합 수 @반품 세트 수 기능. p.놓다( 번호 ) 한다면 번호 그리고나서 주장하다(번호>0, "'set'의 값은\'t는 0이 됩니다.") p._세트 = 번호 끝. 돌아가다 p._세트 끝. 시계열에 대한 통계량 계산 및 평균 및 분산 이 계산에 대한 배경 정보는 [w:en:average] 및 [w:en:en:average]를 참조하십시오.표준 편차] @parameterable timing은 일련의 시간 차이입니다. @평균 및 분산의 반환 표 기능. p.통계학( 타이밍. ) 현지의 minVal = 타이밍.[1] 현지의 maxVal = 타이밍.[1] 현지의 sqr,의미하다=0,0 위해서 i,v 에 짝을 짓다(타이밍.) 하다, 하다, 하다, 하다, 하다, 하다, 하다, 하다, 나다 minVal = v < minVal 그리고. v 또는 minVal maxVal = v > maxVal 그리고. v 또는 maxVal 의미하다 = v + 의미하다 sqr = 수학.pow(v,2) + sqr 끝. 의미하다 = 의미하다 / #타이밍. 현지의 넝쿨 = (sqr / #타이밍.) - 수학.pow(의미하다,2) 돌아가다 { 의미하다, 넝쿨, minVal, maxVal } 끝. 각 반복 청크에 대해 시간을 들이면서 제공된 함수를 반복하는 러너 반복의 커널인 @param 함수 함수 func @지정된 함수에 대한 런타임 테이블 반환 기능. p.달리기 선수(펑크, ...) 함수를 측정합니다. 현지의 시간을 = {} 위해서 i=1,p._세트 하다, 하다, 하다, 하다, 하다, 하다, 하다, 하다, 나다 시간을[i] = os.clock() 위해서 j=1,p._카운트 하다, 하다, 하다, 하다, 하다, 하다, 하다, 하다, 나다 펑크(...) 끝. 시간을[i] = os.clock() - 시간을[i] 끝. 주장하다(#시간을>0, "시간 측정 항목 없음") 돌아가다 시간을 끝. 치수를 조합하여 새로운 형태로 만듭니다. 이 계산에 대한 배경 정보는 w:en:정규 분포 랜덤 변수의 합] @기준에 대한 매개 변수 눈금 통계 @관측된 함수에 대한 매개 변수 택 통계 @결합된 통계가 있는 반환 표, 분산에서 표준 편차로 이동 기능. p.결합하다(똑딱이, 압정을) 기준선의 실제 측정값 조정 돌아가다 { 압정을[1] - 똑딱이[1], 수학.pow(압정을[2] + 똑딱이[2], 0.5), 똑딱이[3], 똑딱이[4] } 끝. 주자가 만든 결과에 대한 형식 @평균 및 표준 편차로서의 모수적 타이밍 @결과를 설명하는 반환 문자열 기능. p.신고( 타이밍. ) 현지의 메시지 = {} 메시지['호출 결과'] = 각각의 통화는 약 1달러 동안 실행되었습니다.\n' 메시지['결과 확인'] = '\t각 세트의 평균 런타임은 $1초였습니다.\n\t$2초의 표준 편차로,\n\t최소 3달러, 최대 4달러.\n' 메시지['결과 확인'] = '\t총 소요 시간은 약 1달러였습니다.\n' 메시지['부하 결과'] = '상대 부하는 1달러로 추정됩니다.'\n' 현지의 기능. g( 열쇠, ...) 현지의 메시지 = mw.메세지.신규( '1987-' .. 열쇠 ) 한다면 메시지:is Blank() 그리고나서 메시지 = mw.메세지.새 원시 메시지( 메시지[열쇠] ) 끝. 돌아가다 메시지 끝. 현지의 기능. f(형식 문자열, 숫자들) 현지의 정형화된 = {} 위해서 _,v 에 짝을 짓다(숫자들) 하다, 하다, 하다, 하다, 하다, 하다, 하다, 하다, 나다 정형화된[1+#정형화된] = string.형식( 형식 문자열, v ) 끝. 돌아가다 정형화된 끝. 현지의 줄들 = { g('호출 결과'):numParams(짐을 풀다(f('.1e', 타이밍.[1]))):평지(), g('결과 확인'):numParams(짐을 풀다(f('.1e', 타이밍.[2]))):평지(), g('결과 확인'):numParams(짐을 풀다(f('.1e', 타이밍.[3]))):평지(), g('부하 결과'):numParams(짐을 풀다(f('%.1f', 타이밍.[4]))):평지() } 돌아가다 테이블.콘캣(줄들, '') 끝. 기준 측정에 사용되는 더미 함수 @리턴 제로 기능. p.절대로() 돌아가다 영의 끝. 수출에 적합한 현지의 mt = { runner인 것처럼 인수가 있는 테이블의 호출 형식 » @반복의 커널인 paramfunction func @결과를 설명하는 반환 문자열 __통화 = 기능. (자신, 펑크, ...) 같은 수준으로 결심함 현지의 f1 = p.절대로 현지의 f2 = 펑크 시계를 맞추다 현지의 똑딱이 = os.clock() 현지의 베이스라인 = 자신.통계학( 자신.달리기 선수(f1, ...) ) 현지의 실제. = 자신.통계학( 자신.달리기 선수(f2, ...) ) 현지의 합쳐진 = 자신.결합하다(베이스라인, 실제.) 현지의 압정을 = os.clock() 돌아가다 자신.신고({{ 합쳐진[1] / p._카운트 }, 합쳐진, { 압정을 - 똑딱이 }, {실제.[1]/베이스라인[1]}}) 끝. } 메타테이블을 설치합니다. 상을 차리다(p, mt) 완성된 돌아가다 p