GOPHERSPACE.DE - P H O X Y
gophering on hngopher.com
HN Gopher Feed (2017-10-05) - page 1 of 10
 
___________________________________________________________________
I/O Access Methods for Linux
105 points by thekozmo
http://www.scylladb.com/2017/10/05/io-access-methods-scylla/
ngopher.com
___________________________________________________________________
 
TheAlchemist - 1 hours ago
A bit off topic, but do anybody have some practical experience with
Scylla (using at work) ? What's your feedback on the product ?
 
rdtsc - 4 hours ago
Very nice job, I like the diagrams and the description.Noticed this
bit "block size which is typically 512 or 4096 bytes" and was
wondering how would the application know how to align. Does it
query the file descriptor for block size? Is there an ioctl call
for that?When it comes to IO it's also possible to differentiate
between blocking/non-blocking and synchronous/asynchronous, and
those categories are orthogonal in general.So there is blocking and
synchronous: read, write, readv, writev. The calling thread blocks
until data is ready and while it gets copied to user memory.non-
blocking synchronous: using non-blocking file descriptors with
select/poll/epoll/kqueue. Checking when data is ready is done
asynchronously but then read, write still happens inline and the
thread waits for it to be copied to user space. This works for
socket IO in Linux but not for disk.non-blocking asynchronous:
using AIO on Linux. Here both waiting till data is ready to be
transferred and transferring happens asynchronously. aio_read
returns right way before read finished. Then have to use aio_error
to check for its status. This works for disk but not socket IO on
Linux.blocking asynchronous: nothing here
 
  the8472 - 3 hours ago
  > blocking asynchronous: nothing here(vm)splice maybe?
 
    bonzini - 2 hours ago
    io_getevents lets you submit a bunch of I/O operations via
    io_submit, and then wait synchronously for one (or some) of
    them to complete.
 
  GrayShade - 4 hours ago
  st_blksize in struct stat: http://man7.org/linux/man-
  pages/man2/stat.2.html
 
amelius - 31 minutes ago
They seem to target situation that the storage-to-memory ratio is
very high.But this raises the question: isn't this ratio decreasing
with cheaper and cheaper RAM these days?(I've seen a lot of systems
already moving to completely in-memory databases, taking this to
the extreme; so this is actually a reality)
 
hoytech - 3 hours ago
> The great advantage of letting the kernel control caching is that
great effort has been invested by the kernel developers over many
decades into tuning the algorithms used by the cache.Some other
advantages:The kernel has a global view of what is going on with
all the different applications running on the system, whereas your
application only knows about itself.The cache can be shared amongst
different applications.You can restart applications and the cache
will stay warm.
 
throwaway49392 - 3 minutes ago
There's also a class of functions that act like read/write, but are
done completely in the kernel without returning to userspace
(sendfile/(vm)splice/copy_file_range).
 
the8472 - 3 hours ago
The diagram is a bit misleading. There is no system call (switching
to the kernel) with read or write hits, assuming the memory is
already mapped, has a page table entry and is resident. You only
incur switches when performing the mapping and due to various page
fault modes (lazy mapping, non-resident data, copy-on-write
needed).> This usually happens when the ratio of storage size to
RAM size is significantly higher than 1:1. Every page that is
brought into cache causes another page to be evicted.While true one
can optimize these things by unmapping larger ranges in bulk (to
reduce cache pressure) or prefetching them (to reduce blocking)
with madvise, allowing the kernel doing the loading asynchronously
while you're accessing the previously prefetched ones.If you know
your read and write patterns very well you can effectively use this
for nearly asynchronous IO without the pains of AIO and few to none
extra threads.
 
  seastarer - 2 hours ago
  Right, the mmap read hit is incorrect, I'll fix it up.
 
    seastarer - 1 hours ago
    I see what happened, the read/write diagram got placed under
    mmap.
 
  mtanski - 2 hours ago
  In really new linux there is a preadv2 sysscall that was merged.
  preadv2 supports a flag RWF_NOWAIT to tell the kernel to not
  block if a read requires uncached data.This lets you play around
  with policy for blocking reads in user space. Examples: try to
  make progress on partially read data & queue up the rest on
  another thread; try performing reads from your network thread and
  if unavailable queue up the blocking read onto another disk
  thread & serve a different request.There's no RWF_NOWAIT support
  for write in pwritev2. But it's technically possible to implement
  it and if your write will cause a writeout to disk return
  EWOULDBLOCK.LWN description: https://lwn.net/Articles/612483/LWN
  summary of my talk: https://lwn.net/Articles/636967/Final patch
  set by Christoph: https://lwn.net/Articles/731700/Disclaimer: I'm
  the author of the preadv2/pwritev2 syscalls. And the original
  author of the support for RWF_NOWAIT, which Christoph Hellwig
  took over. So feel free to consider this to be self
  congratulatory.Correction: It looks like there's a patch set
  floating around for adding support for RWF_NOWAIT in pwritev2 as
  well. https://patchwork.kernel.org/patch/9787271/ (comment from
  Christoph)
 
    colanderman - 1 hours ago
    > try performing reads from your network thread and if
    unavailableHow does this differ from recv(..., MSG_DONTWAIT)?
 
      mtanski - 1 hours ago
      This was my original model when I came up with the idea; in
      fact, my v1 hack used recv and MSG_DONTWAIT. For a number of
      a reasons the kernel community did not want to overload that
      interface and that flag.Besides some technical reasons, the
      big reason was an "impedance mismatch" of the recv API which
      was working with stream data. In that context you're
      depending on another party send data. Also, you can wait on
      this to happen using another API (select et. al) so the
      buffer will be filled not by your actions. On the other hand
      preadv2(..., RWF_NOWAIT) is not going to trigger any more
      read in and theres no wait to wait on the data. Although the
      previous statement is not a 100% true... preadv2 may or may
      not trigger readahead (if it's enabled).Here's the whole
      thread about it... if you're interested in the history of how
      this came to be: https://lkml.org/lkml/2014/7/24/787
 
      tmzt - 1 hours ago
      I think he means perform a disk read in response to a network
      request, and choose to respond to a different queued/pooled
      request if the data is not available to complete it.I would
      assume the intent is similar but applied to a different
      type/source of IO.
 
  arielweisberg - 3 hours ago
  I noticed that as well. Maybe it's assuming a CPU cache and TLB
  miss on read which means going to the kernel. Also on write if
  it's a new page you are going to have to fault once for every
  page which depending on write size is like having to go to the
  kernel for every write. It can actually be good for performance
  in some dimensions to pre-touch pages in a loop.I can't speak for
  Avi though.I suspect he is writing from the perspective of a
  database implementor. For a database the page cache is not
  predictable in ways you want it to be.For writes the issue is IO
  scheduling, when flushing occurs, and how much is flushed at a
  time and at what rate.For reads if a page is not in memory you
  have to block a thread to read it. If you are thread per core
  this means you either have a thread pool on the side to do IO or
  you block an event loop preventing other work from making
  progress. Even having the thread pool on the side is problematic
  because checking whether a page is in the cache is not cheap
  either and requires a system call which is kind of self
  defeating.
 
    the8472 - 3 hours ago
    > Maybe it's assuming a CPU cache and TLB miss on read which
    means going to the kernel.My understanding is that those
    normally don't incur faults that would switch to the kernel
    context. They're just slow due to several memory lookups that
    have to be done to satisfy the primary memory access.
 
      richardwhiuk - 2 hours ago
      Correct for x86/x64. TLB misses require the CPU to lookup the
      location in the current active page table which means another
      memory lookup. I'm not sure how the cache hierarchy works for
      page table lookups following a TLB miss, but worst case, it's
      equivalent to an additional L3 cache miss.
 
      arielweisberg - 2 hours ago
      Oh interesting. TIL.
 
        bonzini - 2 hours ago
        Actually it depends on the processor. Nowadays it's rare,
        but in the past there used to be software TLBs where a TLB
        miss did trap into the kernel, and there was no radix tree-
        like page table structure in the definition of the
        architecture.SPARC and MIPS for example worked like this,
        and server POWER chips had a hashed page table that many
        OSes populated lazily, effectively treating it like a (more
        efficient) software TLB.
 
          namibj - 58 minutes ago
          Well, MIPS is still in widespread use in wifi hardware,
          and POWER is being resurrected for a scale-up way to deal
          with a growing database, considering the current
          generation scales higher at about a similar pricepoint
          than a 4-socket Intel machine. So I am not sure what the
          past tense is supposed to mean, if it denotes the
          architectures to no longer compromise a significant part
          of world-wide (say DRYSTONE) MIPS, or their lack of use
          where they are good at (false).
 
  seastarer - 17 minutes ago
  The diagrams are now correct (the read/write diagram was placed
  under the mmap section by mistake).
 
  colanderman - 1 hours ago
  > If you know your read and write patterns very well you can
  effectively use this for nearly asynchronous IO without the pains
  of AIO and few to none extra threads.The same is true of plain
  read/write, barring extra data copies to/from the kernel.The only
  reason to ever use AIO is if you're doing direct I/O, in which
  case mmap doesn't apply.
 
AceJohnny2 - 2 hours ago
The author's name, Avi Kivity sounded familiar. Turns he created
KVM, the Linux kernel
hypervisor.https://il.linkedin.com/in/avikivity
 
  richardwhiuk - 2 hours ago
  Literally written at the bottom of the article...
 
    AceJohnny2 - 1 hours ago
    >_<