Я работаю над проектом, где я обрабатываю много твитов; цель заключается в удалении дубликатов при их обработке. У меня есть идентификаторы твитов, которые входят в виде строк формата "166471306949304320"
Я использовал для этого HashSet<String>
, который отлично работает некоторое время. Но к тому времени, когда я доберусь до 10 миллионов предметов, я резко увяз, и в итоге получаю ошибку GC, по-видимому, от перефразирования. Я попытался определить лучший размер/нагрузку с помощью
tweetids = new HashSet<String>(220000,0.80F);
и это позволяет ему немного дальше, но по-прежнему мучительно медленным (примерно на 10 миллионов это занимает в 3 раза больше времени для обработки). Как я могу это оптимизировать? Учитывая, что у меня есть приблизительное представление о том, сколько элементов должно быть в наборе к концу (в данном случае около 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, но он разбился чуть более 1 миллиона записей; перераспределение массивов было проблематичным. Я использовал HashSet<Long>
для лучшего эффекта и почти сделал это, но скорость заглохла и, наконец, разбилась на последнем этапе обработки (около 19 миллионов). Решение пришло с выходом из стандартной библиотеки и с помощью Trove. Он закончил 22 миллиона записей на несколько минут быстрее, чем вообще не проверял дубликаты. Окончательная реализация была простой и выглядела так:
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;
}