клиент пожаловался, что работа кода на одном участке очень медленная, стал разбираться и обнаружил
что есть некий класс в кострукторе которого происходит инициализация внутренних членов, что то типа так:
так вот я в цикле создаю 8тысяч раз объект класса foo и засовываю это в лист.
и все это занимает около 50-80 секунд — просто очень долго, но если закоментить инициализацию в конструкторе то время на исполнение уходит 3-10 секунд, что вполне терпимо.
Есть какие-нибудь идеи куда смотреть, что менять? (про архитектуру пока не надо )
Спасибо.
Здравствуйте, Alex Dav, Вы писали:
AD>так вот я в цикле создаю 8тысяч раз объект класса foo и засовываю это в лист. AD>и все это занимает около 50-80 секунд — просто очень долго, но если закоментить инициализацию в конструкторе то время на исполнение уходит 3-10 секунд, что вполне терпимо.
AD>Есть какие-нибудь идеи куда смотреть, что менять? (про архитектуру пока не надо )
Ты же ничего не написал про использование этого класса. Строки меняются? Как часто?
Может помочь, к примеру, замена отдельных строк в классе на специальный контейнер "Коллекция строк", единый для всех экземпляров твоего класса.
Память в контейнере выделяется сразу под большое кол-во строк — снизится нагрузка на манагер памяти.
Детали его реализации зависят от способа использования строк — думай сам
Внутри foo, вместо строк будут храниться индексы на строки в контейнере.
_____________________
С уважением,
Stanislav V. Zudin
Здравствуйте, Stanislav V. Zudin, Вы писали:
SVZ>Ты же ничего не написал про использование этого класса. Строки меняются? Как часто?
так проблем с использованием нет строки конечно разные для каждого экзэмрляра.
я просто пытаюсь понять как инициализация 10 переменных может так влиять на производительность, ведь даже если пустой конструктор выполняется — память для них выделяется.
2. Если "test" это некоторого рода константа, то желательно ее оформить как таковую. Поскольку, присваивая c-строку string-у, конструктор делает лишний проход для вычисления длины null-terminated строки.
Теперь из неявного. Если количество объектов заранее известно, то, предположительно, хранение в std::vector положительно скажется на производительности при добавлении за счет того, что выделение heap-a происходит один раз (см. вызов reserve):
std::vector<foo> a;
// reserve memory
a.reserve(N);
foo o;
while(.t.)
{
// read state into the o object and put it into the a array
...
a.push_back(o);
}
Из недостатков — лишний вызов конструктора копирования при вызове push_back.
Здравствуйте, Анатолий Широков, Вы писали:
АШ>Теперь из неявного. Если количество объектов заранее известно, то, предположительно, хранение в std::vector положительно скажется на
столько стараний, а автор явно указал что он в листе хранит)
Здравствуйте, Alex Dav, Вы писали:
AD>я просто пытаюсь понять как инициализация 10 переменных может так влиять на производительность, ведь даже если пустой конструктор выполняется — память для них выделяется.
Скорее всего в конструкторе копирования std::string есть проверка на то — пустая строка или нет. Если да — то память под содержимое строки память не выделяется и ничего не копируется. (так для каждого временного объекта и копирования)
Здравствуйте, Alex Dav, Вы писали:
AD>так вот я в цикле создаю 8тысяч раз объект класса foo и засовываю это в лист. AD>и все это занимает около 50-80 секунд — просто очень долго, но если закоментить инициализацию в конструкторе то время на исполнение уходит 3-10 секунд, что вполне терпимо.
Как тебе удалось получить такие мегатормоза???
Глянь тут: Re: C++ и производительность
Здравствуйте, Alex Dav, Вы писали:
AD>Есть какие-нибудь идеи куда смотреть, что менять? (про архитектуру пока не надо ) AD>Спасибо.
Чем компиляется и с какими флагами? Если это DEBUG-сборка в Visual Studio или -O0 в GCC, вполне предсказуемый результат. Ещё см вот этот псто
Здравствуйте, Alex Dav, Вы писали: AD>но если закоментить инициализацию в конструкторе то время на исполнение уходит 3-10 секунд, что вполне терпимо.
Вообще-то и без инициализации нетерпимо.
10 секунд на 8000 объектов, засовываемых в список, это слишком много
и без специальных телодвижений труднодостижимо
Без доступа к коду, опциях компилятора и других деталей сложно что-то сказать определенное.
А что, средствами профилирования уже никто не пользуется ?
Подключите профайлер да узнайте, кто именно "виновник", и все вопросы снимутся.
Может, у Вас запись в list синхронизируется каким-нибудь медленным глобальным
объектом ядра типа mutex или для одиночной вставки используется insert, а не push_back ?
Кстати, структуру класса можно оптимизировать для более быстрой инициализации.
Например, задействовать механизм отложенного вычисления — все строковые данные-члены
вынести в отдельный класс, а в исходном классе хранить только указатель него,
инициализирующийся при первом запросе.
Здравствуйте, Анатолий Широков, Вы писали:
АШ>Из явного:
АШ>1. лишний вызов конструктора по умолчанию для всех членов типа string в конструкторе foo:
Оптимизатор заинлайнит, переварит и даже не рыгнет.
АШ>2. Если "test" это некоторого рода константа, то желательно ее оформить как таковую. Поскольку, присваивая c-строку string-у, конструктор делает лишний проход для вычисления длины null-terminated строки.
VS2008 (хз насчет GCC) заменяет strlen("константа") на константу.
P.S. Тут уже полфорума пыталось воспроизвести проблему, у всех получается минимум в 1000 раз быстрее. Аффтар что-то напутал.
Меня другое несколько удивило, что автор поста даже не принял участие в теме, которая его якобы волнует. Так что, гадание на кофейной гуще предлагаю прекратить за неимением предмета обсуждения.
Здравствуйте, Анатолий Широков, Вы писали:
АШ>Меня другое несколько удивило, что автор поста даже не принял участие в теме, которая его якобы волнует. Так что, гадание на кофейной гуще предлагаю прекратить за неимением предмета обсуждения.
Точно.
Может он эти строки для инициализации по сетке для каждого объекта качает.
Может он на каждый экземпляр мегабайты логов создает.
Ну и лист может какой-нибудь самописный или вообще GUI'вый.
Способов затормозить программу бесконечно много
Здравствуйте, Alex Dav, Вы писали:
AD>Есть какие-нибудь идеи куда смотреть, что менять? (про архитектуру пока не надо )
Поскольку не очень понятно, что там за список, предлагаю увеличить кол-во объектов в два раза и посмотреть, во сколько раз увеличится время выполнения. Очень может быть, что выявится O(n^2). Далее пристально смотреть в код вставки в список и на то, как именно элементы лежат в списке (видимо, полные копии).
Здравствуйте, Alex Dav, Вы писали:
AD>так вот я в цикле создаю 8тысяч раз объект класса foo и засовываю это в лист.
Вполне правильно тормозит. В многопоточном CRT каждое выделение и освобождение памяти сопровождается блокировкой. И вот ты создаешь временные объекты, запихиваешь в лист по значению, т.е. создаются копии, а исходные объекты удаляются. Попробуй запихать в лист по указателю или сделать свой allocator для std::string. Еще как вариант танца с бубном — попробуй сделать метод swap для своего объекта (т.е. для всех членов), запихивай в лист элементы, созданные "пустым" конструктором, а затем запихнутому элементу делай swap с инициализированным. Уберешь примерно 2/3 от общей задержки.
Здравствуйте, Alex Dav, Вы писали:
AD>клиент пожаловался, что работа кода на одном участке очень медленная, стал разбираться и обнаружил AD>что есть некий класс в кострукторе которого происходит инициализация внутренних членов, что то типа так:
А можно поподробнее про инициализацию? Что-то нереально звучит как-то: 80 секунд на 8000 объектов, это, грубо говоря, 10 миллисекунд на итерацию, состоящую из, примерно двух десятков new/delete, тогда как средним по психдому можно считать 1 микросекунду на new/delete. Так что, за это время (10 миллисекунд) "десяток империй сгорит и рухнет во мрак".
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
А у тебя экземпляры этого класса нигде в set (или в map в качестве ключа) не вставляются?
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!