Hacker News new | past | comments | ask | show | jobs | submit login

Intel iMac I bought in november 2020 (~3 months of use) with 128GB of RAM, so it never swaps:

  SMART/Health Information (NVMe Log 0x02)
  Critical Warning:                   0x00
  Temperature:                        42 Celsius
  Available Spare:                    100%
  Available Spare Threshold:          99%
  Percentage Used:                    0%
  Data Units Read:                    95,824,868 [49.0 TB]
  Data Units Written:                 89,046,642 [45.5 TB]
  Host Read Commands:                 1,365,215,816
  Host Write Commands:                837,815,676
  Controller Busy Time:               0
  Power Cycles:                       145
  Power On Hours:                     604
Looking at iosnoop I see dropbox, google drive, backbalze, arq and other programs heavily abusing my SSD with tons of small (4kb) writes.

With age of 105 days, that's 433 GB/day.

My SSD's block size is 45.5TB/89046642 which is ~512kb.

433 GB/day divided by blocksize is 9.8 hertz, meaning I've had apps write ~10 times per second on average.

This corresponds with what I'm seeing at iosnoop. Tons of third party apps open files with O_DIRECT flag or call fsync() right after each write. SQLite databases are most common culprit, since by default it flushes to disk every small insert/replace. And every sqlite database I've seen by third party app just uses defaults (none of them are using WAL, for example).

OS has to flush that to disk if O_DIRECT or fsync() is used, therefore leading to write amplification.

https://www.sqlite.org/atomiccommit.html -- Each insert gets into journal first, that's 4kb there, then index gets updated, that's another 4kb, and then it gets committed to main database, that's another 4kb. There might be more, but in what I'm observing in iosnoop it's coming as multiple of 3.

And since I'm on 512kb SSD blocks, that's 1.5MB per single insert/update.

I forced every sqlite database on my disk to be WAL and changed synchronous to NORMAL from default (FULL), and it reduced I/O activity greatly without any ill side effects in months, most likely developers of these apps aren't even aware of these tunables:

https://www.sqlite.org/pragma.html#pragma_journal_mode https://www.sqlite.org/pragma.html#pragma_synchronous




4k (Page size) writes with fsync is the standard way to commit database pages reliably. My understanding is that modern SSDs also have the 4K page as the minimum unit of input. Can you refer me to the documentation or article that shows a page write causes a whole block to be written?


How did you change every sqlite db running on your system?


  #!/usr/bin/env bash
  
  WANTMODE=wal
  
  for file in "$@"; do
      MODE=`sqlite3 -init <(echo .timeout 10000) -batch "$file" 'PRAGMA journal_mode;'`
      if [[ $MODE == $WANTMODE ]]; then continue; fi
      OLDSIZE=`du -kc "$file" "$file-wal" "$file-shm" 2>/dev/null | tail -n1 | cut -f1`
      echo -n "$file: "
      echo "PRAGMA journal_mode=$WANTMODE;" | sqlite3 -init <(echo .timeout 10000) -batch "$file"
      if [[ $? != 0 ]]; then continue; fi
      NEWSIZE=`du -kc "$file" "$file-wal" "$file-shm" 2>/dev/null | tail -n1 | cut -f1`
      echo "${OLDSIZE}kb -> ${NEWSIZE}kb"
  done




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: