тема для размышления
От: alexeiz  
Дата: 01.04.11 06:13
Оценка: -2
Столкнулся недавно с интересной проблемой, которая себя очень странно проявляла, но в конце концов оказалась следствием ошибки алгоритмического характера.

Интересно было то, что как только обнаружилась причина проблемы, как все ее косвенные проявления сразу встали на свои места, а их объяснение стало абсолютно логичным.

Может быть будет интересно кому еще, поэтому выкладываю здесь.

Есть класс (C++), представляющий из себя коллекцию некоторых записей. Назовем его Rowset. Работал он долго, без каких-либо видимых проблем. Но в один прекрасный день кто-то заметил, что на платформе S этот Rowset отнимает необычно много памяти, когда количество записей достигает где-то сто тысяч. На других платформах, L (A и H), такого эффекта не наблюдалось. Стали экспериментировать, оказалось что если добавлять в Rowset записи по одной и их количество довести до пол-милиона/миллион, то на платформе S наш процесс с Rowset вылетает с ошибкой out-of-memory, достигая в памяти размера 4GB. На платформах L (A,H) вроде все с памятью нормально. Но только там при большом количестве записей, Rowset начинает как-то подозрительно медленно работать. Т.е. десятки тысяч записей добавляются за секунду-две, а сотни тысяч уже сотню секунд, несколько минут (при этом отнимая в памяти где-то около 100MB, т.е. не так много). Наоборот, на платформе S, какое-то непропорциональное разбухание в памяти, т.е. до определенного количество записей размер выделяемой памяти не сильно отличается от того, что наблюдается на платформах L (A,H), а потом он резко растет.

Поискали утечки памяти. Вроде все нормально, утечек нет. Да и потом, как так может быть, что утечки есть только на одной платформе, а на других этот же код выполняется без утечек?

Внимание, вопрос: в чем может быть проблема и как ее искать?
Re: тема для размышления
От: Сергей Мухин Россия  
Дата: 01.04.11 06:33
Оценка:
Здравствуйте, alexeiz, Вы писали:

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


такое поведение может быть при неверной hash функции
---
С уважением,
Сергей Мухин
Re[2]: тема для размышления
От: alexeiz  
Дата: 01.04.11 06:47
Оценка:
Здравствуйте, Сергей Мухин, Вы писали:

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


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


СМ>такое поведение может быть при неверной hash функции


Каким образом?
Re[3]: тема для размышления
От: Сергей Мухин Россия  
Дата: 01.04.11 06:50
Оценка:
Здравствуйте, alexeiz, Вы писали:

СМ>>такое поведение может быть при неверной hash функции


A>Каким образом?


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

сказали бы КАК организован этот ваш set
---
С уважением,
Сергей Мухин
Re: тема для размышления
От: jazzer Россия Skype: enerjazzer
Дата: 01.04.11 06:56
Оценка: :))
Здравствуйте, alexeiz, Вы писали:

A>Может быть будет интересно кому еще, поэтому выкладываю здесь.

Данетка?

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

А какой контейнер в коллекции?
Так навскидку похоже на поведение хэш-таблицы — в одном случае (когда кончается память) происходит слишком широкое перераспределение, а в другом (с тормозами) его не происходит, но в корзинке образуется много коллизий и поиск внутри корзинки начинает тормозить. По идее, это и является критерием для перераспределения, непонятно, почему его не происходит, особенно если хэш-функция одна и та же и реализация таблицы (т.е. параметры, управляющие перераспределением) тоже одна и та же. Но если и то, и другое разное на разных платформах, это может быть причиной.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[2]: тема для размышления
От: Сергей Мухин Россия  
Дата: 01.04.11 07:00
Оценка:
Здравствуйте, jazzer, Вы писали:

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


да, про ошибку в перераспределение я и забыл. но ее вероятность меньше, а так же сложней сделать эту часть платформозависимой. а хэш ф-ия легко — например используются адреса объектов, а они могут иметь какие-то быить всегда 0 (или 1) на конкр платфо.
---
С уважением,
Сергей Мухин
Re: тема для размышления
От: valaar  
Дата: 01.04.11 07:03
Оценка:
Здравствуйте, alexeiz, Вы писали:

A>Поискали утечки памяти. Вроде все нормально, утечек нет. Да и потом, как так может быть, что утечки есть только на одной платформе, а на других этот же код выполняется без утечек?


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


Как недавно были убедился, но отсутствие утечек памяти не говорит, что с памятью всё в порядке. Была ситуация, когда всё работает отлично, НО при завершении работы, когда идёт всеобщая чистка, примерно в одном случае из пяти вываливалось предупреждение о записи в уже освобождённую ранее память кучи, при этом стек мог указывать на любое место от деструкторов std коллекций до вызова функции с cdcdcdcd данными. Для повышения вероятности появления ошибки поток данных надо было довести до нескольких сотен тысяч записей. Так как это была не утечка, которую можно поймать простым макросом по перегрузке new, то после безуспешных поисков в Интернете просто переписал new и delete на свои функции, которые при инициализации просто выделяют огромный кусок памяти (простой массив), а при каждом обращении берут очередной элемент и отдают его, протоколируя в какой момент какие участки памяти были выделены и освобождены (повторного использования памяти не было). С первого же раза отладчик поймал нужную функцию. Причина оказалась в том, что у меня были два класса А и Б, при этом для А выделялись куски при первичном обращении, а Б это постоянные new и delete. Думал, и всё время ошибки оказывались рядом с классом Б, поэтому его new и delete и перегрузил, а проблема была в классе А, где я два раза умудрялся вызвать delete.

Поэтому если проблема с памятью, то надо постараться просто отследить какие куски кода выделяются/освобождаются и вывести в лог файл, кто запросил и почему. В любом случае, ошибка должна быть в программе, хотя постоянно и хочется верить в чудеса.
Re[2]: тема для размышления
От: Сергей Мухин Россия  
Дата: 01.04.11 07:08
Оценка:
Здравствуйте, valaar, Вы писали:

и еще. На одной и windows системе (давно было наверно это был windowsNT4, а мб еще раньше) было замечено очень плохое поведение кучи, когда число аллокаций приближается к миллиону. Очень медленно работало. Пришлось написать свою кучу. Но в след windows версии — все работало быстро.
---
С уважением,
Сергей Мухин
Re: тема для размышления
От: Mr.Delphist  
Дата: 01.04.11 14:18
Оценка:
Здравствуйте, alexeiz, Вы писали:

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


А не используется ли каких временных сущностей? Например, преобразование в DOM-модель и обратно, с целью верификации? Или ведение лога обработанных сущностей? Или какой-то статистической таблицы — тоже можно весьма шустро (и нелинейно) нарастить аппетиты по памяти с ростом объема данных.
Re[2]: тема для размышления
От: alexeiz  
Дата: 01.04.11 16:47
Оценка:
Здравствуйте, jazzer, Вы писали:

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


A>>Может быть будет интересно кому еще, поэтому выкладываю здесь.

J>Данетка?

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

J>А какой контейнер в коллекции?
J>Так навскидку похоже на поведение хэш-таблицы — в одном случае (когда кончается память) происходит слишком широкое перераспределение, а в другом (с тормозами) его не происходит, но в корзинке образуется много коллизий и поиск внутри корзинки начинает тормозить. По идее, это и является критерием для перераспределения, непонятно, почему его не происходит, особенно если хэш-функция одна и та же и реализация таблицы (т.е. параметры, управляющие перераспределением) тоже одна и та же. Но если и то, и другое разное на разных платформах, это может быть причиной.

Код выполняется абсолютно один и тот же на всех платформах. Если бы на одной было перераспределение, то и на других оно бы было тоже.

Rowset не использует хэш-таблицы. Там ничего сложнее векторов нет. Правда код там запутанный. Сразу идти и анализировать код с надеждой наткнуться на причину было бы бесполезно.
Re[2]: тема для размышления
От: alexeiz  
Дата: 01.04.11 16:52
Оценка:
Здравствуйте, valaar, Вы писали:

V>Как недавно были убедился, но отсутствие утечек памяти не говорит, что с памятью всё в порядке. Была ситуация, когда всё работает отлично, НО при завершении работы, когда идёт всеобщая чистка, примерно в одном случае из пяти вываливалось предупреждение о записи в уже освобождённую ранее память кучи, при этом стек мог указывать на любое место от деструкторов std коллекций до вызова функции с cdcdcdcd данными. Для повышения вероятности появления ошибки поток данных надо было довести до нескольких сотен тысяч записей.


Прострелов по памяти не оказалось. На платформе S, заменили malloc/free на slab аллокатор с отладочными опциями. Ни утечек, ни прострелов. Однако, эффект out-of-memory пропал...
Re[3]: тема для размышления
От: alpha21264 СССР  
Дата: 01.04.11 17:25
Оценка:
Здравствуйте, alexeiz, Вы писали:

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


V>>Как недавно были убедился, но отсутствие утечек памяти не говорит, что с памятью всё в порядке. Была ситуация, когда всё работает отлично, НО при завершении работы, когда идёт всеобщая чистка, примерно в одном случае из пяти вываливалось предупреждение о записи в уже освобождённую ранее память кучи, при этом стек мог указывать на любое место от деструкторов std коллекций до вызова функции с cdcdcdcd данными. Для повышения вероятности появления ошибки поток данных надо было довести до нескольких сотен тысяч записей.


A>Прострелов по памяти не оказалось. На платформе S, заменили malloc/free на slab аллокатор с отладочными опциями. Ни утечек, ни прострелов. Однако, эффект out-of-memory пропал...


Фрагментацию памяти смотрели?
Только не спрашивайте как
Что за платформа хоть? если Linux то там valgrind есть.
Я бы еще с версиями STL поигрался бы. Бывают всякие эффекты.

Течёт вода Кубань-реки куда велят большевики.
Re[2]: тема для размышления
От: Sheridan Россия  
Дата: 01.04.11 18:30
Оценка:
Приветствую, valaar, вы писали:

v> , где я два раза умудрялся вызвать delete.

Полезно всетаки после delete указатель в NULL сбрасывать.
avalon 1.0rc3 rev 306, zlib 1.2.3 (17.12.2009 01:06:14 MSK +03:00)(Qt 4.6.0)
Matrix has you...
Re[3]: тема для размышления
От: alexeiz  
Дата: 01.04.11 18:43
Оценка: 1 (1) +6
Здравствуйте, Sheridan, Вы писали:

S>Приветствую, valaar, вы писали:


v>> , где я два раза умудрялся вызвать delete.

S>Полезно всетаки после delete указатель в NULL сбрасывать.

Так делают те "админы", у кого утечки памяти и двойное удаление — постоянная головная боль, которую они пытаются уменьшить с помощью таких "полезных" приемов. Ирония в том, что после сбрасывания указателя в NULL, его повторное (и ошибочное) удаление пройдёт абсолютно незамеченным, тем самым закапывая баг в программе, который приводит к этому двойному удалению, еще глубже.
Re[4]: тема для размышления
От: Sheridan Россия  
Дата: 01.04.11 21:50
Оценка:
Приветствую, alexeiz, вы писали:

a> Так делают те "админы", у кого утечки памяти и двойное удаление — постоянная головная боль, которую они пытаются уменьшить с помощью таких "полезных" приемов. Ирония в том, что после сбрасывания указателя в NULL, его повторное (и ошибочное) удаление пройдёт абсолютно незамеченным, тем самым закапывая баг в программе, который приводит к этому двойному удалению, еще глубже.


Ооо, ды ты еще и ясновидец.
avalon 1.0rc3 rev 306, zlib 1.2.3 (17.12.2009 01:06:14 MSK +03:00)(Qt 4.6.0)
Matrix has you...
Re[3]: тема для размышления
От: Сергей Мухин Россия  
Дата: 02.04.11 04:01
Оценка:
Здравствуйте, alexeiz, Вы писали:

A>Код выполняется абсолютно один и тот же на всех платформах.


ну и что, это не делает его платформо независимым.

A>Rowset не использует хэш-таблицы. Там ничего сложнее векторов нет.

A>Правда код там запутанный. Сразу идти и анализировать код с надеждой наткнуться на причину было бы бесполезно.

т.е. свой код мы не смотрим, а сразу просим разобраться RSDN!

при этам ведем себя как партизан. Ни как устроен Rowset, ни что за платформы...
---
С уважением,
Сергей Мухин
Re[4]: тема для размышления
От: valaar  
Дата: 02.04.11 05:37
Оценка:
Здравствуйте, Сергей Мухин, Вы писали:


A>>Rowset не использует хэш-таблицы. Там ничего сложнее векторов нет.

A>>Правда код там запутанный. Сразу идти и анализировать код с надеждой наткнуться на причину было бы бесполезно.

СМ>т.е. свой код мы не смотрим, а сразу просим разобраться RSDN!


СМ>при этам ведем себя как партизан. Ни как устроен Rowset, ни что за платформы...


в первом сообщении автор же написал "Столкнулся недавно с интересной проблемой, которая себя очень странно проявляла, но в конце концов оказалась следствием ошибки алгоритмического характера."
то есть ошибка уже найдена и устранена, но предлагает подумать и предложить версии, что могло быть причиной
Re[5]: тема для размышления
От: Сергей Мухин Россия  
Дата: 02.04.11 05:50
Оценка:
Здравствуйте, valaar, Вы писали:

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

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

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

т.е. если помочь человеку или нельзя или поздно (раз сам решил). Жаль время.
---
С уважением,
Сергей Мухин
Re: тема для размышления
От: frogkiller Россия  
Дата: 02.04.11 15:31
Оценка:
Здравствуйте, alexeiz, Вы писали:

A>Поискали утечки памяти. Вроде все нормально, утечек нет. Да и потом, как так может быть, что утечки есть только на одной платформе, а на других этот же код выполняется без утечек?


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


MALLOC_OPTIONS=KK ?
Курица — это инструмент, с помощью которого одно яйцо производит другие.
Re: тема для размышления
От: minorlogic Украина  
Дата: 02.04.11 16:22
Оценка:
Тогда и вы скажите , что лежит у меня в кармане ?

Другими словами о чем тут думать если нет вводной даже о используемом контейнере ?
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.