From: Linus Torvalds <torvalds@osdl.org>
To: Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
Cc: Marco Costalba <mcostalba@gmail.com>,
Git Mailing List <git@vger.kernel.org>,
Junio C Hamano <junkio@cox.net>, Alex Riesen <raa.lkml@gmail.com>,
Shawn Pearce <spearce@spearce.org>
Subject: Re: [RFC \ WISH] Add -o option to git-rev-list
Date: Mon, 11 Dec 2006 13:14:42 -0800 (PST) [thread overview]
Message-ID: <Pine.LNX.4.64.0612111258050.3515@woody.osdl.org> (raw)
In-Reply-To: <200612112154.56166.Josef.Weidendorfer@gmx.de>
On Mon, 11 Dec 2006, Josef Weidendorfer wrote:
>
> So the implementation in Qt's QProcess is a little bit pessimistic, probably
> to make it work fine with other UNIXs out there.
I suspect it may actually have been performance-optimized for Linux-2.4,
where the pipe buffer size was one page (so if you got a full 4kB on x86,
you'd know that the buffer was fully emptied).
And it actually does end up depending on the load too. For example, the
4kB can also happen to match the default buffer size in stdio (or in the
QT IO buffering equivalent), and in that case you know that any _writer_
that uses stdio buffering will usually use that as the blocksize, so you
have reasons beyond the kernel to think that maybe a certain particular
blocksize is more common than others.
And if that's the case, then if you know that _usually_ the read() would
return -EAGAIN, then it's actually better to return to the main loop and
select(), on the assumption that quite often, the select will be the right
thing (and if it isn't, it will just return immediately anyway, and you
can do the second read).
In other words, it's really a "tuning thing" that depends on the IO
patterns of the apps involved, and the underlying pattern of the OS can
affect it too.
Of course, most of the time it doesn't make _that_ much of a difference,
especially when system calls are reasonably cheap (and they largely are,
under Linux). So you can certainly see the effects of this, but the
effects will vary so much on the load and other issues that it's hard to
say that there is "one correct way" to do things.
For example, very subtle issues can be at play:
- using a larger buffer and having fewer system calls can be
advantageous in many cases. But certainly not always.
HOWEVER. If you have two processes that both do very little with the
data (generating it _or_ using it), and process switching is cheap
thanks to address space identifiers or clever TLB's, then a small
buffer may actually be much better, if it means that the whole working
set fits in the L2 cache.
So a large buffer with fewer system calls may actually be _bad_, if
only because it causes things to go to L3 or memory. In contrast, if
you can re-use a smaller buffer, you'll stay in the L2 cache better.
Same goes for the L1 cache too, but that's really only noticeable for
true micro-benchmarks. Sadly, people often do performance analysis with
microbenches, so they can actually tune their setup for something that
is NOT what people actually see in real life.
In general, if you re-use your buffer, try to keep it small enough that
it stays hot in the L2 can be a good thing. Using 8kB or 16kB buffers
and 64-128 system calls can actually be a lot BETTER than using a 1MB
buffer and a single system call.
Examples of this is stdio. Making your stdio buffers bigger simply
often isn't a good idea. The system call cost of flushing the buffer
simply isn't likely to be the highest cost.
- real-time or fairness issues. Sometimes you are better off doing a
round-robin thing in the main select() loop over 10 smaller buffers
than over ten big buffers (or over a single mainloop call-out that
keeps doing read() until the buffer is entirely empty).
This is not likely to be an issue with qgit-like behaviour (whether you
process a 4kB buffer or 64kB buffer in one go is simply not going to
make a visible difference to a user interface), but it can make a
difference for "server" apps with latency issues. You do not want one
busy client to basically freeze out all the other clients by just
keeping its queue filled all teh time.
So returning to the main loop may actually be the right thing after
each read(), not for performance reasons, but because it gives a nicer
load pattern. It may perform _worse_, but it may well give a smoother
feel to the system!
- simplicity. The main select() loop does the looping anyway, so avoiding
looping in the callouts simplifies the system. And since it's not
necessarily the right thing to do to loop in the individual routines
_anyway_ (see above), why not?
So I don't think there is a right answer here. I suspect QProcess does ok.
next prev parent reply other threads:[~2006-12-11 21:15 UTC|newest]
Thread overview: 39+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-12-10 11:38 [RFC \ WISH] Add -o option to git-rev-list Marco Costalba
2006-12-10 14:54 ` Alex Riesen
2006-12-10 18:16 ` Linus Torvalds
2006-12-10 19:51 ` Marco Costalba
2006-12-10 20:00 ` globs in partial checkout? Michael S. Tsirkin
2006-12-10 20:13 ` Linus Torvalds
2006-12-10 21:07 ` Michael S. Tsirkin
2006-12-10 20:08 ` [RFC \ WISH] Add -o option to git-rev-list Linus Torvalds
2006-12-10 20:19 ` Linus Torvalds
2006-12-10 22:05 ` Marco Costalba
2006-12-10 22:09 ` Marco Costalba
2006-12-10 22:16 ` Linus Torvalds
2006-12-10 22:35 ` Marco Costalba
2006-12-10 22:53 ` Linus Torvalds
2006-12-11 0:15 ` Marco Costalba
2006-12-11 0:51 ` Linus Torvalds
2006-12-11 7:17 ` Marco Costalba
2006-12-11 10:00 ` Alex Riesen
2006-12-11 16:59 ` Linus Torvalds
2006-12-11 17:07 ` Linus Torvalds
2006-12-11 17:39 ` Marco Costalba
2006-12-11 18:15 ` Linus Torvalds
2006-12-11 18:59 ` Marco Costalba
2006-12-11 19:25 ` Linus Torvalds
2006-12-11 20:28 ` Josef Weidendorfer
2006-12-11 20:40 ` Linus Torvalds
2006-12-11 20:54 ` Josef Weidendorfer
2006-12-11 21:14 ` Linus Torvalds [this message]
2006-12-15 18:45 ` Marco Costalba
2006-12-15 19:20 ` Linus Torvalds
2006-12-15 20:41 ` Marco Costalba
2006-12-15 21:04 ` Marco Costalba
2006-12-11 9:26 ` Josef Weidendorfer
2006-12-11 12:52 ` Marco Costalba
2006-12-11 13:28 ` Josef Weidendorfer
2006-12-11 17:28 ` Marco Costalba
2006-12-11 11:39 ` Andreas Ericsson
2006-12-11 12:59 ` Marco Costalba
2006-12-11 13:40 ` Andreas Ericsson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Pine.LNX.4.64.0612111258050.3515@woody.osdl.org \
--to=torvalds@osdl.org \
--cc=Josef.Weidendorfer@gmx.de \
--cc=git@vger.kernel.org \
--cc=junkio@cox.net \
--cc=mcostalba@gmail.com \
--cc=raa.lkml@gmail.com \
--cc=spearce@spearce.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).