Re: тема для размышления
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 03.04.11 09:19
Оценка:
Здравствуйте, alexeiz, Вы писали:

A>Столкнулся недавно с интересной проблемой, которая себя очень странно проявляла, но в конце концов оказалась следствием ошибки алгоритмического характера.


A>Есть класс (C++), представляющий из себя коллекцию некоторых записей. Назовем его Rowset....


A>Внимание, вопрос: в чем может быть проблема и как ее искать?


"Дядя, а я знаю что у вас сломалось"

В программе, в чем же еще может быть проблема.

Я у себя (в страничном кэше с поддержкой многопоточного доступа) похожие тормоза искал с помощью тестов. Нашел линейней поиск в списке грязных страниц, переделал его на поиск через хеш — все стало "как у взрослых"

Искал очень долго ....
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[2]: тема для размышления
От: Сергей Мухин Россия  
Дата: 03.04.11 13:21
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>"Дядя, а я знаю что у вас сломалось"




КД>Я у себя (в страничном кэше с поддержкой многопоточного доступа) похожие тормоза искал с помощью тестов. Нашел линейней поиск в списке грязных страниц, переделал его на поиск через хеш — все стало "как у взрослых"


это не объясняет разное поведение на различных платформах.
---
С уважением,
Сергей Мухин
Re[6]: тема для размышления
От: valaar  
Дата: 04.04.11 08:35
Оценка:
Здравствуйте, Сергей Мухин, Вы писали:

СМ>Здравствуйте, valaar, Вы писали:


V>>в первом сообщении автор же написал "Столкнулся недавно с интересной проблемой, которая себя очень странно проявляла, но в конце концов оказалась следствием ошибки алгоритмического характера."

V>>то есть ошибка уже найдена и устранена, но предлагает подумать и предложить версии, что могло быть причиной

СМ>вы вообще понимаете, что нам НИЧЕГО не предложили. Как можно искать алгоритмическую ошибку не зная, даже примерно, алгоритма?

СМ>И как алгоритм может зависеть от платформы (хотя выбор алгоритма может)? Ошибка в реализации алгоритма.

СМ>т.е. если помочь человеку или нельзя или поздно (раз сам решил). Жаль время.


Во-первых, пока автор поступал честно. Надеюсь, что правильный ответ через некоторое время тоже сообщит.
Во-вторых, вопрос был не только "в чём может быть ошибка?", но и "как её искать?". Высказывайте свои версии и возможные инструменты, автор подсказывал как они будут себя вести. В чём-то похоже на текстовое adventure, где есть некоторое описание, а на возможные действия идёт различная реакция.
В-третьих, все уже обращали внимание, что "результат зависит от платформы". Хотя ошибка и была в алгоритме, но почему вела себя по-разному? Здесь алгоритм вообще можно рассматривать как чёрный ящик. Автор упомянул, что это коллекция, потому что без этого поведение по добавлению малого числа записей и большого было бы сложно описать. Бросаться сразу в отладчик и исходники можно, но это путь "грубой силы".

P.S. Всё это — моё личное мнение.
Re: тема для размышления
От: valaar  
Дата: 04.04.11 08:50
Оценка:
Здравствуйте, alexeiz, Вы писали:

A>Столкнулся недавно с интересной проблемой, которая себя очень странно проявляла, но в конце концов оказалась следствием ошибки алгоритмического характера.

...
A>Внимание, вопрос: в чем может быть проблема и как ее искать?

Верно ли что (просьба уточнить):
а) Исходный код на C++ для каждой из платформ (S, L, A, H) компилировался отдельно своим компилятором?
б) Среди платформ L, A, H была платформа той же разрядности, что и платформа S?
в) Специфика платформ не использовалась? (Например, IOCP под windows.)
г) Использовались ли какие-нибудь мультиплатформенные (например, boost) библиотеки, которые могли внутри себя использовать специфику платформ?
Re[3]: тема для размышления
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 04.04.11 09:17
Оценка:
Здравствуйте, Сергей Мухин, Вы писали:

КД>>Я у себя (в страничном кэше с поддержкой многопоточного доступа) похожие тормоза искал с помощью тестов. Нашел линейней поиск в списке грязных страниц, переделал его на поиск через хеш — все стало "как у взрослых"


СМ>это не объясняет разное поведение на различных платформах.


Ну, были еще (конкретные) проблемы с STL. Бинарник из под BCB5 летал (Rogue Wave STL?). А из под VS2005-2008 (думаю и с 2010 было бы тоже самое) — еле ползал. Особенно это было видно в многопоточной программе.

Проблема оказалась в std::locale.

Пусть поиграется с разными компиляторами/базовыми библиотеками. Может локализует причину

Один черт — нужны тесты, с демонстрацией стабильной деградации производительности.
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[2]: тема для размышления
От: gegMOPO4  
Дата: 04.04.11 10:25
Оценка:
Здравствуйте, minorlogic, Вы писали:
M>Тогда и вы скажите , что лежит у меня в кармане ?

Рука? Нож? Бечёвка или пус-с-сто?
Re[2]: тема для размышления
От: alexeiz  
Дата: 05.04.11 03:34
Оценка:
Здравствуйте, valaar, Вы писали:

V>Верно ли что (просьба уточнить):

V>а) Исходный код на C++ для каждой из платформ (S, L, A, H) компилировался отдельно своим компилятором?

На каждой — свой компилятор. S — Solaris/SunCC, L — Linux/GCC, A — AIX/xlC, H — HPUX/aCC.

V>б) Среди платформ L, A, H была платформа той же разрядности, что и платформа S?


Той-же.

V>в) Специфика платформ не использовалась? (Например, IOCP под windows.)


Нет.

V>г) Использовались ли какие-нибудь мультиплатформенные (например, boost) библиотеки, которые могли внутри себя использовать специфику платформ?


Нет. Конечно, у нас есть платформно зависимые библиотеки. Но можно точно сказать, что они там не были задействованы.
Re[2]: тема для размышления
От: alexeiz  
Дата: 05.04.11 03:36
Оценка:
Здравствуйте, minorlogic, Вы писали:

M>Тогда и вы скажите , что лежит у меня в кармане ?


M>Другими словами о чем тут думать если нет вводной даже о используемом контейнере ?


Об контейнерах, используемых в этом Rowset'е, я знал на тот момент не больше вашего
Re[6]: тема для размышления
От: alexeiz  
Дата: 05.04.11 03:38
Оценка:
Здравствуйте, Сергей Мухин, Вы писали:

СМ>вы вообще понимаете, что нам НИЧЕГО не предложили. Как можно искать алгоритмическую ошибку не зная, даже примерно, алгоритма?

СМ>И как алгоритм может зависеть от платформы (хотя выбор алгоритма может)? Ошибка в реализации алгоритма.

Алгоритм не зависит от платформы. Но ошибка в нем проявляется по разному на разных платформах. Вот так иногда бывает.
Re[4]: тема для размышления
От: alexeiz  
Дата: 05.04.11 04:08
Оценка:
Здравствуйте, alpha21264, Вы писали:

A>Фрагментацию памяти смотрели?

A>Только не спрашивайте как

Так как замена системного менеджера памяти перестает приводить к исчерпанию памяти, то это точно фрагментация. Осталось только найти из-за чего. Как здесь уже посоветовали, каждую аллокацию/деаллокацию записываем в лог. Большой лог получается, 150MB.

Но теперь мы уже не зависим от Rowset и его деталей реализации. Это важный момент. В коде Rowset можно было копаться долго и очень долго.

Проблему можно воспроизвести, проигрывая этот лог. Чем я и хотел заняться следующим делом. Но сначала я полез в него посмотреть, есть ли какой-нибудь цикличеки повторяющийся фрагмент. И он там сразу нашелся в самом начале лога. Около 30 аллокаций/деаллокаций — ничего серьезного. Было трудно поверить, что это и создает злодейскую фрагментацию памяти. Я уже начал писать простенький код, чтобы этот цикл прогонять энное количество раз. Но потом зачем-то полез в конец лога. И там обнаружилось...

alloc 399996
free 399992
... 30 alloc/free, что и в начале
alloc 400000
free 399996
... 30 alloc/free
и так далее

Ну, вот почти и все. Осталось только догадаться, чем в стандартной библиотеке можно создать такой pattern, и почему этот код очень сильно замедлялся на всех остальных платформах, где не наблюдалось фрагментации памяти.
Re[3]: тема для размышления
От: minorlogic Украина  
Дата: 05.04.11 06:56
Оценка:
Здравствуйте, alexeiz, Вы писали:

A>Здравствуйте, minorlogic, Вы писали:


M>>Тогда и вы скажите , что лежит у меня в кармане ?


M>>Другими словами о чем тут думать если нет вводной даже о используемом контейнере ?


A>Об контейнерах, используемых в этом Rowset'е, я знал на тот момент не больше вашего


Тогда откуда предположение что проблема в реализации Rowset?
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[5]: тема для размышления
От: gegMOPO4  
Дата: 05.04.11 07:38
Оценка: 12 (1)
Здравствуйте, alexeiz, Вы писали:
A>alloc 399996
A>free 399992
A>... 30 alloc/free, что и в начале
A>alloc 400000
A>free 399996
A>... 30 alloc/free
A>и так далее
A>Ну, вот почти и все. Осталось только догадаться, чем в стандартной библиотеке можно создать такой pattern, и почему этот код очень сильно замедлялся на всех остальных платформах, где не наблюдалось фрагментации памяти.

Была мысль о vector, который в обычно реализации может привести к троекратному перерасходу памяти. Но этого мало, да и не тормозило бы. А вот если в коде используется «оптимизация» (автор вероятно хотел «сэкономить» память), перед добавлением каждого элемента вызывается reserve(size()+1), то получим как раз указанное поведение. Мало того, что оно тормозит на любой платформе, постоянно переаллоцируя и копируя память, так ещё и на одних оно нагружает менеджер кучи дефрагментацией, а на других — валит с перерасходом фрагментированной неиспользуемой памяти.

Может и без reserve, а просто каждый раз создаётся новый вектор, ещё хуже. Может даже не вектор, а wstring.
Re[5]: тема для размышления
От: night beast СССР  
Дата: 05.04.11 07:38
Оценка:
Здравствуйте, alexeiz, Вы писали:

A>>Фрагментацию памяти смотрели?

A>>Только не спрашивайте как

A>Так как замена системного менеджера памяти перестает приводить к исчерпанию памяти, то это точно фрагментация. Осталось только найти из-за чего. Как здесь уже посоветовали, каждую аллокацию/деаллокацию записываем в лог. Большой лог получается, 150MB.


A>Но теперь мы уже не зависим от Rowset и его деталей реализации. Это важный момент. В коде Rowset можно было копаться долго и очень долго.


A>Проблему можно воспроизвести, проигрывая этот лог. Чем я и хотел заняться следующим делом. Но сначала я полез в него посмотреть, есть ли какой-нибудь цикличеки повторяющийся фрагмент. И он там сразу нашелся в самом начале лога. Около 30 аллокаций/деаллокаций — ничего серьезного. Было трудно поверить, что это и создает злодейскую фрагментацию памяти. Я уже начал писать простенький код, чтобы этот цикл прогонять энное количество раз. Но потом зачем-то полез в конец лога. И там обнаружилось...


с RVO никак не связано?
Re[6]: тема для размышления
От: alexeiz  
Дата: 18.04.11 00:10
Оценка:
Здравствуйте, gegMOPO4, Вы писали:

MOP>Была мысль о vector, который в обычно реализации может привести к троекратному перерасходу памяти. Но этого мало, да и не тормозило бы. А вот если в коде используется «оптимизация» (автор вероятно хотел «сэкономить» память), перед добавлением каждого элемента вызывается reserve(size()+1), то получим как раз указанное поведение. Мало того, что оно тормозит на любой платформе, постоянно переаллоцируя и копируя память, так ещё и на одних оно нагружает менеджер кучи дефрагментацией, а на других — валит с перерасходом фрагментированной неиспользуемой памяти.


Так и есть . Хотя, причина была не в желании съэкономить память, а в написании exception-safe кода, и reserve(size() + 1) был завуалирован в reserve(size() + numberOfRows), где numberOfRows всегда равнялось 1.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.