# Improve Pacman Performance (简体中文)

翻译状态： 本文是英文页面 Improve_Pacman_Performance 的翻译，最后翻译时间：2013-12-18，点击这里可以查看翻译后英文页面的改动。

## 提高数据库访问速度

Pacman将所有软件包的信息放在一一对应的许多小文件中。通过改善数据库访问速度，可以减少花在数据库相关任务上的时间，比如：寻找软件包、检索软件包依赖性。

最安全最简单的方法是以root身份运行

    # pacman-optimize

上述命令试图将所有小文件放在磁盘上同一个物理区域，以减少磁头移动。这种方法很安全，但不一定有效。其效果取决于你的文件系统、磁盘使用率、和磁盘碎片程度。另一种更激进的方式是在优化数据库之前首先删除 cache 中所有未安装以及不使用的仓库中的包：

    # pacman -Sc && pacman-optimize

## 加快下载速度

注意: 如果你的包下载速度变得极慢，首先确定你用的是那些(镜像)网站而不是ftp.archlinux.org，因为后者从2007年3月开始限速。

可以通过各种下载工具而不是Pacman内置的下载方式，来改善Pacman的下载速度。

不论怎样，在做任何修改前，你必须确定拥有了最新版的Pacman：

    # pacman -Syu

### 使用 Powerpill

Powerpill 是 Pacman 的完整包裹程序，增加了平行下载和分段下载功能，加速下载过程。Pacman 一次只下载一个软件包，完成后才开始下一个下载。 Powerpill 同时下载多个软件包。 Powerpill wiki 页面提供了基本的配置和使用方法。

### 使用powerpill-light(过时)

pacman2aria2 提供了一个名为 "powerpill-light" 的脚本，替代了之前用 Perl 写的 powerpill。现在 Powerpill 已经重新发布，所以 powerpill-light 已经过时。

### 使用wget

对于需要更强大代理支持的用户来说，用wget比用Pacman自己的下载方式更加方便。

要使用 `wget`，首先使用`pacman -S wget`安装它，然后修改`/etc/pacman.conf`并在其中的`[options]`区段将下面内容去掉注释：

    XferCommand = /usr/bin/wget -c --passive-ftp -c %u

除了将`wget`参数放在`/etc/pacman.conf`里，你也可以直接修改`wget`配置文件（全局文件是`/etc/wgetrc`，各个用户的文件是`$HOME/.wgetrc`）。

### 使用aria2

aria2是一个具有断点续传和分块下载功能的轻量级下载软件，支持HTTP/HTTPS/FTP协议。aria2可以多线程通过HTTP/HTTPS和FTP协议连接镜像服务器，显著提高下载速度。

注意: 在Pacman的XferCommand使用 aria2c 不会导致并行下载多个包。因为Pacman调用XferCommand时是一次一个包调用的，等待下载完成才会启动下一个。想要并行下载多个包，参见下面的 powerpill-light 部分。

#### 安装

通过`pacman -S aria2`安装aria2。

#### 配置

修改`/etc/pacman.conf`，在`[option]`段添加下列一行（如果已存在则修改之）：

    XferCommand = /usr/bin/aria2c --allow-overwrite=true -c --file-allocation=none --log-level=error -m2 --max-connection-per-server=2 --max-file-not-found=5 --min-split-size=5M --no-conf --remote-time=true --summary-interval=60 -t5 -d / -o %o %u

#### 参数细节

`/usr/bin/aria2c`
  aria2主程序的完整路径。
`--allow-overwrite=true`
  如果相应的控制文件不存在则重新下载。(默认值：false)
`-c, --continue`
  如果相应的控制文件存在则继续未完成的下载。
`--file-allocation=none`
  下载开始前预设空间。(默认值: prealloc) 1
`--log-level=error`
  设置错误输出级别。 (默认值: debug)
`-m2, --max-tries=2`
  从每个镜像源下载特定文件的最大尝试次数设为2。 (默认值: 5)
`--max-connection-per-server=2`
  下载每个文件时到每个镜像源的最大连接数设为2。(默认值: 1)
`--max-file-not-found=5`
  如果5次尝试后仍未下载完成1字节则强制停止。(默认值: 0)
`--min-split-size=5M`
  只有当文件大于5MB时才分割下载。 (默认值: 20M)
`--no-conf`
  不加载 `aria2.conf` 。 (默认值: `~/.aria2/aria2.conf`)
`--remote-time=true`
  对远程文件应用时间戳并应用到本地文件。 (默认值: false)
`--summary-interval=60`
  每60s显式一次下载总进度。 (默认值: 60) 2
`-t5, --timeout=5`
  对镜像源的连接建立后5s超时。 (默认值: 60)
`-d, --dir`
  由 pacman 设定的文件下载目录。
`-o, --output`
  输出的下载文件的文件名
`%o`
  代表 pacman 指定的文件名的变量
`%u`
  代表 pacman 指定的 URL 的变量

#### 其他解释

1 `--file-allocation=falloc`
  对较新的文件系统建议使用，如 ext4(支持extents)、 btrfs 和 xfs 因为它们存储大文件(GB级别)时速度很快。 较老的文件系统如ext3则不要使用falloc，因为prealloc消耗的时间几乎和标准分配相同，同时会锁定aria2进程而停止下载。

2 `--summary-interval=0`
  减少下载总进度的输出并有可能改善性能。日志会按照 `log-level` 选项的设置继续输出。

### pacget (Aria2) 镜像脚本

此脚本将大大提高宽带用户的下载速度。它从pacman获得下载链接，在/etc/pacman.d/mirrorlist中寻找镜像服务器并全部添加到aria2使用的镜像。最终的结果就是aria2同时连接到10-20个服务器（默认是4个）进行下载，这大大提高了宽带用户的下载速度。此法将使大部分用户达到带宽极限。

注意: 在XferCommand中，你必须将'exec'放在/usr/bin/pacget前面，因为一旦你终止了pacget或者aria2（用了pacget的进程ID），pacman也同时终止。这将防止一些“不便”，因为Pacman 不会在你将它停止后继续运行。
警告: 如果你选择过期的镜像服务器，可能会遭遇很多问题。只要使用 Reflector 脚本选择几个和主服务器同步的、快速的服务器。不要选择过期的镜像服务器，因为可能会引起错误。同时，ftp.archlinux.org 拥有2个IP地址，你可能只需要其中一个，并且将其添加到`/etc/hosts`中。

    /usr/bin/pacget

    #!/bin/bash

    msg() {
      echo ""
      echo -e "   \033[1;34m->\033[1;0m \033[1;1m${1}\033[1;0m" >&2
    }

    error() {
      echo -e "\033[1;31m==> ERROR:\033[1;0m \033[1;1m$1\033[1;0m" >&2
    }

    CONF=/etc/pacget.conf
    STATS=/etc/pacget.stats
    ARIA2=$(which aria2c 2> /dev/null)

    # ----- do some checks first -----
    if [ ! -x "$ARIA2" ]; then
      error "aria2c was not found or isn't executable."
      exit 1
    fi

    if [ $# -ne 2 ]; then
      error "Incorrect number of arguments"
      exit 1
    fi

    filename=$(basename $1)
    server=${1%/$filename}
    arch=$(grep ^Architecture /etc/pacman.conf | cut -d '=' -f2 | sed 's/ //g')
    if [[ $arch = "auto" ]]; then
      arch=$(uname -m)
    fi
    # Determine which repo is being used
    repo=$(awk -F'/' '$(NF-2)~/^(community|core|extra|testing|comunity-testing|multilib)$/{print $(NF-2)}' <<< $server)
    [ -z $repo ] && repo="custom"

    # For db files, or when using a custom repo (which most likely doesn't have any mirror),
    # use only the URL passed by pacman; Otherwise, extract the list of servers (from the include file of the repo) to download from
    url=$1
    if ! [[ $filename = *.db || $repo = "custom" ]]; then
      mirrorlist=$(awk -F' *= *' '$0~"^\\["r"\\]",/Include *= */{l=$2} END{print l}' r=$repo /etc/pacman.conf)
      if [ -n mirrorlist ]; then
        num_conn=$(grep ^split $CONF | cut -d'=' -f2)
        url=$(sed -r '/^Server *= */!d; s/Server *= *//; s/\$repo'"/$repo/"'; s/\$arch'"/$arch/; s/$/\/$filename/" $mirrorlist | head -n $(($num_conn *2)) )
      fi
    fi

    msg "Downloading $filename"
    cd /var/cache/pacman/pkg/

    touch $STATS

    $ARIA2 --conf-path=$CONF --max-tries=1 --max-file-not-found=5 \
      --uri-selector=adaptive --server-stat-if=$STATS --server-stat-of=$STATS \
      --allow-overwrite=true --remote-time=true --log-level=error --summary-interval=0 \
      $url --out=${filename}.pacget && [ ! -f ${filename}.pacget.aria2 ] && mv ${filename}.pacget $2 && chmod 644 $2

    exit $?

    /etc/pacget.conf

    # The log file
    log=/var/log/pacget.log
    # Number of servers to download from
    split=5
    # Minimum file size that justifies a split, i.e. concurrent download (default 20M)
    min-split-size=1M
    # Maximum download speed (0 = unrestricted)
    max-download-limit=0
    # Minimum download speed (0 = do not care)
    lowest-speed-limit=0
    # Server timeout period
    timeout=5
    # 'none' or 'falloc'
    file-allocation=none

将此脚本另存为/usr/bin/pacget，并且使其具有可执行属性：

    # chmod 755 /usr/bin/pacget

在/etc/pacman.conf中添加如下内容（如果已存在则修改之）：

    XferCommand = exec /usr/bin/pacget %u %o

注意: 如果使用ftp.archlinux.org作为首选服务器，有可能会出现一些问题，例如镜像服务器还没有完全同步。要发挥此脚本的最大效力，需要选择一个更合适（有规律地进行同步）的镜像服务器，然后将其放在服务器列表的最顶端。这样做可以避免因为各个服务器还没有同步，而只能从ftp.archlinux.org获得数据的情况。

### 使用其它程序

这里还有一些可以和Pacman协同工作的下载软件。下面列举了它们对应的XferCommand命令写法：

- `snarf`: `XferCommand = /usr/bin/snarf -N %u`
- `lftp`: `XferCommand = /usr/bin/lftp -c pget %u`
- `axel`: `XferCommand = /usr/bin/axel -n 2 -v -a -o %o %u`

## 选择最快的镜像

当下载包时，pacman 会按照 `/etc/pacman.d/mirrorlist`中的顺序使用镜像。然而最上面的镜像并不一定对你最快。

注意: 这不会应用到 powerpill-light，因为它会连接到许多服务器来同时下载，提高下载速度。单个连接的速度不是很重要，并且 powerpill-light 可以配置每个连接的最小速度。

### 选择一个本地镜像

最简单的方法是编辑 mirrorlist 文件，然后在文件最上面设置一个本地的镜像，这样 pacman 就会优先使用这个镜像。

另外，pacman.conf 文件也可以编辑，在引用mirrorlist文件的一行之前放置一个本地镜像，也就是写着 "add your preferred servers here" 的地方。如果你对不同仓库使用同一镜像会更安全一些。

### 使用 rankmirrors

你可以使用 rankmirrors 来对 pacman 镜像通过连接时间和速度排序。

### 使用 Reflector

你也可以使用 Reflector 来获取一个安装速度排序的定制镜像列表。

### 在改变镜像之后

在改变镜像之后最好刷新一下pacman的数据库。使用两个 y 的强制刷新.

    # pacman -Syy

## 在局域网共享包

如果你在局域网上运行几个 Arch 机器，你可以共享包，这样就可以大大减少下载时间。记住你不能在不同的体系结构(即 i686 and x86_64)下共享，否则会遇到问题。

参见 Pacman tips#Network_shared_pacman_cache.

Categories:

- Package management (简体中文)
- 简体中文