Ho il seguente scenario:grande manipolazione array è molto lento in Ruby
Ho bisogno di capire la lista unica di ID in un grande set.
Così, ad esempio, ho 6000 matrici di ID (elenco seguaci), ognuna delle quali può avere una dimensione compresa tra 1 e 25000 (la loro lista di follower).
Desidero ottenere l'elenco univoco di ID su tutti questi array di ID (seguaci unici di follower). Una volta fatto, devo sottrarre un'altra lista (un'altra lista di follower di persone) di id e ottenere un conteggio finale.
Il set finale di ID univoci cresce a circa 60.000.000 di record. In ruby quando si aggiungono gli array al grande array, inizia a diventare molto lento circa un paio di milioni. L'aggiunta al set richiede inizialmente 1 minuto e poi aumenta di oltre 4 secondi a 2 milioni (non dove vicino a dove devo andare).
Ho scritto un programma di test in Java e fa tutto in meno di un minuto.
Forse sto facendo questo inefficientemente in ruby, o c'è un altro modo. Dal momento che il mio codice principale è proprietario Ho scritto un semplice programma di test per simulare il problema:
big_array = []
loop_counter = 0
start_time = Time.now
# final target size of the big array
while big_array.length < 60000000
loop_counter+=1
# target size of one persons follower list
random_size_of_followers = rand(5000)
follower_list = []
follower_counter = 0
while follower_counter < random_size_of_followers
follower_counter+=1
# make ids very large so we get good spread and only some amt of dupes
follower_id = rand(240000000) + 100000
follower_list << follower_id
end
# combine the big list with this list
big_array = big_array | follower_list
end_time = Time.now
# every 100 iterations check where we are and how long each loop and combine takes.
if loop_counter % 100 == 0
elapsed_time = end_time - start_time
average_time = elapsed_time.to_f/loop_counter.to_f
puts "average time for loop is #{average_time}, total size of big_array is #{big_array.length}"
start_time = Time.now
end
end
Eventuali suggerimenti, è il momento di passare a JRuby e spostare roba come questa per Java?
Volevo solo fai notare che hai avuto 'loop_counter = 0' nella sezione dei tempi. Mentre l'approccio di accesso all'array è ** molto più lento ** rispetto all'approccio hash suggerito, il tempo di ciclo non cresce così velocemente. Con 2 milioni di record, il tempo di loop triplica a circa 0,27 secondi sulla mia macchina, da un tempo di ciclo iniziale di 0,09 secondi. –
Ruby è molto veloce, lo stai solo facendo nel modo sbagliato. Questo è davvero un caso d'uso per un database, non una manipolazione di array in memoria in nessuna lingua. Un buon DBM può trovare rapidamente valori e associazioni distinti, tutti prima che la query esca dal database. Raccomanderò [Sequel] (http://sequel.rubyforge.org/) come un ottimo database ORM che renderà più semplice la manutenzione e l'interrogazione. –