Usuário com melhor resposta
Travamento usando o Dictionary com muitos itens ...

Pergunta
-
Private MyList As Dictionary(Of UInteger, UInteger)
Private Sub FillList()
MyList = New Dictionary(Of UInteger, UInteger)
For tb As Integer = 1 To 6000
For dCol As Integer = 1 To 130
For dLin As Integer = 1 To 500
Dim thisNumber As UInteger = MyNumber(dCol, tb, dLin)
If Not MyList.ContainsKey(thisNumber) Then
MyList.Add(thisNumber, thisNumber)
RaiseEvent NewNumber(byval tb, dCol, dLin, myList.Count)
If MyList.Count >= 49000820 Then
Exit Sub End If
End If
Next
Next
Next
End Sub
No código acima, a função MyNumber retorna um numero que pode variar de 1 a 48.000.820.
É possível que o mesmo número seja gerado outra vez, em outra iteração.
O número é adicionado â collection, se já não tiver sido adicionado antes.
Se a collection for preenchida com todos os números possíveis, a Sub é encerrada.
Caso contrário, todos os For...Next são executados até o fim.
Ao final, vou processar os números armazenados em outra rotina.
Pode parecer estranho estar usando Dictionary para armazenar números inteiros, mas é a única Collection em que a velocidade de processamento não diminui â medida que o número de items aumenta.
ArrayList e List(of T) consumiram tempo demais, testei com os métodos .Contains, IndexOf e .Find.
Também testei armazenando em DataTable mas a performance foi ainda pior (como eu esperava).
O Dictionary precisa estar aberto na memória para que seja possível verificar "se já tem".
Ficou com velocidade bem satisfatória.
O problema é que, quando o Dictionary atinge uma determinada quantidade (uns 30 e poucos milhões) a máquina congela. Esperei uns 30 minutos e não liberou.
Reparei também que, durante a execução, mesmo sendo rápida, se eu apenas mexer o mouse, a máquina congela por alguns segundos e depois retorna.
Mas no travamento dos 30 e poucos milhões é preciso desligar o micro na marra.
Alguém poderia indicar um modo melhor (= que processe até o fim, sem perder velocidade e sem congelar) de fazer isso?
P.S: estou rodando de dentro do Visual Studio 2010. O debugger não capta nenhum erro, parece que está processando mas alguma sobrecarga ocorre com o micro
Processador i7, 8GB RAM
Obrigado pelas respostas.
- Editado Alexander-2014 segunda-feira, 20 de janeiro de 2014 18:26
Respostas
-
- Sugerido como Resposta Diego de Almeida Barreto (Lewis) segunda-feira, 20 de janeiro de 2014 19:43
- Marcado como Resposta Giovani Cr segunda-feira, 27 de janeiro de 2014 17:12
Todas as Respostas
-
-
Resumindo:
Estou usando uma collection tipo Dictionary para armazenar números que vão de um até quase 50 milhões.
O Dictionary tem que estar carregado TODO na memória, porque, antes de armazenar, tenho que pesquisar se já tem, para não armazenar duas vezes o mesmo número.
Testei com diversos modos de armazenamento: List(of T), ArrayList, DataTable e até gravando em BD.
Em todos eles a pesquisa (para ver se já tem antes de armazenar) fica lenta demais.
Com o Dictionary, a velocidade ficou perfeita.
O problema: quando o Dictionary está muito grande (cerca de 35.000.000) , em um determinado momento, o sistema pára, e o micro fica "congelado".
O debugger do VS não interrompe a execução, como acontece quando dá erro de Memory Overflow.
Parece que continua executando alguma tarefa (talvez redimensionando o Dictionary...) mas demora um tempo enorme ou infinito. Esperei 40 minutos e nada aconteceu, tive que desligar o micro no botão, pois tudo fica congelado.
Preciso de alguma idéia para processar isso de modo eficiente, mesmo que tenha que mudar a lógica do programa.
Obrigado pelas respostas.
-
- Sugerido como Resposta Diego de Almeida Barreto (Lewis) segunda-feira, 20 de janeiro de 2014 19:43
- Marcado como Resposta Giovani Cr segunda-feira, 27 de janeiro de 2014 17:12