Os SSDs podem ser incrivelmente rápidos face aos discos rígidos tradicionais, mas ainda assim continuam a ser lentos em termos das velocidades de transferência que os computadores são capazes. Por isso, continuam a ser utilizadas caches, que guardam os dados em memória até que sejam verdadeiramente gravados (mais lentamente) nos SSDs - e é aqui que a Apple fez uma batota no macOS.
Uma vez que quando um programa pede para gravar dados não tem a garantia que os dados tenham sido efectivamente gravados, existe um comando - fsync() - que pede ao sistema que garanta que efectivamente todos os dados em cache sejam escritos (para o SSD, disco rígido, pen USB, ou qualquer outro dispositivo). Só que no macOS a Apple alterou o comando, ignorando a parte de gravar a cache de escrita para o SSD. Em resultado disso, quando um programa pede para que os dados sejam mesmo gravados, o macOS diz que sim, que está tudo feito, sem o fazer.
Well, this is unfortunate. It turns out Apple's custom NVMe drives are amazingly fast - if you don't care about data integrity.
— Hector Martin (@marcan42) February 17, 2022
If you do, they drop down to HDD performance. Thread.
So effectively macOS cheats on benchmarks; fio on macOS does not give numbers comparable to Linux, and databases and other applications requiring data integrity on macOS need to special case it and use F_FULLSYNC.
— Hector Martin (@marcan42) February 17, 2022
How bad is it if you use F_FULLSYNC? It's bad.
E rapidamente se perceber porquê. Quando se forçam os dados a ficar gravados, tal como seria esperado, os resultados dos SSDs utilizados pela Apple reduzem-se drasticamente, para níveis inferiores ao de SSDs SATA.Single threaded, simple Python file rewrite test:
— Hector Martin (@marcan42) February 17, 2022
Macbook Air M1 (macOS):
- flushing: 46 IOPS
- not: 40000 IOPS
x86 iMac + WD SN550 1TB NVMe (Linux):
- flushing: 2000 IOPS
- not: 20000 IOPS
x86 laptop + Samsung SSD 860 EVO 500GB SATA:
- flushing: 143 IOPS
- not: 5000 IOPS
Mas se por um lado se poderia ver como uma optimização bem vinda, o reverso da medalha é que pode levar à perda de dados quando existe um crash do sistema, um reset, ou perda de energia. Num teste, foi pedido ao sistema que gravasse algo no SSD (com o comando que supostamente deveria garantir isso), esperou-se 5 segundos, e fez-se um hard reboot: e verificou-se que os dados não tinham sido gravados.macOS doesn't even seem to try to proactively issue syncs; you can write a file on macOS, fsync() it, wait 5 seconds, issue a hard reboot (e.g. via USB-PD command), and the data is gone. That's pretty bad.
— Hector Martin (@marcan42) February 17, 2022
É uma aposta da Apple de que o seu macOS não vai crashar ou ficar sem energia e causar esta perda ou corrupção de dados; mas é uma aposta arriscada, que apesar de beneficiar os utilizadores em termos de desempenho no dia a dia, pode resultar bastante mal para os utilizadores se / quando perderem dados críticos por causa disso.
Vai para aqui uma grande confusão. O comportamento do fsync() em MacOS é assim, atrevo-me a dizer, desde sempre! isto já era assim no tempo dos HDDs. Não tem nada a ver com os novos Macs.
ResponderEliminarBasta ver o que está na respectiva Man Page há muitos anos:
"Specifically, if the drive loses power or the OS crashes, the application
may find that only some or none of their data was written. The disk
drive may also re-order the data so that later writes may be present,
while earlier writes are not.
This is not a theoretical edge case. This scenario is easily reproduced
with real world workloads and drive power failures.
For applications that require tighter guarantees about the integrity of
their data, Mac OS X provides the F_FULLFSYNC fcntl. The F_FULLFSYNC
fcntl asks the drive to flush all buffered data to permanent storage.
Applications, such as databases, that require a strict ordering of writes
should use F_FULLFSYNC to ensure that their data is written in the order
they expect. Please see fcntl(2) for more detail."
Em Linux há só um comando: fsync()
ResponderEliminarEm Mac OS X há dois: fsync() e F_FULLFSYNC fcntl [este igual ao f sync() do Linux]
Está documentado e os programadores podem optar por um ou por outro.
E a batota é? Haver dois comandos em vez de um?
Pelo vejo na página do manual, esse comportamento é assim desde pelo menos 1993. Portanto a única coisa que vejo é alguém que tentou fazer algo sem ler a documentação, assumindo que seria o mesmo que em Linux, e apercebeu-se disso.
ResponderEliminarSe a Apple poderia (e deveria) ter feito ao contrário, e garantir primeiro a persistência de dados e usar outro método para escrita mais rápida, provavelmente sim. Daí a ser batota, bem, vai um salto bem grande.