Subject: Re: bug#18808: implement 'tail -r' as synonym for 'tac'

From: Pádraig Brady <[email-masked]>
Date: Thu, 23 Oct 2014 22:59:11 +0100

On 10/23/2014 08:03 PM, Eric Blake wrote:
> On 10/23/2014 12:35 PM, Pádraig Brady wrote:
>>
>> Now the only reason I see would be for compat with solaris and BSD.
>>
>> I don't think they should have included that functionality though
>> as there isn't much complementary with the other tail functions
>> (being incompat with -f for example) and so is better split out as a separate util.
> 
> Yeah, today's Austin Group call included a debate about whether
> standardizing 'tac' would be smarter than 'tail -r', but the consensus
> among those on the call was that since:

I understand these 3 arguments, though don't necessarily agree with any.

> 1. more implementations already have 'tail -r' than 'tac'

More implementations but definitely not more installations.
POSIX should prefer the most popular interface in my biased opinion.

> 2. standardizing new requirements to an existing utility is easier than
> adding a completely new utility (if only slightly, due to less paperwork)

meh, paperwork should not impact on interface

> 3. GNU code tends to be the most adaptable

True, though while pragmatic should also not dictate interface.

Saying that, I'm 50:50 for implementing `tail -r` for compat reasons.

> therefore, 'tail -r' won the vote, and the result of the meeting was an
> action to me to see how adaptable GNU really is, and whether we can
> indeed quickly implement 'tail -r'.
> 
>>
>> The only small advantage of integration is a tiny perf benefit
>> when specifying a number of lines, but really `tail -r -n$num $file`
>> is of minimal improvement over `tac $file | head -n$num`
>> (though would be better than `tail -n$num | tac` as it avoids buffering).
> 
> The fact that we DON'T have 'tac -n' is what intrigues me most; that's
> the one thing that 'tail -r -n' can do in a single process that GNU
> can't.  Of course, it is trivial to implement it by doing what tac has
> always done and then stop output after -n is exceeded, and easy on
> seekable files as well.  But on non-seekable files, it may lend to an
> interesting optimization where knowing that the output will be limited
> to n lines makes it easier to set up a rolling window of the most recent
> n lines seen rather than having to dump out to a temporary file when the
> file proves to be larger than the current hueristics of when tac stays
> in memory.

-n wouldn't really have any impact on that better implementation.
I.E. ideally we should have an adaptive buffer internally
that after 128KiB or so (the current io_blksize()) would
start buffering to file, irrespective of -n.
That would deal with large lines and large -n.
Generally such an adaptive switch is optimal in various utils,
to operate efficiently with small inputs, but scalably with large ones.

>> As a side note I see that solaris doesn't even support non seekable input mode
>> (though BSD does):
>>
>>   $ printf "%s\n" 1 2 3 | tail -r -2
>>   tail: cannot open input
> 
> Careful, which tail are you testing?  From your output, I'm guessing you
> are trying to open the file named './-2' rather than limiting -r to a
> line count.  We made several observations during the Austin Group that
> /usr/bin/tail and /usr/xpg4/bin/tail behave differently.
> 
> $ /usr/bin/tail -rc
> usage: tail [+/-[n][lbc][f]] [file]
>        tail [+/-[n][l][r|f]] [file]
> $ printf "%s\n" 1 2 3 | /usr/bin/tail -2r
> 3
> 2
> $ printf "%s\n" 1 2 3 | /usr/xpg4/bin/tail -r -n2
> 3
> 2
> $ printf "%s\n" 1 2 3 | /usr/xpg4/bin/tail -r -2
> 3
> 2

Ugh right, that's the case here too.
How confusing.

thanks,
Pádraig.