4

在静态库与共享库的争论中,我经常听说共享库消除了重复并减少了整体磁盘空间。但是共享库在现代 Linux 发行版中真正节省了多少磁盘空间?如果所有程序都使用静态库编译,需要多少空间?有没有人计算过典型桌面 Linux 发行版(例如 Ubuntu)的数字?有没有可用的统计数据?

附录:

所有答案都提供了丰富的信息并受到赞赏,但他们似乎拒绝了我的问题,而不是试图回答它。Kaleb 是在正确的轨道上,但他选择计算内存空间而不是磁盘空间的数字(我的问题是磁盘空间)。

因为程序只为它们使用的部分静态库“付费”,所以几乎不可能定量地知道所有静态与所有共享的磁盘空间差异。

现在我意识到几乎不可能回答我的问题,我觉得我的问题很糟糕。但我会把它留在这里以保留信息丰富的答案。

所以 SO 不再唠叨我选择一个答案,我将选择最受欢迎的一个(即使它回避了这个问题)。

4

5 回答 5

9

我不确定您是从哪里听到的,但减少磁盘空间主要是一个红鲱鱼,因为驱动器空间接近每 GB 几美分。共享库的真正好处在于这些库的安全性和错误修复更新;使用静态库的应用程序必须使用新库单独重建,而所有使用共享库的应用程序都可以通过仅替换几个文件来立即更新。

于 2010-01-20T20:25:59.657 回答
6

共享库不仅可以节省磁盘空间,还可以节省内存,这一点更为重要。预链接步骤在这里很重要......您不能在同一个库的两个实例之间共享内存页面,除非它们被加载到相同的地址,并且预链接允许这种情况发生。

于 2010-01-20T20:46:57.640 回答
4

共享库不一定会节省磁盘空间或内存。

当应用程序链接到静态库时,只有应用程序使用的库的那些部分才会被拉入应用程序二进制文件中。库存档 (.a) 包含目标文件 (.o),如果它们被很好地分解,应用程序将通过仅链接它使用的目标文件来使用更少的内存。共享库将在磁盘和内存中包含整个库,无论其中的一部分是否被应用程序使用。

对于台式机和服务器系统,这不太可能带来整体上的胜利,但如果您正在开发嵌入式应用程序,那么值得尝试静态链接所有应用程序,看看这是否能给您带来整体节省。

于 2010-01-22T23:43:09.000 回答
2

好的,也许不是答案,但我会考虑节省内存。节省将基于第一个应用程序后加载库的次数,因此让我们使用快速脚本找出每个库在系统上节省多少:

#!/bin/sh

lastlib=""
let -i cnt=1
let -i size=0
lsof | grep 'lib.*\.so$' | awk '{print $9}' | sort | while read lib ; do
    if [ "$lastlib" == "$lib" ] ; then
        let -i cnt="$cnt + 1"
    else
        let -i size="`ls -l $lib | awk '{print $5}'`"
        let -i savings="($cnt - 1) * $size"
        echo "$lastlib: $savings"
        let -i cnt=1
    fi
    lastlib="$lib"
done

这将为我们节省每个库,如下所示:

...
/usr/lib64/qt4/plugins/crypto/libqca-ossl.so: 0
/usr/lib64/qt4/plugins/imageformats/libqgif.so: 540640
/usr/lib64/qt4/plugins/imageformats/libqico.so: 791200
...

然后,总节省:

$ ./checker.sh | awk '{total = total + $2}END{print total}'
263160760

所以,粗略地说,在我的系统上,我节省了大约 250 Megs 的内存。您的里程会有所不同。

于 2010-01-20T21:04:43.533 回答
2

我能够找出部分定量的答案,而无需做大量的工作。这是我的(脑筋急转弯)方法:

1) 使用以下命令生成软件包列表及其安装大小和依赖项列表:

dpkg-query -Wf '${Package}\t${Installed-Size}\t${Depends}

2)解析结果并为每个包构建统计图:

struct PkgStats
{
    PkgStats() : kbSize(0), dependantCount(0) {}
    int kbSize;
    int dependentCount;
};

typedef std::map<std::string, PkgStats> PkgMap;

直接依赖于该包dependentCount的其他包的数量在哪里。

结果

以下是对我的系统依赖最多的包的前 20 个列表:

Package             Installed KB    # Deps  Dup'd MB
libc6               10096           750     7385
python              624             112     68
libatk1.0-0         200             92      18
perl                18852           48      865
gconf2              248             34      8
debconf             988             23      21
libasound2          1428            19      25
defoma              564             18      9
libart-2.0-2        164             14      2
libavahi-client3    160             14      2
libbz2-1.0          128             12      1
openoffice.org-core 124908          11      1220
gcc-4.4-base        168             10      1
libbonobo2-0        916             10      8
cli-common          336             8       2
coreutils           12928           8       88
erlang-base         6708            8       46
libbluetooth3       200             8       1
dictionaries-common 1016            7       6

Dup'd MB如果没有共享 ( = installed_size * (dependants_count - 1), for ) 将被复制的兆字节数在哪里dependants_count > 1

看到 libc6 在上面并不奇怪。:) 顺便说一句,我有一个典型的 Ubuntu 9.10 安装程序,安装了一些与编程相关的软件包,以及一些 GIS 工具。

一些统计数据:

  • 安装包总数:1717
  • 平均直接家属人数:0.92
  • 不共享的总重复大小(忽略间接依赖项):10.25GB
  • 直方图 # 的直接受抚养人(注意对数 Y 刻度): 直方图

请注意,以上完全忽略了间接依赖(即一切都应该至少间接依赖于 libc6)。我真正应该做的是构建所有依赖关系的图表并将其用作我的统计数据的基础。也许我会在某个时候解决它并发布一篇冗长的博客文章,其中包含更多细节和严谨性。

于 2010-01-21T20:29:47.983 回答