I've tried various buffer sizes, from 4k to 128k. Buffer size doesn't
change the behaviour, at least in that range. 

The song in question is a .flac file. If you want to look at it it's at
http://ikrast.herbison.com:82/Johannes as Benedictus.flac. The other
.flac file, Carol of the bells, doesn't exhibit much if any stutter.
Please delete any copy you take when done.

The timing data I collected from the server is in the directory as
why.csv. The columns are:

. time since start of server in ms (I started the song about 83 seconds
in)

. nanoseconds spent reading the next chunk of the file. Negligible in
all cases (internal SSD).

. Number of bytes the read returned from the file. 16K every time.

. nanoseconds spent in the socket send() call. Initially small, but at
millisecond 84393 it goes up sharply and ends up taking a significant
fraction of a second each time.

. The number of bytes send() claims to have transferred, 16k each time

. the amount queued/unacknowledged in the system TCP buffer, reported by
ioctl and ...OUTQ. Doesn't seem remarkable.

. The squeezebox's buffer fullness. These are requested periodically and
the last value fetched is written to each row. This immediately
approaches 1 and stays there, but starts to nosedive around ms 187826.
Note that the size and rate of the TCP sends() doesn't change
significantly; the same general rate of sending that kept the player
topped off before suddenly isn't feeding the buffer much of any. Note
that Nagle is off, not that it matters much in this case, and turning it
back on didn't change anything.

It's worth noting again that the loop that reads from the disk and
writes to the socket, is running with Linux's real time priority of 97,
and nothing else in the system runs that high. I don't believe there are
pauses being injected by scheduling - the time to send() each buffer
dominates the loop and it's presumably that slow because the squeezebox
has quenched the stream. 

The code is at s.cpp. The loop at line 19 is there to make sure the
while buffer gets sent in case send() writes only part of the buffer,
but it's always taken exactly once because res == howMany is always
true. The logger (ts) is lightweight and writing to an SSD and isn't
injecting timing issues.

The big mystery here is why are the send()s as slow as they are when the
squeezebox is clearly draining the play buffer. When the play buffer is
99.9% full it makes sense that it would pause the TCP stream - and
clearly those pauses don't prevent the play buffer from staying 98+%
full for most of the play. The question isn't "why isn't the server
sending fast enough." I think it's sending whenever it's allowed to.

I haven't figured out wireshark yet, but when I do I'll try to capture
just the music stream. Pointers welcome; it's a complicated unfamiliar
interface.


------------------------------------------------------------------------
ScottAM's Profile: http://forums.slimdevices.com/member.php?userid=69412
View this thread: http://forums.slimdevices.com/showthread.php?t=110986

_______________________________________________
unix mailing list
unix@lists.slimdevices.com
http://lists.slimdevices.com/mailman/listinfo/unix

Reply via email to