여전히 트위터 트렌드를 가지고 놀고 있습니다. 처리 속도를 높이고 싶을 만큼 충분한 데이터를 수집했습니다. 추세 단어로 인덱싱된 연관 배열을 사용하여 각 추세 단어에 정수 인덱스를 할당하고 싶습니다. 아래에는 테이블에 새 단어를 추가하거나 이전 단어에 대한 색인을 가져오는 세 가지 기술이 있습니다.
첫 번째는 TRY를 사용하여 단어가 테이블에 없을 때 예외를 포착합니다. 단어가 있으면 가장 빠르고 예외가 발생하면 가장 느립니다.
두 번째는 CONTAINS를 사용하여 단어가 있는지 테스트한 다음 추가하거나 찾습니다. 더하기는 가장 빠르고 조회는 가장 느립니다(두 번 조회하기 때문입니다.)
마지막은 연관 배열 기본값을 사용하여 검색된 값이 이미 존재하는지 확인합니다. 그것은 좋은 타협 속도를 제공합니다.
모든 예제에는 두 번 실행되는 "t" 루프가 있습니다. 처음 xN 배열이 비어 있고 채워야 합니다. 두 번째로 모든 값이 이미 존재합니다.
// Three ways to build a lookup table. No clear winner!
// Goal: assign an integer, starting at 1, to each new
// entry. For timing purposes, use the integer as the
// key and the value. The key will be a string in real
// code. The value will be used as an index elsewhere.
explain = {"create new entry","use existing entry"};
N = 1e5; // several seconds at 1e5
/*
Use TRY to determine when an entry needs to be created.
On the "catch" create the entry. If there is no catch,
the value is already fetched. The "t" loop runs 20X
slower the first time because the "catch" is expensive.
But the second time the "t" loop is the fastest solution.
*/
x1 = [=> ];
For( t = 1, t <= 2, t += 1,
start = HP Time();
For( ix = 1, ix < N, ix += 1,
Try( y = x1[ix], y = (x1[ix] = ix) )
);
stop = HP Time();
Write( Eval Insert( "\!nTry method: ^char((stop - start)/1e6,5,3)^ seconds ^explain[t]^" ) );
);
/*
Use CONTAINS to determine if the entry needs to be created.
Use the if's "then" clause to fetch the existing index or
"else" clause to create a new entry. The "t" loop has the
fastest speed on the first run, by far, and the slowest
speed on the second run.
*/
x2 = [=> ];
For( t = 1, t <= 2, t += 1,
start = HP Time();
For( ix = 1, ix < N, ix += 1,
If( Contains( x2, ix ),
y = x2[ix],
y = (x2[ix] = ix)
)
);
stop = HP Time();
Write( Eval Insert( "\!nContains method: ^char((stop - start)/1e6,5,3)^ seconds ^explain[t]^" ) );
);
/*
Use a DEFAULT value to determine if the entry needs to be
created. Fetch the value for the entry, check for the default
and create if needed. This gives an between value for both
"t" loops. It might be a good compromise choice if no extra
testing will be done and 0 can be used as a default. !y,
below, is faster than y==0.
*/
x3 = [=> 0];
For( t = 1, t <= 2, t += 1,
start = HP Time();
For( ix = 1, ix < N, ix += 1,
y = x3[ix];
If( !y, y = (x3[ix] = ix) );
);
stop = HP Time();
Write( Eval Insert( "\!ndefault 0 method: ^char((stop - start)/1e6,5,3)^ seconds ^explain[t]^" ) );
);
// quick test... the lack of a default value in x1 and x2
// makes them compare not equal, so add it before testing.
x1 << setdefaultvalue( 0 );
x2 << setdefaultvalue( 0 );
Show( x1 == x2, x1 == x3 );
시도 방법: 2.851초 새 항목 만들기
시도 방법: 0.099 초 기존 항목 사용
포함 방법: 0.209 초 새 항목 만들기
포함 방법: 0.151초 기존 항목 사용
기본 0 방법: 0.259 초 새 항목 만들기
기본 0 방법: 0.117 초 기존 항목 사용
x1 == x2 = 1;
x1 == x3 = 1;
빨간색으로 표시된 TRY 및 CONTAINS는 기존 및 새 항목에 대한 가장 빠른 시간을 제공합니다. 녹색에서는 DEFAULT 0이 적절한 절충안일 수 있습니다. 얼마나 많은 항목이 생성되고 조회되는 횟수에 따라 달라집니다.
알림 주셔서 감사합니다! 내 예제에서 허용 가능한 값 집합을 벗어난 기본값을 선택했으므로 기본값으로 실제로 유용하지 않습니다. 0은 내 조회에 유효하지 않은 색인입니다. 누락으로 시작했는데 isMissing(x)이 x==0보다 비쌉니다.
현재 일부 REST API 관련 작업을 하고 있으며 이로 인해 기본값과 동일한 값을 가진 연관 배열 및 키 제거 나는 기본값을 사용하거나 사용하지 않을 것입니다. JMP 사용자를 위한 대화형 UI를 구축하기 위해 JSON 응답을 사용하는 이유는 "기본값"이 있더라도 키가 필요합니다. 하지만 이 게시물 이후에는 Try to check for missing key를 사용하는 게으른 옵션을 사용하지 않을 것 같습니다.
더보기...