spaghettiwires calc

Dimensionamento della cache per lo storage

Hai uno storage capiente ma lento e vuoi metterci davanti un livello veloce, per esempio degli SSD davanti ai dischi meccanici o a uno storage a oggetti. Indica quanti dati muovi ogni giorno e che velocità di lettura vuoi ottenere in media: ti diciamo quanto deve essere grande la cache e per quanto tempo deve tenere i dati.

MB/s

È il numero che conta di più. Sta tra la velocità del secondo livello e quella del primo: più ti avvicini al primo, più la cache deve crescere.

Il tuo carico di lavoro
GB/giorno

Quanti dati nuovi arrivano ogni giorno.

GB/giorno

Quanti dati leggi ogni giorno, in tutto.

giorni

Ogni quanti giorni si dimezza la probabilità di rileggere un dato. A spanne: per quanti giorni continui a lavorarci dopo averlo scritto.

Quando torni su un dato vecchio

Accesso puntuale: un cliente ti chiede di rimandargli una fattura del 2002, gliela mandi e la cosa finisce lì. Rifare il lavoro: ripeschi dei dati vecchi per rielaborarli con tutta la pipeline, e tornano attuali anche quelli vicini.

Primo livello: la cache
MB/s

Quando il dato è in cache.

ms

Tempo di risposta quando il dato è in cache.

GB

Capacità grezza di ciascun dispositivo della cache.

Secondo livello: lo storage
MB/s

Quando il dato non è in cache e va preso da qui.

ms

Tempo di risposta del secondo livello, prima di iniziare a trasferire.

MB

Quanti dati passano in cache a ogni miss: la dimensione del blocco, o quella media dei file se vengono letti per intero.

[[ t.error_title ]]

[[ errorText ]]

[[ t['stat_' + s.k] ]]
[[ s.v ]]
[[ t['stat_' + s.k + '_help'] ]]
[[ t.chart_title ]]
[[ tk.label ]] [[ tk.label ]] [[ t.axis_x ]] [[ fmt(t.marker_label, { size: gb(result.size) }) ]]

[[ hoverPoint.speed ]]

[[ t.tooltip_size ]]: [[ hoverPoint.size ]]

[[ t.tooltip_hit ]]: [[ hoverPoint.hit ]]

[[ fmt(t.chart_note, { speed: speed(values.speed1) }) ]]

[[ t.table_toggle ]]

[[ t.table_help ]]

[[ t.table_hit ]] [[ t.table_speed ]] [[ t.table_days ]] [[ t.table_size ]]
[[ speed(row.target) ]] [[ smart(row.days) ]] [[ gb(row.size) ]]

Come funziona

Il calcolatore considera due livelli di storage: uno piccolo e veloce, la cache, e uno grande e lento, dove stanno davvero i dati. Ogni lettura che trova il dato in cache va alla velocità del primo livello, le altre a quella del secondo. La velocità media dipende quindi dalla quota di letture che trovano il dato in cache: lo hit ratio.

Lo hit ratio che serve

Tra due velocità la media giusta è quella armonica, perché a sommarsi sono i tempi di lettura, non le velocità. Con v1 la velocità del primo livello, v2 quella del secondo e T l'obiettivo, lo hit ratio p che serve è:

1 / T = p / v1 + (1 − p) / v2

p = v1 · (T − v2) / (T · (v1 − v2))

Per quanto tenere i dati in cache

Il modello assume che un dato venga usato molto appena scritto e sempre meno col tempo, con un calo esponenziale: dopo un'emivita h la probabilità di rileggerlo si è dimezzata. Se la cache tiene ogni dato per t giorni, la quota di letture che arriva dopo, e quindi finisce sul secondo livello, è 2^(−t/h). Perché non superi 1 − p:

t = h · log₂(1 / (1 − p))

Quanto grande

In quei t giorni la cache deve contenere i dati scritti (W al giorno) più quelli letti (R al giorno). Quanto pesano le letture dipende da cosa succede quando torni su un dato vecchio. Se è un accesso puntuale, come rimandare a un cliente una vecchia fattura, leggi quel dato e la cosa finisce lì: conta una volta sola. Se invece è una rilavorazione, per esempio ripeschi dei file per rifare i calcoli o allenare un modello, il dato vecchio torna attuale e si porta dietro i dati vicini, che da lì in poi vengono riletti come se fossero nuovi. Ogni lettura ne tira dietro un'altra con probabilità p, e la catena vale in media 1 + p + p² + … = 1 / (1 − p) letture. Con p alto è di gran lunga la voce più grossa.

S = W · t + R · t / (1 − p)   rifai tutto il lavoro

S = W · t + R · t           accesso puntuale

La latenza su miss è quella del secondo livello più il tempo per copiare in cache un blocco intero. I dischi necessari sono la cache divisa per la capacità di un disco, arrotondata per eccesso, senza contare la ridondanza. Le scritture per disco al giorno (DWPD) contano tutto quello che entra in cache: a regime, con la rimozione a tempo, l'intera cache si rinnova ogni t giorni.

Qualche consiglio

  • Usa il tempo in cache come timeout di rimozione. Se la cache butta via i dati prima, lo hit ratio scende e con lui la velocità media.
  • Non puntare alla velocità piena del primo livello. Guarda il grafico: gli ultimi MB/s costano più di tutti gli altri insieme.
  • Ai dischi calcolati aggiungi quelli per la ridondanza (RAID, repliche) e tieni un margine di spazio libero: molti SSD rallentano quando sono quasi pieni.
  • Qui 1 GB = 1000 MB e 1 TB = 1000 GB, come nelle capacità dichiarate dai produttori di dischi.