помогите улучшить производительность
От: Alex Dav Россия  
Дата: 10.07.10 06:37
Оценка:
клиент пожаловался, что работа кода на одном участке очень медленная, стал разбираться и обнаружил
что есть некий класс в кострукторе которого происходит инициализация внутренних членов, что то типа так:

class foo
{
 public:
    foo(int x, int y)
    {
    m_x = x;
    m_y = y;
    m_s = "test";
    m_f = "test";
    m_o = "test";
    m_i = "test";
    m_r = "test";
    m_b = "test";
    m_a = "test";
     }

 private:
    int m_x;
    int m_y;
    string m_s;
    string m_f;
    string m_o;
    string m_i;
    string m_r;
    string m_b;
    string m_a;
}


так вот я в цикле создаю 8тысяч раз объект класса foo и засовываю это в лист.
и все это занимает около 50-80 секунд — просто очень долго, но если закоментить инициализацию в конструкторе то время на исполнение уходит 3-10 секунд, что вполне терпимо.

Есть какие-нибудь идеи куда смотреть, что менять? (про архитектуру пока не надо )
Спасибо.
Re: помогите улучшить производительность
От: Stanislav V. Zudin Россия  
Дата: 10.07.10 07:00
Оценка:
Здравствуйте, Alex Dav, Вы писали:

AD>так вот я в цикле создаю 8тысяч раз объект класса foo и засовываю это в лист.

AD>и все это занимает около 50-80 секунд — просто очень долго, но если закоментить инициализацию в конструкторе то время на исполнение уходит 3-10 секунд, что вполне терпимо.

AD>Есть какие-нибудь идеи куда смотреть, что менять? (про архитектуру пока не надо )


Ты же ничего не написал про использование этого класса. Строки меняются? Как часто?

Может помочь, к примеру, замена отдельных строк в классе на специальный контейнер "Коллекция строк", единый для всех экземпляров твоего класса.
Память в контейнере выделяется сразу под большое кол-во строк — снизится нагрузка на манагер памяти.
Детали его реализации зависят от способа использования строк — думай сам

Внутри foo, вместо строк будут храниться индексы на строки в контейнере.
_____________________
С уважением,
Stanislav V. Zudin
Re[2]: помогите улучшить производительность
От: Alex Dav Россия  
Дата: 10.07.10 07:05
Оценка:
Здравствуйте, Stanislav V. Zudin, Вы писали:

SVZ>Ты же ничего не написал про использование этого класса. Строки меняются? Как часто?

так проблем с использованием нет строки конечно разные для каждого экзэмрляра.
я просто пытаюсь понять как инициализация 10 переменных может так влиять на производительность, ведь даже если пустой конструктор выполняется — память для них выделяется.
Re: помогите улучшить производительность
От: Анатолий Широков СССР  
Дата: 10.07.10 07:12
Оценка: 1 (1)
Из явного:

1. лишний вызов конструктора по умолчанию для всех членов типа string в конструкторе foo:

 foo(int x, int y) 
/*  лишний вызов конструктора по умолчанию
    m_s(),
    m_f(),
    m_o(),
    m_i(),
    m_r(),
    m_b(),
    m_a()
*/
    {
    m_x = x;
    m_y = y;
    m_s = "test";
    m_f = "test";
    m_o = "test";
    m_i = "test";
    m_r = "test";
    m_b = "test";
    m_a = "test";
     }

2. Если "test" это некоторого рода константа, то желательно ее оформить как таковую. Поскольку, присваивая c-строку string-у, конструктор делает лишний проход для вычисления длины null-terminated строки.

Итого:

const string INITIAL = "test";

class foo
{
 public:
    foo(int x, int y) :
       m_x(x),
       m_y(y),
       m_s(INITIAL),
       m_f(INITIAL),
       m_o(INITIAL),
       m_i(INITIAL),
       m_r(INITIAL),
       m_b(INITIAL),
       m_a(INITIAL)
    {
    }

 private:
    int m_x;
    int m_y;
    string m_s;
    string m_f;
    string m_o;
    string m_i;
    string m_r;
    string m_b;
    string m_a;
}


Теперь из неявного. Если количество объектов заранее известно, то, предположительно, хранение в 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.

Удачи!
Re[2]: помогите улучшить производительность
От: Sni4ok  
Дата: 10.07.10 09:08
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:

АШ>Теперь из неявного. Если количество объектов заранее известно, то, предположительно, хранение в std::vector положительно скажется на


столько стараний, а автор явно указал что он в листе хранит)
Re[3]: помогите улучшить производительность
От: kpcb Россия  
Дата: 10.07.10 10:13
Оценка:
Здравствуйте, Alex Dav, Вы писали:

AD>я просто пытаюсь понять как инициализация 10 переменных может так влиять на производительность, ведь даже если пустой конструктор выполняется — память для них выделяется.


Скорее всего в конструкторе копирования std::string есть проверка на то — пустая строка или нет. Если да — то память под содержимое строки память не выделяется и ничего не копируется. (так для каждого временного объекта и копирования)
Re: помогите улучшить производительность
От: gegMOPO4  
Дата: 10.07.10 10:14
Оценка: 1 (1)
1. Убрать присваивания в конструкторе и сразу инициализировать члены.
    foo(int x, int y)
        m_x(x),
        m_y(y),
        m_s("test"),
        m_f("test"),
        ...
    {


2. Если указанные инициализирующие строки константы — лучше сразу вынести их в статические константные std::string.
static std::string const TEST("test");

Если передаются в конструктор как аргументы — передавать их по константной ссылке.
    foo(int x, int y, std::string const & s, std::string const & f, ...)


3. При добавлении в список избегать локального экземпляра foo, создавать сразу при вызове push_back.
    list.push_back(foo(3, 5));
Re: помогите улучшить производительность
От: CreatorCray  
Дата: 10.07.10 11:06
Оценка: 1 (1)
Здравствуйте, Alex Dav, Вы писали:

AD>так вот я в цикле создаю 8тысяч раз объект класса foo и засовываю это в лист.

AD>и все это занимает около 50-80 секунд — просто очень долго, но если закоментить инициализацию в конструкторе то время на исполнение уходит 3-10 секунд, что вполне терпимо.
Как тебе удалось получить такие мегатормоза???
Глянь тут: Re: C++ и производительность
Автор: CreatorCray
Дата: 10.07.10
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re: помогите улучшить производительность
От: пыщьх http://rsdn_user.livejournal.com
Дата: 10.07.10 11:12
Оценка: 1 (1)
Здравствуйте, Alex Dav, Вы писали:

AD>Есть какие-нибудь идеи куда смотреть, что менять? (про архитектуру пока не надо )

AD>Спасибо.
Чем компиляется и с какими флагами? Если это DEBUG-сборка в Visual Studio или -O0 в GCC, вполне предсказуемый результат. Ещё см вот этот псто
Автор: пыщьх
Дата: 10.07.10
.
Запретное обсуждение модерирования RSDN:
http://rsdn-user.livejournal.com/652.html
Re: помогите улучшить производительность
От: bkat  
Дата: 10.07.10 18:24
Оценка:
Здравствуйте, Alex Dav, Вы писали:
AD>но если закоментить инициализацию в конструкторе то время на исполнение уходит 3-10 секунд, что вполне терпимо.

Вообще-то и без инициализации нетерпимо.
10 секунд на 8000 объектов, засовываемых в список, это слишком много
и без специальных телодвижений труднодостижимо

Без доступа к коду, опциях компилятора и других деталей сложно что-то сказать определенное.
Re: помогите улучшить производительность
От: okman Беларусь https://searchinform.ru/
Дата: 10.07.10 18:59
Оценка:
Здравствуйте, Alex Dav.

А что, средствами профилирования уже никто не пользуется ?
Подключите профайлер да узнайте, кто именно "виновник", и все вопросы снимутся.
Может, у Вас запись в list синхронизируется каким-нибудь медленным глобальным
объектом ядра типа mutex или для одиночной вставки используется insert, а не push_back ?

Кстати, структуру класса можно оптимизировать для более быстрой инициализации.
Например, задействовать механизм отложенного вычисления — все строковые данные-члены
вынести в отдельный класс, а в исходном классе хранить только указатель него,
инициализирующийся при первом запросе.
Re[2]: помогите улучшить производительность
От: пыщьх http://rsdn_user.livejournal.com
Дата: 10.07.10 19:35
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:

АШ>Из явного:


АШ>1. лишний вызов конструктора по умолчанию для всех членов типа string в конструкторе foo:

Оптимизатор заинлайнит, переварит и даже не рыгнет.

АШ>2. Если "test" это некоторого рода константа, то желательно ее оформить как таковую. Поскольку, присваивая c-строку string-у, конструктор делает лишний проход для вычисления длины null-terminated строки.

VS2008 (хз насчет GCC) заменяет strlen("константа") на константу.

P.S. Тут уже полфорума пыталось воспроизвести проблему, у всех получается минимум в 1000 раз быстрее. Аффтар что-то напутал.
Запретное обсуждение модерирования RSDN:
http://rsdn-user.livejournal.com/652.html
Re[3]: помогите улучшить производительность
От: Анатолий Широков СССР  
Дата: 11.07.10 21:08
Оценка: 1 (1)
Меня другое несколько удивило, что автор поста даже не принял участие в теме, которая его якобы волнует. Так что, гадание на кофейной гуще предлагаю прекратить за неимением предмета обсуждения.
Re[4]: помогите улучшить производительность
От: bkat  
Дата: 11.07.10 21:36
Оценка: 1 (1)
Здравствуйте, Анатолий Широков, Вы писали:

АШ>Меня другое несколько удивило, что автор поста даже не принял участие в теме, которая его якобы волнует. Так что, гадание на кофейной гуще предлагаю прекратить за неимением предмета обсуждения.


Точно.
Может он эти строки для инициализации по сетке для каждого объекта качает.
Может он на каждый экземпляр мегабайты логов создает.
Ну и лист может какой-нибудь самописный или вообще GUI'вый.
Способов затормозить программу бесконечно много
Re: помогите улучшить производительность
От: minorlogic Украина  
Дата: 12.07.10 06:04
Оценка:
8000 раз за 80 секунд , можно отрендрить 3д сцену за отведенное время.
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re: помогите улучшить производительность
От: A.Lokotkov Россия  
Дата: 12.07.10 12:07
Оценка:
Здравствуйте, Alex Dav, Вы писали:

AD>Есть какие-нибудь идеи куда смотреть, что менять? (про архитектуру пока не надо )


Поскольку не очень понятно, что там за список, предлагаю увеличить кол-во объектов в два раза и посмотреть, во сколько раз увеличится время выполнения. Очень может быть, что выявится O(n^2). Далее пристально смотреть в код вставки в список и на то, как именно элементы лежат в списке (видимо, полные копии).
bloß it hudla
Re: топикстартер, АУ!
От: пыщьх http://rsdn_user.livejournal.com
Дата: 14.07.10 11:54
Оценка: :))) :))
Нашли причину тормозов-то? А то тут полфорума теперь бессонницей страдает и ваш паззл разгадывает...
Запретное обсуждение модерирования RSDN:
http://rsdn-user.livejournal.com/652.html
Re: помогите улучшить производительность
От: vdimas Россия  
Дата: 18.07.10 11:58
Оценка: 1 (1) -1
Здравствуйте, Alex Dav, Вы писали:

AD>так вот я в цикле создаю 8тысяч раз объект класса foo и засовываю это в лист.


Вполне правильно тормозит. В многопоточном CRT каждое выделение и освобождение памяти сопровождается блокировкой. И вот ты создаешь временные объекты, запихиваешь в лист по значению, т.е. создаются копии, а исходные объекты удаляются. Попробуй запихать в лист по указателю или сделать свой allocator для std::string. Еще как вариант танца с бубном — попробуй сделать метод swap для своего объекта (т.е. для всех членов), запихивай в лист элементы, созданные "пустым" конструктором, а затем запихнутому элементу делай swap с инициализированным. Уберешь примерно 2/3 от общей задержки.
Re: помогите улучшить производительность
От: Геннадий Васильев Россия http://www.livejournal.com/users/gesha_x
Дата: 18.07.10 16:48
Оценка:
Здравствуйте, Alex Dav, Вы писали:

AD>клиент пожаловался, что работа кода на одном участке очень медленная, стал разбираться и обнаружил

AD>что есть некий класс в кострукторе которого происходит инициализация внутренних членов, что то типа так:

А можно поподробнее про инициализацию? Что-то нереально звучит как-то: 80 секунд на 8000 объектов, это, грубо говоря, 10 миллисекунд на итерацию, состоящую из, примерно двух десятков new/delete, тогда как средним по психдому можно считать 1 микросекунду на new/delete. Так что, за это время (10 миллисекунд) "десяток империй сгорит и рухнет во мрак".
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
Re: Вопрос
От: Геннадий Васильев Россия http://www.livejournal.com/users/gesha_x
Дата: 18.07.10 17:09
Оценка:
Здравствуйте, Alex Dav, Вы писали:

А у тебя экземпляры этого класса нигде в set (или в map в качестве ключа) не вставляются?
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.