огромные исполняемые файлы из-за символов отладки, почему?

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

Приложение разбито примерно на 5 общих объектов и главный объект. Один из самых больших общих объектов был 40 МБ и вырос до 50, даже когда код уменьшился.

Я не совсем удивился, что код начал расти, потому что, в конце концов, мы добавляем некоторые функции. Но меня удивило, что он вырос на 20%. Конечно, никто и близко не подошел к написанию 20% кода, поэтому мне трудно представить, как он так вырос. Мне довольно сложно анализировать этот модуль, но в пятницу у меня есть новые точки данных, которые проливают некоторый свет.

Есть, наверное, 10 каналов на серверы SOAP. Код автогенерируется, плохо. У каждой службы был один класс парсера с точно таким же кодом, например:

#include <boost/shared_ptr.hpp>
#include <xercesstuff...>
class ParserService1 {
public:
  void parse() {
    try {
      Service1ContentHandler*p = new Service1ContentHandler( ... );
      parser->setContentHandler(p);
      parser->parser();
    } catch (SAX ...) {
      ...
    }
  }
};

Эти классы были совершенно ненужными, работает одна функция. Каждый класс ContentHandler был автоматически сгенерирован с одинаковыми 7 или 8 переменными, который я смог разделить с помощью наследования.

Так что я ожидал, что размер кода уменьшится, когда я удалил классы парсера и все остальное из кода. Но при наличии всего 10 сервисов я не ожидал, что он упадет с 38 МБ до 36 МБ. Это возмутительное количество символов.

Единственное, что я могу придумать, это то, что каждый парсер включал boost :: shared_ptr, некоторые вещи парсера Xerces, и что каким-то образом компилятор и компоновщик сохраняют все эти символы повторно для каждого файл. В любом случае мне любопытно узнать.

Итак, может ли кто-нибудь подсказать, как я буду отслеживать, почему такая простая модификация должна иметь такое большое влияние? Я могу использовать nm в модуле, чтобы посмотреть на символы внутри, но это приведет к созданию болезненного, огромного количества полу-читаемого материала.

Кроме того, когда коллега запускала свой код с моей новой библиотекой, время пользователя уменьшилось с 1 мин 55 до 1 мин 25 секунд. Реальное время сильно варьируется, потому что мы ждем медленных серверов SOAP (IMHO, SOAP - невероятно плохая замена CORBA ...), но время процессора довольно стабильно. Я ожидал небольшого прироста от столь значительного уменьшения размера кода, но суть в том, что на сервере с большой памятью я был очень удивлен, что скорость сильно пострадала, учитывая, что я не менял архитектуру Сама обработка XML.

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

Обновить: потому что мы ждем медленных серверов SOAP (IMHO, SOAP - невероятно плохая замена CORBA ...), но время процессора довольно стабильно. Я ожидал небольшого прироста от столь значительного уменьшения размера кода, но суть в том, что на сервере с большой памятью я был очень удивлен, что скорость сильно пострадала, учитывая, что я не менял архитектуру Сама обработка XML.

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

Обновить: потому что мы ждем медленных серверов SOAP (IMHO, SOAP - невероятно плохая замена CORBA ...), но время процессора довольно стабильно. Я ожидал небольшого прироста от столь значительного уменьшения размера кода, но суть в том, что на сервере с большой памятью я был очень удивлен, что скорость сильно пострадала, учитывая, что я не менял архитектуру Сама обработка XML.

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

Обновить: I verified that in fact, having debugging symbols in the task does not appear to change the run time at all. I did this by creating a header file that included lots of stuff, including the two that had the effect here: boost shared pointers and some of the xerces XML parser. There appears to be no runtime performance hit (I checked because there were differences of opinion between two answers). However, I also verified that including header files creates debugging symbols for each instance, even though the stripped binary size is unchanged. So if you include a given file, even if you don't even use it, there is a fixed number of symbols objected into that object that are not folded together at link time even though they are presumably identical.

My code looks like:

#include "includetorture.h"
void f1()
{
    f2(); // call the function in the next file
}

The size with my particular include files was about 100k per source file. Presumably, if I had included more, it would be higher. The total executable with the includes was ~600k, without about 9k. I verified that the growth is linear with the number of files doing the including, but the stripped code is the same size regardless, as it should be.

Clearly I was mistaken thinking this was the reason for the performance gain. I think I have accounted for that now. Even though I didn't remove much code, I did streamline a lot of big xml string processing, and reduced the path through code considerably, and that is presumably the reason.

10
задан Dov 3 June 2011 в 14:53
поделиться