Eu fiz o hash de cada palavra duas vezes para contá-la apenas uma vez
Eu fiz o profiling de um parser de logs na semana passada. Ele conta códigos de erro em um log diário. A lógica principal é uma simples atualização de dicionário.
A maioria dos desenvolvedores escreve assim:
if (counts.TryGetValue(code, out int c))
counts[code] = c + 1;
else
counts[code] = 1;
Este código faz o hash da chave duas vezes. O TryGetValue encontra a entrada calculando o hash e percorrendo o bucket. Em seguida, o indexador faz exatamente o mesmo trabalho novamente para atualizar o valor. Você desperdiça ciclos de CPU na mesma chave e no mesmo hash duas vezes por token.
Você pode pular a segunda etapa. Use CollectionsMarshal.GetValueRefOrAddDefault.
ref int slot = ref CollectionsMarshal.GetValueRefOrAddDefault(counts, code, out _);
slot++;
Este método encontra ou cria o slot em uma única etapa. Ele fornece uma referência diretamente ao armazenamento. Você realiza um hash e uma busca no bucket. Então, você altera o valor no local (in place).
Eu testei isso com 5 milhões de tokens.
Resultados: • TryGetValue + indexador: 160,0 ms • GetValueRefOrAddDefault: 95,0 ms
A versão de uma única busca é 1,7x mais rápida.
Crucialmente, as alocações de memória permaneceram idênticas. Este truque não economiza memória. Ele apenas economiza CPU. Se o seu código está lento devido à coleta de lixo (garbage collection), esta mudança não fará nada. Se o seu código está lento devido a contagens intensas, isso ajuda.
Use isso quando o seu loop realizar muitas atualizações em chaves existentes. O benefício aumenta conforme a proporção de atualizações em relação às inserções cresce.
Um aviso: A referência aponta para o armazenamento interno do dicionário. Ela só permanece válida até a próxima alteração estrutural. Não mantenha a referência se você adicionar ou remover chaves. Obtenha a ref, altere o valor e siga em frente.
Use TryGetValue para a maioria das tarefas. É mais fácil de ler. Use a versão com ref apenas quando o loop do seu dicionário for um gargalo de desempenho.
Fonte: https://dev.to/ssukhpinder/i-hashed-every-word-twice-to-count-it-once-1mg9
