[pacman-dev] [PATCH] Allow UseDelta option to specify a delta ratio
Rework the frontend and backend to allow passing a ratio value in for UseDelta rather than having a hardcoded #define-d 0.7 value always used. This is useful for those with fast connections, who would likely benefit from tuning this ratio to lower values; it is also useful for general testing purposes. The libalpm API changes for this, but we do support the old config file format with a no-value 'UseDelta' option; in this case we simply use the old default of 0.7. We clamp the ratio values to a sane range between 0.0 and 2.0, allowing ratios above 1.0 for testing purposes. Signed-off-by: Dan McGee <dan@archlinux.org> --- doc/pacman.conf.5.txt | 10 +++++++--- etc/pacman.conf.in | 2 +- lib/libalpm/alpm.h | 4 ++-- lib/libalpm/delta.c | 3 ++- lib/libalpm/delta.h | 3 --- lib/libalpm/handle.c | 12 ++++++++---- lib/libalpm/handle.h | 2 +- lib/libalpm/sync.c | 4 ++-- src/pacman/conf.c | 19 ++++++++++++++++--- src/pacman/conf.h | 2 +- 10 files changed, 40 insertions(+), 21 deletions(-) diff --git a/doc/pacman.conf.5.txt b/doc/pacman.conf.5.txt index 2c1a24b..3913292 100644 --- a/doc/pacman.conf.5.txt +++ b/doc/pacman.conf.5.txt @@ -168,9 +168,13 @@ Options Log action messages through syslog(). This will insert log entries into +{localstatedir}/log/messages+ or equivalent. -*UseDelta*:: - Download delta files instead of complete packages if possible. Requires - the xdelta3 program to be installed. +*UseDelta* [= ratio]:: + Download delta files instead of complete packages if possible. Requires + the `xdelta3` program to be installed. If a ratio is specified (e.g., + `0.5`), then it is used as a cutoff for determining whether to use deltas. + Allowed values are between `0.0` and `2.0`; sensible values are between + `0.2` and `0.9`. Using a value above `1.0` is not recommended. The + default is `0.7` if left unspecified. *TotalDownload*:: When downloading, display the amount downloaded, download rate, ETA, diff --git a/etc/pacman.conf.in b/etc/pacman.conf.in index 932140f..7f9db1b 100644 --- a/etc/pacman.conf.in +++ b/etc/pacman.conf.in @@ -20,6 +20,7 @@ SyncFirst = pacman #XferCommand = /usr/bin/curl -C - -f %u > %o #XferCommand = /usr/bin/wget --passive-ftp -c -O %o %u #CleanMethod = KeepInstalled +#UseDelta = 0.7 Architecture = auto # Pacman won't upgrade packages listed in IgnorePkg and members of IgnoreGroup @@ -31,7 +32,6 @@ Architecture = auto # Misc options #UseSyslog -#UseDelta #TotalDownload CheckSpace #VerbosePkgLists diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h index 95c817e..9ffdebc 100644 --- a/lib/libalpm/alpm.h +++ b/lib/libalpm/alpm.h @@ -535,8 +535,8 @@ const char *alpm_option_get_arch(alpm_handle_t *handle); /** Sets the targeted architecture. */ int alpm_option_set_arch(alpm_handle_t *handle, const char *arch); -int alpm_option_get_usedelta(alpm_handle_t *handle); -int alpm_option_set_usedelta(alpm_handle_t *handle, int usedelta); +double alpm_option_get_deltaratio(alpm_handle_t *handle); +int alpm_option_set_deltaratio(alpm_handle_t *handle, double ratio); int alpm_option_get_checkspace(alpm_handle_t *handle); int alpm_option_set_checkspace(alpm_handle_t *handle, int checkspace); diff --git a/lib/libalpm/delta.c b/lib/libalpm/delta.c index 726f03c..e3acc66 100644 --- a/lib/libalpm/delta.c +++ b/lib/libalpm/delta.c @@ -264,7 +264,8 @@ static alpm_list_t *find_unused(alpm_list_t *deltas, const char *to, off_t quota alpm_list_t SYMEXPORT *alpm_pkg_unused_deltas(alpm_pkg_t *pkg) { ASSERT(pkg != NULL, return NULL); - return find_unused(pkg->deltas, pkg->filename, pkg->size * MAX_DELTA_RATIO); + return find_unused(pkg->deltas, pkg->filename, + pkg->size * pkg->handle->deltaratio); } /** @} */ diff --git a/lib/libalpm/delta.h b/lib/libalpm/delta.h index 1173ddf..37f208b 100644 --- a/lib/libalpm/delta.h +++ b/lib/libalpm/delta.h @@ -30,9 +30,6 @@ alpm_delta_t *_alpm_delta_dup(const alpm_delta_t *delta); off_t _alpm_shortest_delta_path(alpm_handle_t *handle, alpm_list_t *deltas, const char *to, alpm_list_t **path); -/* max percent of package size to download deltas */ -#define MAX_DELTA_RATIO 0.7 - #endif /* _ALPM_DELTA_H */ /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/handle.c b/lib/libalpm/handle.c index 8e2e3c7..2187dca 100644 --- a/lib/libalpm/handle.c +++ b/lib/libalpm/handle.c @@ -43,6 +43,7 @@ alpm_handle_t *_alpm_handle_new(void) alpm_handle_t *handle; CALLOC(handle, 1, sizeof(alpm_handle_t), return NULL); + handle->deltaratio = 0.0; return handle; } @@ -252,10 +253,10 @@ const char SYMEXPORT *alpm_option_get_arch(alpm_handle_t *handle) return handle->arch; } -int SYMEXPORT alpm_option_get_usedelta(alpm_handle_t *handle) +double SYMEXPORT alpm_option_get_deltaratio(alpm_handle_t *handle) { CHECK_HANDLE(handle, return -1); - return handle->usedelta; + return handle->deltaratio; } int SYMEXPORT alpm_option_get_checkspace(alpm_handle_t *handle) @@ -597,10 +598,13 @@ int SYMEXPORT alpm_option_set_arch(alpm_handle_t *handle, const char *arch) return 0; } -int SYMEXPORT alpm_option_set_usedelta(alpm_handle_t *handle, int usedelta) +int SYMEXPORT alpm_option_set_deltaratio(alpm_handle_t *handle, double ratio) { CHECK_HANDLE(handle, return -1); - handle->usedelta = usedelta; + if(ratio < 0.0 || ratio > 2.0) { + RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1); + } + handle->deltaratio = ratio; return 0; } diff --git a/lib/libalpm/handle.h b/lib/libalpm/handle.h index a64c5c9..a090ae4 100644 --- a/lib/libalpm/handle.h +++ b/lib/libalpm/handle.h @@ -88,8 +88,8 @@ struct __alpm_handle_t { /* options */ char *arch; /* Architecture of packages we should allow */ + double deltaratio; /* Download deltas if possible; a ratio value */ int usesyslog; /* Use syslog instead of logfile? */ /* TODO move to frontend */ - int usedelta; /* Download deltas if possible */ int checkspace; /* Check disk space before installing */ alpm_siglevel_t siglevel; /* Default signature verification level */ diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c index 49a3f42..6967b49 100644 --- a/lib/libalpm/sync.c +++ b/lib/libalpm/sync.c @@ -318,13 +318,13 @@ static int compute_download_size(alpm_pkg_t *newpkg) /* tell the caller that we have a partial */ ret = 1; - } else if(handle->usedelta) { + } else if(handle->deltaratio > 0.0) { off_t dltsize; dltsize = _alpm_shortest_delta_path(handle, newpkg->deltas, newpkg->filename, &newpkg->delta_path); - if(newpkg->delta_path && (dltsize < newpkg->size * MAX_DELTA_RATIO)) { + if(newpkg->delta_path && (dltsize < newpkg->size * handle->deltaratio)) { _alpm_log(handle, ALPM_LOG_DEBUG, "using delta size\n"); size = dltsize; } else { diff --git a/src/pacman/conf.c b/src/pacman/conf.c index 7ba2791..e1bff18 100644 --- a/src/pacman/conf.c +++ b/src/pacman/conf.c @@ -52,6 +52,7 @@ config_t *config_new(void) newconfig->op = PM_OP_MAIN; newconfig->logmask = ALPM_LOG_ERROR | ALPM_LOG_WARNING; newconfig->configfile = strdup(CONFFILE); + newconfig->deltaratio = 0.0; if(alpm_capabilities() & ALPM_CAPABILITY_SIGNATURES) { newconfig->siglevel = ALPM_SIG_PACKAGE | ALPM_SIG_PACKAGE_OPTIONAL | ALPM_SIG_DATABASE | ALPM_SIG_DATABASE_OPTIONAL; @@ -397,8 +398,8 @@ static int _parse_options(const char *key, char *value, config->verbosepkglists = 1; pm_printf(ALPM_LOG_DEBUG, "config: verbosepkglists\n"); } else if(strcmp(key, "UseDelta") == 0) { - config->usedelta = 1; - pm_printf(ALPM_LOG_DEBUG, "config: usedelta\n"); + config->deltaratio = 0.7; + pm_printf(ALPM_LOG_DEBUG, "config: usedelta (default 0.7)\n"); } else if(strcmp(key, "TotalDownload") == 0) { config->totaldownload = 1; pm_printf(ALPM_LOG_DEBUG, "config: totaldownload\n"); @@ -429,6 +430,18 @@ static int _parse_options(const char *key, char *value, if(!config->arch) { config_set_arch(value); } + } else if(strcmp(key, "UseDelta") == 0) { + double ratio; + char *endptr; + ratio = strtod(value, &endptr); + if(*endptr != '\0' || ratio < 0.0 || ratio > 2.0) { + pm_printf(ALPM_LOG_ERROR, + _("config file %s, line %d: invalid value for '%s' : '%s'\n"), + file, linenum, "UseDelta", value); + return 1; + } + config->deltaratio = ratio; + pm_printf(ALPM_LOG_DEBUG, "config: usedelta = %f\n", ratio); } else if(strcmp(key, "DBPath") == 0) { /* don't overwrite a path specified on the command line */ if(!config->dbpath) { @@ -605,7 +618,7 @@ static int setup_libalpm(void) alpm_option_set_arch(handle, config->arch); alpm_option_set_checkspace(handle, config->checkspace); alpm_option_set_usesyslog(handle, config->usesyslog); - alpm_option_set_usedelta(handle, config->usedelta); + alpm_option_set_deltaratio(handle, config->deltaratio); alpm_option_set_ignorepkgs(handle, config->ignorepkg); alpm_option_set_ignoregroups(handle, config->ignoregrp); diff --git a/src/pacman/conf.h b/src/pacman/conf.h index 325fbb6..481132f 100644 --- a/src/pacman/conf.h +++ b/src/pacman/conf.h @@ -34,7 +34,7 @@ typedef struct __config_t { unsigned short print; unsigned short checkspace; unsigned short usesyslog; - unsigned short usedelta; + double deltaratio; char *arch; char *print_format; /* unfortunately, we have to keep track of paths both here and in the library -- 1.7.8.3
On 12/01/12 07:42, Dan McGee wrote:
Rework the frontend and backend to allow passing a ratio value in for UseDelta rather than having a hardcoded #define-d 0.7 value always used. This is useful for those with fast connections, who would likely benefit from tuning this ratio to lower values; it is also useful for general testing purposes.
The libalpm API changes for this, but we do support the old config file format with a no-value 'UseDelta' option; in this case we simply use the old default of 0.7.
We clamp the ratio values to a sane range between 0.0 and 2.0, allowing ratios above 1.0 for testing purposes.
Signed-off-by: Dan McGee <dan@archlinux.org>
Ack-by: Allan Looks good from some basic testing here. My only thought (which is possibly full of bikeshed, so feel free to ignore...) was do we really want to stick with a ratio or move to an absolute size difference? 0.9 of a 100MB package is much more useful than 0.9 of a 1KB package. Allan
On Wed, Jan 11, 2012 at 6:52 PM, Allan McRae <allan@archlinux.org> wrote:
On 12/01/12 07:42, Dan McGee wrote:
Rework the frontend and backend to allow passing a ratio value in for UseDelta rather than having a hardcoded #define-d 0.7 value always used. This is useful for those with fast connections, who would likely benefit from tuning this ratio to lower values; it is also useful for general testing purposes.
The libalpm API changes for this, but we do support the old config file format with a no-value 'UseDelta' option; in this case we simply use the old default of 0.7.
We clamp the ratio values to a sane range between 0.0 and 2.0, allowing ratios above 1.0 for testing purposes.
Signed-off-by: Dan McGee <dan@archlinux.org>
Ack-by: Allan
Looks good from some basic testing here.
My only thought (which is possibly full of bikeshed, so feel free to ignore...) was do we really want to stick with a ratio or move to an absolute size difference? 0.9 of a 100MB package is much more useful than 0.9 of a 1KB package.
$ pacman -Si | grep 'Download Size' | sort -k4 -n > /tmp/sizes.txt 4278 of 5490 packages available for me on x86_64 right now (77.9%) are under 1MiB in the sync repos right now; 5342 are less than 20MiB (97.3%). My guess is it isn't worth doing deltas at all for packages in the <1MiB group as the time to reconstitute the package will take longer than the download itself. With that said, what would your bikeshed idea look like? I can imagine something like `UseDelta = 5MiB` that would use deltas if the download size saved for that particular package was > 5MiB or something; the syntax seems a tad cryptic and not self-explanatory though. -Dan
participants (3)
-
Allan McRae
-
Dan McGee
-
Dan McGee