Профильный размер двухуровневого изображения Objective C

Вы создаете систему мьютекс .

У меня нет кода Delphi, но вот код C ++:

HANDLE Mutex;

const char MutexName[] = "MyUniqueProgramName";

Mutex = OpenMutex(MUTEX_ALL_ACCESS, false, MutexName);

if (Mutex)
     throw Exception("Program is already running.");
else
     Mutex = CreateMutex(NULL, true, MutexName);
22
задан Rob Napier 6 June 2009 в 20:34
поделиться

2 ответа

Apple has some awesome docs on Code Size Performance Guidelines, almost all of which applies to this question in some form. There are even tips for pedantic approaches like manually ordering symbols in the binary if desired. :-)

I'm totally a fan of simple, slim code and minimizing disk/memory footprint. Premature optimization is always a bad idea, but consistent housekeeping can be a good way to prevent cruft from accumulating. Unfortunately, I don't know of an automated way to profile code sizes, but several tools exist that can help provide specific insight.

Binary Image Size

Object files aren't as terrible an approximation as you'd guess. One reason the sum is smaller than the parts is because the code is all joined together with a single header. Although the percentages won't be precise, the biggest object files are the biggest parts of the linked binary.

For understanding the raw length of each particular method in an object file, you could use /usr/bin/otool to print out the assembly code, punctuated by Objective-C method names:

$ otool -tV MyClass.o

I look for long stretches of assembly that correspond to relatively short or simple methods and examine whether the code can be simplified or removed entirely.

In addition to otool, I've found that /usr/bin/size can be quite useful, since it breaks up segments and sections hierarchically and shows you the size of each, both for object files and compiled binaries. For example:

$ size -m -s __TEXT __text MyClass.o
$ size -m /Applications/iCal.app/Contents/MacOS/iCal

This is a "bigger picture" view, although it usually reinforces that __TEXT __text is often one of the largest in the file, and hence a good place to start pruning.

Dead Code Identification

Nobody really wants their binary to be littered with code that is never used. In a dynamic and loosely-coupled language like Objective-C, it can be difficult or impossible to statically determine whether specific code is "used" or not. Even if a class is instantiated or a method is called, tracing code paths (both theoretical and actual) can be a headache. I use a few tricks to help with this.

  • For static analysis, I strongly recommend the Clang Static Analyzer (which is happily built into Xcode 3.2 on Snow Leopard). Among all its other virtues, this tool can trace code paths an identify chunks of code that cannot possibly be executed, and should either be removed or the surrounding code should be fixed so that it can be called.
  • For dynamic analysis, I use gcov (with unit testing) to identify which code is actually executed. Coverage reports (read with something like CoverStory) reveal un-executed code, which — coupled with manual examination and testing — can help identify code that may be dead. You do have to tweak some setting and run gcov manually on your binaries. I used this blog post to get started.

In practice, it's uncommon for dead code to be a large enough proportion of the code to make a substantial difference in binary size or load time, but dead code certainly complicates maintenance, and it's best to get rid of it if you can.

Symbol Visibility

Reducing symbol visibility may seem like a strange recommendation, but it makes things much easier for dyld (the linker that loads programs at runtime) and enables the compiler to perform better optimizations. Consider hiding global variables (that aren't declared as static) etc. by prefixing them with a "hidden" attribute, or enabling "Symbols Hidden by Default" in Xcode and explicitly making symbols visible. I use the following macros:

#define HIDDEN __attribute__((visibility("hidden")))
#define VISIBLE __attribute__((visibility("default")))

I find /usr/bin/nm invaluable for identifying unnecessarily visible symbols, and for identifying potential external dependencies you might be unaware of or hadn't considered.

$ 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

Although reducing symbol visibility is unlikely to directly reduce the size of your binary, the compiler may be able to make improvements it couldn't otherwise. Also, you stand to reduce accidental dependencies on symbols you didn't intend to expose.

Analyzing Library Dependencies and Loading

In addition to raw binary size, it can often be quite helpful to analyze which dynamic libraries you link to, and eliminate those that might be unnecessary, particularly less-commonly-used frameworks that may not be loaded yet. (You can also see this from Xcode too, but with complex projects, sometimes things slip through, so this also makes for a handy sanity check after building.) Again, otool to the rescue...

$ otool -L MyClass.o

Another (extremely verbose) alternative is to have dyld print loaded libraries, like so (from Terminal):

$ export DYLD_PRINT_LIBRARIES=1
$ /Applications/iCal.app/Contents/MacOS/iCal

This shows exactly what is being loaded, including dependencies of the libraries your code links against.

Analyzing Launch Performance

Usually, what you really care about is whether the code size and library dependencies are truly affecting launch time. Setting this environment variable will cause dyld to report load statistics, which can really help pinpoint how time was spent on load:

$ export DYLD_PRINT_STATISTICS=1
$ /Applications/iCal.app/Contents/MacOS/iCal

On Leopard and later, you'll notice entries about "dyld shared cache". Basically, the dynamic linker creates a consolidated "super library" composed of the most frequently-used dynamic libraries. It is mentioned in this Apple documentation, and the behavior can be altered with the DYLD_SHARED_REGION and DYLD_NO_FIX_PREBINDING environment variables, similar to above. See man dyld for details.

41
ответ дан 29 November 2019 в 04:33
поделиться

Возможно, вы захотите посмотреть otool. В частности, вы, вероятно, захотите использовать флаг -l, который отображает все команды загрузки (также известные как разделы и сегменты), составляющие ваш двоичный файл.

Сказав все это, вы обычно обнаружите, что ресурсы более значительны, чем код, который вы пишете, поэтому мне интересно, с какой проблемой вы столкнулись и пытаетесь решить. Наши приложения содержат довольно много кода, но все же занимают всего несколько МБ. Возможно, вы статически связываетесь с какими-то большими библиотеками - я не знаю.

Если большая часть вашего кода - это Objective-C, очень небольшая его часть будет удалена с удалением мертвого кода (по очевидным причинам), так что не будет иметь большого значения.

Что будет иметь значение, так это отладочная информация, которая будет существенной. Ваши объектные файлы будут включать это, но вы d обычно хранят его в отдельном пакете dSYM, когда вы связываете его, поэтому он не будет включен в окончательный двоичный файл (или, по крайней мере, это то, что вы должны делать).

Ваш код будет в __TEXT, __text сегмент / раздел.

Я почти уверен, что компоновщик объединит эквивалентные строки, так что общая сумма будет меньше, чем сумма частей для этих разделов, но, я думаю, обычно не намного.

Я бы также ожидайте, что ваши разделы перемещения и символов будут меньше суммы частей. Вы должны удалить из связанного двоичного файла ненужные символы для экономии места (что не то же самое, что удаление отладочной информации). См. Параметр «Разрезать связанный продукт» в Xcode.

Еще одна вещь, которую следует помнить, это то, что ваш связанный двоичный файл будет двоичным файлом FAT, тогда как объектные файлы обычно нет.

t быть включенным в окончательный двоичный файл (или, по крайней мере, это то, что вы должны делать).

Ваш код будет в сегменте / разделе __TEXT, __text.

Я почти уверен, что компоновщик объединит эквивалентные строки таким образом, общая сумма будет меньше суммы частей для этих разделов, но, я думаю, обычно не намного.

Я также ожидаю, что ваши разделы перемещения и символов будут меньше суммы частей. Вы должны удалить из связанного двоичного файла ненужные символы для экономии места (что не то же самое, что удаление отладочной информации). См. Параметр «Разрезать связанный продукт» в Xcode.

Еще одна вещь, которую следует помнить, это то, что ваш связанный двоичный файл будет двоичным файлом FAT, тогда как объектные файлы обычно нет.

t быть включенным в окончательный двоичный файл (или, по крайней мере, это то, что вы должны делать).

Ваш код будет в сегменте / разделе __TEXT, __text.

Я почти уверен, что компоновщик объединит эквивалентные строки таким образом, общая сумма будет меньше суммы частей для этих разделов, но, я думаю, обычно не намного.

Я также ожидаю, что ваши разделы перемещения и символов будут меньше суммы частей. Вы должны удалить из связанного двоичного файла ненужные символы для экономии места (что не то же самое, что удаление отладочной информации). См. Параметр «Разрезать связанный продукт» в Xcode.

Еще одна вещь, которую следует помнить, это то, что ваш связанный двоичный файл будет двоичным файлом FAT, тогда как объектные файлы обычно нет.

__text segment / section.

Я почти уверен, что компоновщик объединит эквивалентные строки, так что общая сумма будет меньше суммы частей для этих разделов, но, как мне кажется, обычно не намного.

Я бы сделал это. также ожидайте, что ваши разделы перемещения и символов будут меньше суммы частей. Вы должны удалить из связанного двоичного файла ненужные символы для экономии места (что не то же самое, что удаление отладочной информации). См. Параметр «Разрезать связанный продукт» в Xcode.

Еще одна вещь, которую следует помнить, это то, что ваш связанный двоичный файл будет двоичным файлом FAT, тогда как объектные файлы обычно нет.

__text segment / section.

Я почти уверен, что компоновщик объединит эквивалентные строки, так что общая сумма будет меньше суммы частей для этих разделов, но, как мне кажется, обычно не намного.

Я бы сделал это. также ожидайте, что ваши разделы перемещения и символов будут меньше суммы частей. Вы должны удалить из связанного двоичного файла ненужные символы для экономии места (что не то же самое, что удаление отладочной информации). См. Параметр «Разрезать связанный продукт» в Xcode.

Еще одна вещь, которую следует помнить, это то, что ваш связанный двоичный файл будет двоичным файлом FAT, тогда как объектные файлы обычно нет.

Я также ожидаю, что ваши разделы перемещения и символов будут меньше суммы частей. Вы должны удалить из связанного двоичного файла ненужные символы для экономии места (что не то же самое, что удаление отладочной информации). См. Параметр «Разрезать связанный продукт» в Xcode.

Еще одна вещь, которую следует помнить, это то, что ваш связанный двоичный файл будет двоичным файлом FAT, тогда как объектные файлы обычно нет.

Я также ожидаю, что ваши разделы перемещения и символов будут меньше суммы частей. Вы должны удалить из связанного двоичного файла ненужные символы для экономии места (что не то же самое, что удаление отладочной информации). См. Параметр «Разрезать связанный продукт» в Xcode.

Еще одна вещь, которую следует помнить, это то, что ваш связанный двоичный файл будет двоичным файлом FAT, тогда как объектные файлы обычно нет.

3
ответ дан 29 November 2019 в 04:33
поделиться