[PATCH 1 of 2 V2] log: flush stdout/err for the first log entries
Pierre-Yves David
pierre-yves.david at ens-lyon.org
Sat Sep 26 17:45:45 CDT 2015
On 09/26/2015 01:03 AM, Yuya Nishihara wrote:
> On Fri, 25 Sep 2015 13:08:09 -0500, Matt Mackall wrote:
>> On Thu, 2015-09-24 at 16:11 -0700, Durham Goode wrote:
>>> On 9/24/15 3:51 PM, Matt Mackall wrote:
>>>> On Thu, 2015-09-24 at 13:02 -0700, Durham Goode wrote:
>>>>> On 9/24/15 12:49 PM, Matt Mackall wrote:
>>>>>> On Thu, 2015-09-24 at 12:20 -0700, Durham Goode wrote:
>>>>>>> # HG changeset patch
>>>>>>> # User Durham Goode <durham at fb.com>
>>>>>>> # Date 1443118388 25200
>>>>>>> # Thu Sep 24 11:13:08 2015 -0700
>>>>>>> # Node ID 7a9aaaadaed9887a956cb6a1e79be527e6f4a20f
>>>>>>> # Parent a0eff7ebc2aebb32cf4c8da276104102ff37d786
>>>>>>> log: flush stdout/err for the first log entries
>>>>>>>
>>>>>>> There have been problems with the pager where we get no results until the python
>>>>>>> buffer has been filled. Let's fix that by manually flushing the buffer for the
>>>>>>> first 50 commits from log. 50 was chosen because it will likely fill the users
>>>>>>> screen and doesn't introduce a significant overhead.
>>>>>>>
>>>>>>> The overhead of this is negiligble. I see no perf difference when running log on
>>>>>>> 100,000 commits.
>>>>>> Still confused as to why this isn't in the ui code.
>>>>> This is in addition to the ui code. I have a patch that adjusts the ui
>>>>> code to flush every N seconds, but it causes some tests to fail (since
>>>>> they didn't on the timing of the progress bar output) so I sent these
>>>>> patches first.
>>>>>
>>>>> We still need these 2 patches though. Imagine a scenario where you run
>>>>> hg log on a directory that has only had one commit total (and it was
>>>>> recent). Immediately one commit is printed into the buffer (before the
>>>>> flush time limit is hit). Then half an hour goes buy while we scan the
>>>>> rest of the repository for another commit in that directory. We end up
>>>>> not showing the user that commit until the command is completely
>>>>> finished. Printing the first N units prevents this experience.
>>>> Right. You can't make the timer thing really work without a thread or
>>>> something. So given that's known to be somewhat broken and that this
>>>> flushing problem isn't in any way log-specific, why don't we just put a
>>>> counter and a flush in ui.write()?
>>>>
>>>> I just did this, saw a pretty repeatable 7.2->7.3s change for hg log on
>>>> the hg repo:
>>>>
>>>> diff -r b80b2ee71a08 mercurial/ui.py
>>>> --- a/mercurial/ui.py Thu Sep 24 00:34:15 2015 -0700
>>>> +++ b/mercurial/ui.py Thu Sep 24 17:45:42 2015 -0500
>>>> @@ -104,6 +104,7 @@
>>>> self._ucfg = config.config() # untrusted
>>>> self._trustusers = set()
>>>> self._trustgroups = set()
>>>> + self._outcount = 0
>>>> self.callhooks = True
>>>>
>>>> if src:
>>>> @@ -617,6 +618,9 @@
>>>> else:
>>>> for a in args:
>>>> self.fout.write(str(a))
>>>> + if self._outcount < 50:
>>>> + self.fout.flush()
>>>> + self._outcount += 1
>>>>
>>>> def write_err(self, *args, **opts):
>>>> self._progclear()
>>>>
>>>> ("hg log -k sullivan -T." is a pretty good behavior test here.)
>
> So we want line-buffering for first 50 lines?
>
> I've timed it with line-buffered stdout. It's slightly slower than fully-
> buffered io, but perhaps we don't care it if we use the pager.
Look slike you got your hand on the way to control the buffer setting. \o/
We should definitely goes for line (or probably even none) buffering for
the pager pipe (the same as what we do for no-pager).
--
Pierre-Yves David
More information about the Mercurial-devel
mailing list