Estruturas de Dados
Probabilísticas para lidar com
   DADO PRA CARAMBA


Juan Lopes
@juanplopes
Bloom Filters (1970)
Hit Counting (1990)
HyperLogLog (2007)
Detectar duplicações


indexar(documento):
  se documento não está indexado:
    lucene.indexar(documento)
Detectar duplicações


indexar(documento):
  se documento não está indexado:
    lucene.indexar(documento)
Consultar no disco?
Consultar no disco?
Consultar em memória?
              HashSet<T>
Consultar em memória?




      100M ids
Consultar em memória?



  100M ids × 32 chars / id
Consultar em memória?


 100M ids × 104 bytes / id
        > 10GB
Consultar em memória?


 100M ids × 104 bytes / id
        > 10GB
Bloom Filters

      I had a big data problem,
  "I know, I'll use a bloom filter."
Now I'm not sure how many
problems I have, but I know
   which ones I don't.
Bloom Filters


    Adicione!(item)

     Contém?(item)
Bloom Filters


     Contém?(item)
       não 100%
       sim ~95%
Bloom Filters
                       0
   x
                h(x)
                       0


                       1


                       0


                       0


                       0


                       0


                       0
Bloom Filters
                        1
   x
                 h(x)
                        0


                        1

          h(y)
                        0
   y

                        0


                        0


                        0


                        0
Bloom Filters
                        1
   x
                 h(x)
                        0


                        1

          h(y)
                        0
   y

                        0


                        0

         h(z)
   z                    0


                        0
Bloom Filters

adicionar!(item):
  V[hash(item)] ← 1

contém?(item):
  retorne V[hash(item)] = 1
Bloom Filters


      100M itens
    2Gbits (256MB)
      5% de erro
Bloom Filters
                           g(x)   1
   x
                          h(x)
                                  0


          h(y)                    1


                                  0
   y
                 g(y)
                                  0

        h(z)                      1


   z                    g(z)      0


                                  1
Bloom Filters
adicionar!(item):
  para cada hash em hashes:
    V[hash(item)] ← 1

contém?(item):
  para cada hash em hashes:
    se V[hash(item)] = 0:
      retorne falso
  retorne verdadeiro
Bloom Filters

       100M itens
   4 funções de hash
   625Mbits (78MB)
      5% de erro
Bloom Filters

       100M itens
   5 funções de hash
     1Gbit (128MB)
      1% de erro
Bloom Filters

       100M itens
   7 funções de hash
    2Gbit (256MB)
    0.01% de erro
Bloom Filters

 Probabilidade de falso
       positivo:
Cardinalidade


 Quantos ips distintos
  acessaram o site na
     última hora?
Cardinalidade



Qual a cardinalidade do
       stream S?
Consultar em memória?
              HashSet<T>
Usando HashSet

adicionar!(item):
  S ← S ∪ { item }

quantos?:
  retorne |S|
Consultar em memória?




  >10K eventos/s
Consultar em memória?


> 10K eventos/s × 3.600s/h
× 100 bytes / evento
       > 3GB/h
Consultar em memória?


> 10K eventos/s × 3.600s/h
× 100 bytes / evento
       > 3GB/h
Hit Counting
                n/10 bits
-c log (z/c)   2% de erro
Hit Counting
                n/10 bits
-c log (z/c)   2% de erro


36M eventos
3.6Mbits
450KB
Hit Counting
adicionar!(item):
  V[hash(item)] ← 1

quantos?:
  z ← número de zeros em V
  c ← tamanho de V
  retorne -c × log(z/c)
HyperLogLog


Contar até 1 bilhão
  de elementos
  usando 1.5KB
Hash



       "To hash" é
        "espalhar"
Hash

  04 = 00000100
  08 = 00001000
  12 = 00001100
  16 = 00010000
Hash
It is theoretically impossible to define a
   hash function that creates random
 data from non-random data in actual
 files. But in practice it is not difficult to
    produce a pretty good imitation of
               random data.

                           Donald Knuth
HyperLogLog
      Qual a
probabilidade dos n
   primeiros bits
   serem 0...01?
HyperLogLog

1xxxxxxx -> 50%
01xxxxxx -> 25%
001xxxxx -> 12.5%
0001xxxx -> 6.25%
HyperLogLog
 Dado que existe uma
   palavra com os n
     primeiros bits
     0...01, qual a
cardinalidade provável?
HyperLogLog

1xxxxxxx -> 2
01xxxxxx -> 4
001xxxxx -> 8
0001xxxx -> 16
HyperLogLog



 Multiplas funções de
        hash?
HyperLogLog



  Dividir o stream em
    "m" substreams
HyperLogLog
          01100010
           i=3 v=4

  0   0   0   4   0   0   0   0
  0   1   2   3   4   5   6   7
HyperLogLog

 21   22   20   24   20   25   20   20
  1   2    0    4    0    5    0    0
  0   1    2    3    4    5    6    7
HyperLogLog

  2   4   1   16   1   32   1   1
  1   2   0   4    0   5    0   0
  0   1   2   3    4   5    6   7
HyperLogLog



          M(i)
      2          , i<m
HyperLogLog



               M(i)
 Ê = média(2          , i<m)
HyperLogLog



                   M(i)
 Ê = m × média(2          , i<m)
HyperLogLog


  Ê = αm × m × média(2M(i), i<m)
      α m=
HyperLogLog


  Ê = αm × m × média(2M(i), i<m)
      α m=


       αm= (0.7213 / (1 + 1.079 / m))
HyperLogLog
adicionar!(item):
 x ← hash(item)
 i ← log2m primeiros bits de x
  v ← pos. do primeiro 1 nos bits restantes de x
  M(i) ← max(M(i), v)

quantos?:
  retorne αm × m × média(2M(i), i<m)
HyperLogLog
        média aritmética:
   (M(0) + M(1) + ... + M(m-1)) / m

        média geométrica:
    (M(0) × M(1) × ... × M(m-1))1/m

        média harmônica:
  m / (M(0)-1 + M(1)-1 + ... + M(m-1)-1)
HyperLogLog
  Cada registro de M tem 5 bits.
       Por isso "LogLog":
                   32
        log2(log2(2 )) = 5
   Registradores         Erro
         m             (104/√m) %
  m = 2048 (1.25KB)      2.3%
  m = 65536 (40KB)       0.4%
 m = 1048576 (648KB)      0.1%
HyperLogLog


      Para baixas
 cardinalidades, o erro
   relativo aumenta.
HyperLogLog
quantos?:
  Ê ← αm × m × média(2M(i), i<m)
  se Ê < 2.5 × m:
    z ← número de zeros em M
    retorne -m × log(z/m)
  senão:
    retorne Ê
HyperLogLog
  1   2   2   4   0   5   0   0
  0   1   2   3   4   5   6   7



  5   0   1   0   5   2   3   1
  0   1   2   3   4   5   6   7
HyperLogLog
  1   2   2   4   0   5   0   0
  0   1   2   3   4   5   6   7



  5   0   1   0   5   2   3   1
  0   1   2   3   4   5   6   7




  5   2   2   4   5   5   3   1
  0   1   2   3   4   5   6   7
Referências
Space/Time Trade-offs in Hash Coding with Allowable Errors (Bloom Filters)
http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.20.2080



A Linear-Time Probabilistic Counting Algorithm for Database Applications
http://dblab.kaist.ac.kr/Publication/pdf/ACM90_TODS_v15n2.pdf



HyperLogLog: the analysis of a near-optimal cardinality estimation algorithm
http://algo.inria.fr/flajolet/Publications/FlFuGaMe07.pdf



Hashing Explained - Google Guava
http://code.google.com/p/guava-libraries/wiki/HashingExplained



StreamLib
https://github.com/clearspring/stream-lib

dnarj-20120630