On Fri, Jan 13, 2017 at 11:36:41AM -0600, Joel Cunningham wrote:
> 
> > On Jan 12, 2017, at 10:59 AM, Joel Cunningham <joel.cunning...@me.com> 
> > wrote:
> > 
> > Nicolas,
> > 
> > I’ve found existing “read-ahead logic” in avio_seek to do what I’ve 
> > implemented in http_stream_forward().  This is controlled by 
> > SHORT_SEEK_THRESHOLD, currently set to 4KB.  I proto-typed increasing this 
> > to the 256KB (matches the initial TCP window in my test setup) and saw the 
> > same number of reduction in HTTP GETs and the number of seeks!  Thanks for 
> > the heads up, this should reduce my patch size!
> > 
> > I could plumb this setting (s->short_seek_threshold) to a URL function that 
> > would get the desired value from HTTP/TCP.  Looking at how 
> > ffio_init_context() is implemented, it doesn’t appear to have access to the 
> > URLContext pointer.  Any guidance on how I can plumb the protocol layer 
> > with aviobuf without a public API change?
> > 
> > Thanks,
> > 
> > Joel
> 
> 
> I managed to figure the plumbing out in a way that doesn’t modify any public 
> APIs.  I added a new callback to struct AVIOContext that gets a short seek 
> threshold value from URLContext if available (otherwise fallback to 
> s->short_seek_threshold).  This allows using the read-ahead/discard logic in 
> avio_seek and eliminates my forwarding logic in the HTTP layer (thanks to 
> Nicolas for pointing me in this direction).  See new patch below
> 
> I also updated my commit message to include assumptions/considerations about 
> congestion control on the sender (thanks to Andy for calling out the 
> discussion on it).  Lastly, I have upload new captures/log in dropbox for 
> those that want to take a look at my testing output (see 
> ffplay_short_seek_output.log and mac-ffplay-short-seek-patch.pcapng)
> 
> https://www.dropbox.com/sh/4q4ru8isdv22joj/AABU3XyXmgLMiEFqucf1LdZ3a?dl=0
> 
> Thanks for the feedback so far,
> 
> Joel
> 
> From 9bb2f184591c2d6e6a91d3760e63b013ca4c95e5 Mon Sep 17 00:00:00 2001
> From: Joel Cunningham <joel.cunning...@me.com>
> Date: Fri, 13 Jan 2017 10:52:25 -0600
> Subject: [PATCH] HTTP: improve performance by reducing forward seeks
> 
> This commit optimizes HTTP performance by reducing forward seeks, instead
> favoring a read-ahead and discard on the current connection (referred to
> as a short seek) for seeks that are within a TCP window's worth of data.
> This improves performance because with TCP flow control, a window's worth
> of data will be in the local socket buffer already or in-flight from the
> sender once congestion control on the sender is fully utilizing the window.
> 
> Note: this approach doesn't attempt to differentiate from a newly opened
> connection which may not be fully utilizing the window due to congestion
> control vs one that is. The receiver can't get at this information, so we
> assume worst case; that full window is in use (we did advertise it after all)
> and that data could be in-flight
> 
> The previous behavior of closing the connection, then opening a new
> with a new HTTP range value results in a massive amounts of discarded
> and re-sent data when large TCP windows are used.  This has been observed
> on MacOS/iOS which starts with an inital window of 256KB and grows up to
> 1MB depending on the bandwidth-product delay.
> 
> When seeking within a window's worth of data and we close the connection,
> then open a new one within the same window's worth of data, we discard
> from the current offset till the end of the window.  Then on the new
> connection the server ends up re-sending the previous data from new
> offset till the end of old window.
> 
> Example (assumes full window utilization):
> 
> TCP window size: 64KB
> Position: 32KB
> Forward seek position: 40KB
> 
>       *                      (Next window)
> 32KB |--------------| 96KB |---------------| 160KB
>         *
>   40KB |---------------| 104KB
> 
> Re-sent amount: 96KB - 40KB = 56KB
> 
> For a real world test example, I have MP4 file of ~25MB, which ffplay
> only reads ~16MB and performs 177 seeks. With current ffmpeg, this results
> in 177 HTTP GETs and ~73MB worth of TCP data communication.  With this
> patch, ffmpeg issues 4 HTTP GETs and 3 seeks for a total of ~22MB of TCP data
> communication.
> 
> To support this feature, the short seek logic in avio_seek() has been
> extended to call a function to get the short seek threshold value.  This
> callback has been plumbed to the URLProtocol structure, which now has
> infrastructure in HTTP and TCP to get the underlying receiver window size
> via SO_RCVBUF.  If the underlying URL and protocol don't support returning
> a short seek threshold, the default s->short_seek_threshold is used
> 
> This feature has been tested on Windows 7 and MacOS/iOS.  Windows support
> is slightly complicated by the fact that when TCP window auto-tuning is
> enabled, SO_RCVBUF doesn't report the real window size, but it does if
> SO_RCVBUF was manually set (disabling auto-tuning). So we can only use
> this optimization on Windows in the later case
> ---
>  libavformat/avio.c    |  7 +++++++
>  libavformat/avio.h    |  6 ++++++
>  libavformat/aviobuf.c | 18 +++++++++++++++++-
>  libavformat/http.c    |  8 ++++++++
>  libavformat/tcp.c     | 21 +++++++++++++++++++++
>  libavformat/url.h     |  8 ++++++++
>  6 files changed, 67 insertions(+), 1 deletion(-)

this segfaults with many fuzzed files
backtrace looks like this:

#0  0x00007fffffffb368 in ?? ()
#1  0x00000000005f9280 in avio_seek (s=0x7fffffffb278, offset=31, whence=0) at 
libavformat/aviobuf.c:259

> 
> diff --git a/libavformat/avio.c b/libavformat/avio.c
> index 3606eb0..ecf6801 100644
> --- a/libavformat/avio.c
> +++ b/libavformat/avio.c
> @@ -645,6 +645,13 @@ int ffurl_get_multi_file_handle(URLContext *h, int 
> **handles, int *numhandles)
>      return h->prot->url_get_multi_file_handle(h, handles, numhandles);
>  }
>  
> +int ffurl_get_short_seek(URLContext *h)
> +{
> +    if (!h->prot->url_get_short_seek)

> +        return -1;

should be some AVERROR code


> +    return h->prot->url_get_short_seek(h);
> +}
> +
>  int ffurl_shutdown(URLContext *h, int flags)
>  {
>      if (!h->prot->url_shutdown)
> diff --git a/libavformat/avio.h b/libavformat/avio.h
> index b1ce1d1..0480981 100644
> --- a/libavformat/avio.h
> +++ b/libavformat/avio.h
> @@ -287,6 +287,12 @@ typedef struct AVIOContext {
>      int short_seek_threshold;
>  
>      /**
> +     * A callback that is used instead of short_seek_threshold.
> +     * This is current internal only, do not use from outside.
> +     */
> +    int (*short_seek_get)(void *opaque);
> +
> +    /**
>       * ',' separated list of allowed protocols.
>       */
>      const char *protocol_whitelist;

thats not ok to add this way, the docs say this:
/**
 * Bytestream IO Context.
 * New fields can be added to the end with minor version bumps.
 * Removal, reordering and changes to existing fields require a major
 * version bump.
 * sizeof(AVIOContext) must not be used outside libav*.
 *
 * @note None of the function pointers in AVIOContext should be called
 *       directly, they should only be set by the client application
 *       when implementing custom I/O. Normally these are set to the
 *       function pointers specified in avio_alloc_context()
 */

[...]
> --- a/libavformat/tcp.c
> +++ b/libavformat/tcp.c
> @@ -265,6 +265,26 @@ static int tcp_get_file_handle(URLContext *h)
>      return s->fd;
>  }
>  
> +static int tcp_get_window_size(URLContext *h)
> +{
> +    TCPContext *s = h->priv_data;
> +    int avail;
> +    int avail_len = sizeof(avail);
> +

> +    #if HAVE_WINSOCK2_H

this formating is IIRC not allowed in C the # must be in the first
column


> +    /* SO_RCVBUF with winsock only reports the actual TCP window size when
> +    auto-tuning has been disabled via setting SO_RCVBUF */
> +    if (s->recv_buffer_size < 0) {
> +        return AVERROR(ENOSYS);
> +    }
> +    #endif
> +
> +    if (getsockopt(s->fd, SOL_SOCKET, SO_RCVBUF, &avail, &avail_len)) {
> +           return ff_neterrno();
> +    }

the indention is inconsisntent

[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

It is what and why we do it that matters, not just one of them.

Attachment: signature.asc
Description: Digital signature

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

Reply via email to