많은 트윗을 처리중인 프로젝트에서 작업하고 있습니다. 목표는 내가 처리 할 때 중복을 제거하는 것입니다. 트위터 ID는 형식의 문자열로 제공됩니다. "166471306949304320"
Java : 대규모 중복 검색을 위해 해시 세트 최적화
나는이 동안 HashSet<String>
을 사용해 왔는데 잠시 동안 잘 작동합니다. 그러나 내가 약 1 천만 가지 항목에 도달 할 때까지 나는 심하게 휘청 거려 결국 GC 오류를 일으켰습니다. 아마도 아마도 다시 해싱에서 발생했을 것입니다. 나는
tweetids = new HashSet<String>(220000,0.80F);
와 더 나은 크기/부하를 정의하는 시도하고는 조금 더 멀리를 얻을 수 있지만 여전히 (약 1000 만은 처리 한 배를 복용에 의한) 극심한 느립니다. 이것을 어떻게 최적화 할 수 있습니까? 마지막으로 얼마나 많은 항목이 있어야하는지에 대한 대략적인 아이디어가 있다고 가정하면 (이 경우 약 20-22 백만), 두 번 또는 세 번 다시 충돌하는 HashSet을 생성해야하며, 그렇지 않은 경우에는 오버 헤드가 발생합니다. 너무 많은 시간 벌칙이 부과됩니까? String을 사용하지 않거나 다른 HashCode 함수 (String의 특정 인스턴스에 대해이 작업을 수행하는 방법을 모르겠다)를 정의하면 더 쉽게 작동할까요? 구현 코드의이 부분은 아래와 같습니다. 당신의 권고
tweetids = new HashSet<String>(220000,0.80F); // in constructor
duplicates = 0;
...
// In loop: For(each tweet)
String twid = (String) tweet_twitter_data.get("id");
// Check that we have not processed this tweet already
if (!(tweetids.add(twid))){
duplicates++;
continue;
}
솔루션
덕분에, 나는 그것을 해결했다. 문제는 해시 표현에 필요한 메모리 양이었습니다. 첫째, HashSet<String>
은 방대한 숫자로 String.hashCode()
이 엄청 났기 때문에 간단하고 엄청나게 열성적이었습니다. 다음으로 Trie를 시도했지만, 100 만 개가 넘는 항목에서 충돌했습니다. 배열을 재 할당하는 것은 문제가있었습니다. 나는 더 나은 효과를 내기 위해 HashSet<Long>
을 사용했으나 거의 만들었지 만 속도가 떨어지며 마침내 처리의 마지막 단계 (약 1900 만 건)에 추락했습니다. 해결책은 표준 라이브러리를 벗어나 Trove을 사용하는 것입니다. 그것은 중복을 전혀 점검하지 않는 것보다 2200 만개의 기록을 몇 분 빨리 마쳤습니다. 최종 구현은 간단했다,이 모습 :
import gnu.trove.set.hash.TLongHashSet;
...
TLongHashSet tweetids; // class variable
...
tweetids = new TLongHashSet(23000000,0.80F); // in constructor
...
// inside for(each record)
String twid = (String) tweet_twitter_data.get("id");
if (!(tweetids.add(Long.parseLong(twid)))) {
duplicates++;
continue;
}
ID 번호를 숫자로 취급하고, 좋은 기본 가치를 찾고, 그 차이점을 다루는 방법은 어떻습니까? 그런 다음 문자열을 능가해야하는'HashSet '을 사용할 수 있습니다. Trove 라이브러리를 사용하여 프리미티브를 처리 할 수도 있습니다. –
단순히 힙의 크기를 늘릴 수 없습니까? – assylias
집합에 결국 2200 만 개의 항목이 포함될 것이라는 것을 알고 있다면 처음부터 22_000_000/0.75 용량의 HashSet을 만들면 어떨까요? 그것은 재탕을 막을 것입니다. –