gpt4 book ai didi

objective-c - 分析 Objective-C 二进制图像大小

转载 作者:太空狗 更新时间:2023-10-30 03:12:14 24 4
gpt4 key购买 nike

我正在寻找工具和方法来确定我的 Cocoa 和 Cocoa-Touch 程序的哪些部分对最终二进制图像大小的贡献最大,以及帮助减少它的方法。我不是在寻找“魔法子弹”编译器标志。我正在寻找分析技术来评估和减少图像大小浪费,就像 Shark 和 Instruments 帮助运行时评估一样。

一阶近似值可能是 .o 的大小,但就优化和死代码剥离后的最终图像大小而言,这有多可信?如果我把所有的 .o 加起来,它们比我的最终图像大得多,所以很明显链接器已经帮了我很大的忙。但这意味着 .o 的大小可能不是一个有用的度量。

其他人如何在不破坏代码可维护性的情况下减少图像大小?

最佳答案

Apple 在 Code Size Performance Guidelines 上有一些很棒的文档,几乎所有这些都以某种形式适用于这个问题。如果需要,甚至还有一些关于迂腐方法的提示,例如手动对二进制中的符号进行排序。 :-)

我完全喜欢简单、纤薄的代码并最大限度地减少磁盘/内存占用。过早的优化总是一个坏主意,但一致的内务管理可以是防止垃圾堆积的好方法。不幸的是,我不知道分析代码大小的自动化方法,但有几种工具可以帮助提供特定的洞察力。

二进制图像大小

目标文件并不像您想象的那么糟糕。总和小于部分的一个原因是代码全部用单个标题连接在一起。虽然百分比不会很精确,但最大的目标文件是链接二进制文件的最大部分。

要了解目标文件中每个特定方法的原始长度,您可以使用 /usr/bin/otool 打印出汇编代码,标点为 Objective-C 方法名称:

$ otool -tV MyClass.o

我寻找与相对较短或简单的方法相对应的长程序集,并检查是否可以简化或完全删除代码。

除了 otool ,我发现 /usr/bin/size 可能非常有用,因为它按层次结构分解段和节,并向您显示每个的大小,包括目标文件和编译后的二进制文件。例如:
$ size -m -s __TEXT __text MyClass.o
$ size -m /Applications/iCal.app/Contents/MacOS/iCal

这是一个“大局” View ,尽管它通常会强化 __TEXT __text通常是文件中最大的文件之一,因此是开始修剪的好地方。

死码识别

没有人真的希望他们的二进制文件中充斥着从未使用过的代码。在像 Objective-C 这样的动态和松散耦合的语言中,很难或不可能静态地确定是否“使用”了特定代码。即使实例化了一个类或调用了一个方法,跟踪代码路径(理论的和实际的)也很头疼。我使用一些技巧来帮助解决这个问题。
  • 对于静态分析,我强烈推荐 Clang Static Analyzer (它很高兴地内置在雪豹上的 Xcode 3.2 中)。在它的所有其他优点中,该工具可以跟踪代码路径并识别无法执行的代码块,并且应该删除或修复周围的代码以便可以调用它。
  • 对于动态分析,我使用 gcov (带单元测试)识别哪个代码是 实际上执行。覆盖率报告(阅读类似 CoverStory 的内容)显示未执行的代码,结合手动检查和测试,可以帮助识别可能已死的代码。您必须调整一些设置并在二进制文件上手动运行 gcov。我用过 this blog post开始。

  • 在实践中,死代码在代码中占足够大的比例以在二进制大小或加载时间上产生实质性差异的情况并不常见,但死代码肯定会使维护复杂化,如果可以,最好摆脱它。

    符号可见性

    降低符号可见性似乎是一个奇怪的建议,但它使 dyld 的事情变得容易多了。 (在运行时加载程序的链接器)并使编译器能够执行更好的优化。考虑隐藏全局变量(未声明为 static )等,方法是在它们前面加上“隐藏”属性,或在 Xcode 中启用“默认隐藏的符号”并显式地使符号可见。我使用以下宏:
    #define HIDDEN __attribute__((visibility("hidden")))
    #define VISIBLE __attribute__((visibility("default")))

    我找 /usr/bin/nm 对于识别不必要的可见符号以及识别您可能不知道或没有考虑过的潜在外部依赖关系非常宝贵。
    $ nm -m -s __TEXT __text MyClass.o  # -s displays only a given section
    $ nm -m -p MyClass.o # -p preserves symbol table ordering (no sort)
    $ nm -m -u MyClass.o # -u displays only undefined symbols

    尽管降低符号可见性不太可能直接减小二进制文件的大小,但编译器可能能够进行其他情况下无法做到的改进。此外,您可以减少对不打算公开的符号的意外依赖。

    分析库依赖和加载

    除了原始二进制大小之外,分析您链接到哪些动态库并消除那些可能是不必要的,尤其是可能尚未加载的不太常用的框架,通常会很有帮助。 (您也可以从 Xcode 中看到这一点,但是对于复杂的项目,有时事情会漏掉,所以这也有助于在构建后进行方便的完整性检查。)再次, otool 去救...
    $ otool -L MyClass.o

    另一个(非常冗长的)替代方法是使用 dyld打印加载的库,像这样(来自终端):
    $ export DYLD_PRINT_LIBRARIES=1
    $ /Applications/iCal.app/Contents/MacOS/iCal

    这准确地显示了正在加载的内容,包括您的代码链接的库的依赖项。

    分析启动性能

    通常,您真正关心的是代码大小和库依赖项是否真正影响启动时间。设置这个环境变量会导致 dyld报告负载统计信息,这确实有助于查明加载时间:
    $ export DYLD_PRINT_STATISTICS=1
    $ /Applications/iCal.app/Contents/MacOS/iCal

    在 Leopard 及更高版本上,您会注意到有关“ dyld 共享缓存 ”的条目。基本上,动态链接器创建了一个由最常用的动态库组成的统一“ super 库”。在 this Apple documentation中提到了,并且可以使用 DYLD_SHARED_REGION 更改行为和 DYLD_NO_FIX_PREBINDING环境变量,类似上面。见 man dyld 详情。

    关于objective-c - 分析 Objective-C 二进制图像大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/960470/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com