• Joel Cunningham's avatar
    HTTP: improve performance by reducing forward seeks · 8c8e5d52
    Joel Cunningham authored
    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 initial 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
    Signed-off-by: 's avatarJoel Cunningham <joel.cunningham@me.com>
    Signed-off-by: 's avatarMichael Niedermayer <michael@niedermayer.cc>
    8c8e5d52
avio.c 19.5 KB