Opened 14 years ago

Closed 10 years ago

Last modified 16 months ago

#502 closed enhancement (wontfix)

Use custom locking helper executable

Reported by: Olly Betts Owned by: Olly Betts
Priority: normal Milestone:
Component: Backend-Chert Version: 1.2.2
Severity: normal Keywords:
Cc: Blocked By:
Blocking: Operating System: All

Description (last modified by Olly Betts)

Here I noted that exec-ing our own custom statically linked helper executable instead of /bin/cat was quite a bit faster:

http://article.gmane.org/gmane.comp.search.xapian.devel/519

However we never got around to doing that.

It's just occurred to me that there's an additional little win to be had in this case, at least on some platforms - if we have our own helper, we can move work like the closing of file descriptors to after the exec() and use vfork() instead of fork(). There's not a huge saving to be had from vfork() on a modern OS, but it can still be more efficient - for example:

http://www.netbsd.org/docs/kernel/vfork.html

On some platforms, vfork() may just be an alias for fork(), but there's no penalty to doing the work in the child that I can see, and it may still be a small win to minimise modifications to pages shared with the parent. It also means close-on-exec file descriptors get closed for us, which may be more efficient.

Marking as 1.2.x as this is ABI and API compatible.

Change History (8)

comment:1 by Olly Betts, 13 years ago

Description: modified (diff)

Remove bogus "not" from description.

comment:2 by Olly Betts, 13 years ago

Milestone: 1.2.x1.3.0

Let's do this in 1.3.0 - while it's ABI and API compatible, it'll require packaging changes, and we don't currently install binaries which the library needs to run.

comment:3 by Olly Betts, 13 years ago

Milestone: 1.3.01.3.x

comment:4 by Olly Betts, 13 years ago

Milestone: 1.3.x1.3.1

comment:5 by Olly Betts, 12 years ago

Milestone: 1.3.11.3.2

It's time we got 1.3.1 out.

comment:6 by Olly Betts, 11 years ago

Milestone: 1.3.21.3.3

comment:7 by Olly Betts, 10 years ago

Status: newassigned

On Linux we no longer need to fork() a child process, thanks to the "OFD" locks. These have been submitted to POSIX, and they clearly fix a mistake in the specification of fcntl() locking, so I'm hopefully they'll get implemented promptly.

There are a few obstacles to using vfork() - we call dup2() currently to connect stdin and stdout of the child process to the pipe created by socketpair() but we could instead pass the number of the fd on the command line of the helper, and just use that number. We would have to postpone getting the lock until after we have done the exec though, since we have to close any other open fds before we try to get the lock (or else closing them might smash the lock).

comment:8 by Olly Betts, 10 years ago

Milestone: 1.3.3
Resolution: wontfix
Status: assignedclosed

I did some timings on my current dev box, running Debian unstable which is reasonably close to what jessie will be, and testing on a spinning disk (though SSD didn't seem to make much difference when I compared). For these I just ran simpleindex around 10 times, with instrumentation added to flintlock.cc (plus patches to implement each approach):

  • 11-40 us fcntl alone
  • 12-40 us OFD
  • 13-66 us flock
  • 170-488 us fork/exec static cat helper
  • 185-335 us fork/exec dynamic cat helper
  • 190-380 us fork/fcntl/exec cat
  • 224-477 us fork/fcntl and loop on read rather than exec-ing /bin/cat:
  • 269-570 us vfork/exec static fat helper
  • 385-701 us vfork/exec dynamic fat helper
  • 383-858 us fork/exec static fat helper
  • 454-1006 us fork/exec dynamic fat helper

The cat helper is a simple program which just reads and swallows stdin (so it behaves like cat > /dev/null)

The fat helper does all the things which we currently do in the child process between fork() and exec() (and the library then exec-s this helper right after fork()).

The statically linked cat helper is surprisingly large - perhaps a cunningly written helper could avoid pulling in as much of libc, though I only call read() explicitly.

I conclude from this that (at least on my hardware running a recent Linux kernel) there is no benefit at all from trying to be clever about the helper, and the benefits of using any custom helper are minimal, and not worth the extra complication involved. Perhaps other platforms would benefit more, but OFD locking is clearly where we actually want to be.

So I'm going to close this as "wontfix".

Last edited 16 months ago by Olly Betts (previous) (diff)
Note: See TracTickets for help on using tickets.