Package: apt-cacher-ng
Version: 0.8.6-1
Severity: normal
Tags: patch

Dear Maintainer,

after a lot of testing I have reason to believe the implementation of
MaxDlSpeed is broken: The actual download speed is often slower then
configured, down to the half.

This becomes pretty obvious at a configured limit of 500 when
downloading a bigger file like Packages.* using wget, after removing
the corresponding file from /var/cache/apt-cacher-ng/ to enforce
fetching: The visible download speed is somewhat 277 kbyte/sec (259
Kibyte/sec).

Analysis led to dlcon.cc (a bit in detail here since it took a while to
figure out how it works): Initially, a request block size
(m_nSpeedLimitMaxPerTake) is computed and an according interval
(nIntervalUS) to yield the desired rate; the latter then is rounded up
to a power of two minus one (m_nSpeedLimiterRoundUp) to simplify sleep
time computation. Quite nifty by the way :)

However: m_nSpeedLimitMaxPerTake is not increased by the same factor.
As a result, the effective download rate matches the configured rate
only a a few values only (e.g. 256, 512, 992, 1984) but is much
slower if the configuration value is a bit below that one.

The patch attached fixes the problem for me. It's minimal by intention,
it might be worth an idea to re-write the computation of the
parameters, I have the feeling this could look nicer.

Regards,
    Christoph

-- System Information:
Debian Release: stretch/sid
  APT prefers testing
  APT policy: (500, 'testing')
Architecture: amd64 (x86_64)

Kernel: Linux 4.1.10 (SMP w/4 CPU cores)
Locale: LANG=C, LC_CTYPE=C (charmap=ANSI_X3.4-1968)
Shell: /bin/sh linked to /bin/dash
Init: unable to detect

Subject: Fix computation of download limit
Author: Christoph Biedl <debian.a...@manchmal.in-ulm.de>
Date: Sun Oct 11 16:42:45 2015 +0200

--- a/source/dlcon.cc
+++ b/source/dlcon.cc
@@ -901,10 +901,11 @@
                 nTakesPerSec=1;
              m_nSpeedLimitMaxPerTake = nSpeedNowKib*1024/nTakesPerSec;
              auto nIntervalUS=1000000 / nTakesPerSec;
+             auto nIntervalUS_copy = nIntervalUS;
              // creating a bitmask
              for(m_nSpeedLimiterRoundUp=1,nIntervalUS/=2;nIntervalUS;nIntervalUS>>=1)
                 m_nSpeedLimiterRoundUp = (m_nSpeedLimiterRoundUp<<1)|1;
-
+             m_nSpeedLimitMaxPerTake = uint(double(m_nSpeedLimitMaxPerTake) * double(m_nSpeedLimiterRoundUp) / double(nIntervalUS_copy));
           }
           // waiting for the next time slice to get data from buffer
           timeval tv;

Attachment: signature.asc
Description: Digital signature

Reply via email to