Конференция "Базы" » AdoDb.RecordSet и занимаемая им память. [MSSQL]
 
  • Дмитрий Тимохов (18.03.11 19:46) [0]
    Добрый день.

    1. Сначала ситуация:
    У меня есть строка:
    RS := Cmd.Execute(...); // RS - это AdoDb.Recordset, а Cmd - это AdoDb.Command



    После выполнения строки занятая виртуальная память сразу увеличивается на 1 Гб.

    Я возвращаю 500000. Но это данные от силы на 50Мб, ну никак не 1Гб.

    Поразбиравшись я пришел к выводу, что 1 Гб - это как раз сумма значений DefinedSize каждого поля, каждой строки RS.

    Я был подумал, что неужели авторы AdoDb так устроили менеджмент памяти, что для типов переменной длины резервируют память по максимуму!!!! Не может быть, думаю. Начал делать тесты с другими запросами.

    В итоге я пришел к выводу, что в более простых случаях, когда полей не 20, а меньше Recordset хранит данные в памяти более оптимально даже при 500000 и более строк! Даже с полями varchar!

    Т.е. картинка такова - при каком-то количестве полей Recordset начинает хранить в памяти данные не оптимально!

    2. Теперь, что интересует.
    Не видел ли кто-то подобного поведения?
    Есть ли документальное объяснение подобному поведению?
    Может настройки у AdoDb есть какие?
  • Дмитрий Тимохов (18.03.11 20:02) [1]
    Это феномен какой-то

    Такой запрос дает 125Мб прироста (т.е. это 500000*255 байт)
    create table #t (Data varchar(255))
    insert #t select top 500000 cast(data as varchar(255)) from notea
    select * from #t



    Такой 12Мб прироста (т.е. реальные данные):
    create table #t (Data varchar(200))
    insert #t select top 500000 cast(data as varchar(200)) from notea
    select * from #t



    И такой дает те же 12Мб прироста:
    create table #t (Data varchar(400))
    insert #t select top 500000 cast(data as varchar(400)) from notea
    select * from #t



    Может кто-то объяснить сей феномен?
  • Дмитрий Тимохов (18.03.11 20:04) [2]
    Да, забыл сказать. В таблице notea Data - это varchar(7500)
  • Anatoly Podgoretsky © (18.03.11 20:35) [3]
    Ты неправильно считаешь размер для строк, он реально больше на 12/16 байт. А здесь все понятно, разный размер буфера, как решит система, для 255 решила выделить полный буфер, а в двух других случаях только по 10%
  • sniknik © (18.03.11 21:15) [4]
    > Может кто-то объяснить сей феномен?
    поменяй порядок "тестов",  и получишь другие результаты, скорее всего.
  • Loginov Dmitry © (18.03.11 22:38) [5]

    > Я был подумал, что неужели авторы AdoDb так устроили менеджмент
    > памяти, что для типов переменной длины резервируют память
    > по максимуму!!!! Не может быть, думаю. Начал делать тесты
    > с другими запросами.


    > 2. Теперь, что интересует.
    > Не видел ли кто-то подобного поведения?
    > Есть ли документальное объяснение подобному поведению?
    > Может настройки у AdoDb есть какие?


    Вообще-то это особенность любых компонентов, основанных на TDataSet, стандартный, так сказать, подход. Все строки таблицы в памяти должны быть одинаковой, фиксированной длины (можно больше, чем необходимо, но не меньше). См. реализацию TDataSet и его наследников.
    С другой стороны допускаю, что в наследниках такое поведение может меняться, но тут без дополнительного кода не обойтись, т.к. придется перекрывать многочисленные и уже реализованные в TDataSet virtual-методы.
  • Дмитрий Тимохов (19.03.11 22:43) [6]
    Anatoly Podgoretsky ©   (18.03.11 20:35) [3]
    Ты неправильно считаешь размер для строк, он реально больше на 12/16 байт. А здесь все понятно, разный размер буфера, как решит система, для 255 решила выделить полный буфер, а в двух других случаях только по 10%



    Ничего не понял. Я не знаю какой манагер памяти у AdoDb.Recordset.
    Вот интересно, почему она для 200 и 400 выделяет сколько нужно, а для 255 по полной.

    sniknik ©   (18.03.11 21:15) [4]
    Я на разных серверах посмотрел уже. Везде одинаковая картинка.
    Я еще с другими размерами поиграюсь. Возможно угляжу некую логику.

    Если у тебя есть сомнения в правильности тестов, могу прислать тестовый случай. Сам все увидишь.  


    > Loginov Dmitry ©   (18.03.11 22:38) [5]

    да здесь до компонента не доходит вообще.
    я напрямую с АДО работаю.
  • sniknik © (19.03.11 23:21) [7]
    присылай. а лучше выложи куда нибудь... мало ли, может еще кто захочет посмотреть/проверить.
  • Дмитрий Тимохов (20.03.11 00:42) [8]
    Ок. Только сначала соберу его с нуля, чтобы исключить влияние особенностей нашей БД (мало ли там настройки какие или еще что). Возможно, что в примере с нуля не будет такого эффекта.
  • Дмитрий Тимохов (21.03.11 12:52) [9]
    Начал я делать тесты на другой базе и другом сервере.

    Там другая картинка, но тоже не ясная вообще.

    Все в зависимости от длины varchar оказывается разный результат.
    При том, что обращение идет к одним и тем же данным.

    В общем я решил забить. Времени нет. Спишу на особенности (лажу) организации памяти AdoDb.
  • Игорь Шевченко © (21.03.11 13:44) [10]

    > Спишу на особенности (лажу) организации памяти AdoDb


    И почему ты смотришь на соринку, которая в глазу твоего брата, а бревна, которое в твоём собственном глазу, не замечаешь ? (Лк. 6, 41)
  • sniknik © (21.03.11 15:01) [11]
    > почему ты смотришь на соринку
    а почему в армию берут сильных, а спрашивают как с умных? ;)

    в смысле, применительно к ..., -   хотят чтобы работало быстро, а как "оптимизатор" какой так сразу внимание на размер используемой памяти.
    причем в процессе работы. (типа, еще аналогия, делаешь что то, все на столе под рукой разложено, и тут приходит "оптимизатор" и начинает - "а чего бардак? места на столе нет. почему сразу после использования вещи на место не убираешь? в ящичек, в сундучок, на замочек, и на полочку... в соседней комнате, ведь там его место.  ну и что, что  через минуту понадобится, оттуда и возьмешь... и будет полный стол свободного места."  ну типа того.)
  • Дмитрий Тимохов (21.03.11 17:32) [12]
    Почему такая увенность, что я лошок я не могу отличить ошибку не от ошибки?
    Не хочется рвать кое-что доказывая вам что-то...

    Вообще, может, соберусь, только не рвя, а спокойно и размеренно. В дела себе поставлю, т.к. с проблемой надо разбираться...
  • Игорь Шевченко © (21.03.11 19:05) [13]
    Дмитрий Тимохов   (21.03.11 17:32) [12]

    ADO существует давно, в Delphi тоже не вчера появилось. Была бы очевидная лажа, ее бы устранили. ADO тестируют миллионы мух и пишут багрепорты, если найдут лажу. Они не могут ошибаться :)
  • sniknik © (21.03.11 20:10) [14]
    > т.к. с проблемой надо разбираться...
    ну так разбирайся, а не списывай на ADO.

    > Почему такая увенность, что я лошок я не могу отличить ошибку не от ошибки?
    1 "cписывание" на лажу в популярном продукте, до поиска ошибок у себя.
    2 "наезд" на мелкософт.
    3 не понимание механизмов выделения памяти, отношение к памяти как линейной структуре с ожиданием что выделиться в "обрез", сколько надо, хотя так практически никто (даже банальный обжектлист) не делает.
    не говоришь как измерял, что указывает скорее всего на просмотр в таск менеждере о недопустимости чего уже наверное весь инет переполнен.
    4 > неужели авторы AdoDb
    не понимание что такое AdoDb... его авторы (дельфи) никакого отношения к "проблеме" и близко не имеют.
    5 > хранить в памяти данные не оптимально!
    исковерканные понятия об оптимальности. скорость доступа, или "экономия места", что важнее? оптимальнее? экономия места в процессе работы это как раз что то противоположное оптимальности.
    6 > Может настройки у AdoDb есть какие?
    преждевременные выводы, даже не узнав ничего(очень мало, не знаешь даже о настройках, очевидном) о продукте.
    7 не учитываешь возможного кеша/повторного использования уже выделенной первым запросом "лишней" памяти (иначе бы упомянул), дополнительных структур под индексы, рабочие данные (первым запросом они могут создаваться, после просто использоваться, и.т.к. ADO это COM обьект, то даже кратковременное отключение коннекта не гарантирует "сброса", наоборот, для более оптимальной работы ADO не разрушает объект какое то время. т.к. часто пере подключаются по старому "адресу", т.е. чтобы не делать лишних "телодвижений").

    хватит?
  • Дмитрий Тимохов (22.03.11 00:21) [15]
    sniknik ©   (21.03.11 20:10) [14]

    я соберусь потом все же представить свой тест-доказательства.
    вон, Игоря в арбитры возьмем (если, конечно, он захочет).

    по сути я могу сказать, что мне в общем все равно, как АДО зажрал виртуальную память - зарезервировал он ее, или реально выделил.
    факт в том, что в одном случае доступной виртуальной памяти остается 1Гб, в другом почти 2Гб. Т.е. в одном случае АДО честно резервирует под себя 1Гб виртуальной памяти.

    остаток памяти могу сказать как измерял. Возможно, это отчасти косвенный способ, но он оч. хорошо коррелирует с исходными предположениями о том, что зарезервированная виртуальная память под АДО в одном случае намного (на порядок) превышает другой случай. теперь как измерял:
    1. По Process Explorer - см. на зарезервированную виртуальную память.
    2. До и после загрузки Рекодсета с помощью штатного манагера памяти Дельфи загружал и освобождал по 1Мб память, пока не будет EOutOfMemory.
    Результаты коррелируются почти полностью - т.е. 1 + 2 примерно равно 2Гб, сколько и должно быть.

    при наличии времени обязательно посмотрю на результаты с помощью VirtualQuery (так вроде называется).    

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

    в общем, если тебе не интересно самому в данной странной особенности разбираться, то тест я сделаю, через недельку.

    предлагаю не переводить во взаимные наезды (я уже постирал, все что тебе ответил изначально). пообсуждаем предметно потом - поверь, в данном вопросе тебе будет, что подчерпнуть в знании особенностей АДОДБ.
  • Дмитрий Тимохов (22.03.11 00:43) [16]

    > Игорь Шевченко ©   (21.03.11 19:05) [13]
    >
    > Дмитрий Тимохов   (21.03.11 17:32) [12]
    >
    > ADO существует давно, в Delphi тоже не вчера появилось.
    > Была бы очевидная лажа, ее бы устранили. ADO тестируют миллионы
    > мух и пишут багрепорты, если найдут лажу. Они не могут ошибаться
    > :)


    Ситуация не настолько очевидна - я думаю, что на клиента мало кто гоняет 500000 строк. Может, просто не попадал никто ... Мне самому удивительно, почему так получается - но я адо уже 12 лет использую активно, и объемы гоняю часто большие, а только сейчас обнаружил такое поведение.  

    ждем моего примера.
  • sniknik © (22.03.11 00:44) [17]
    > вообще, сделай тест, аналогичный моему.
    > сам увидишь.
    сделал сразу, до того как писал [4]. не увидел.
  • Дмитрий Тимохов (22.03.11 09:31) [18]

    > сделал сразу, до того как писал [4]. не увидел.

    какая версия сервера, какая версия АДО?
    у меня дома тоже повторяется, правда конфигурация аналогиная - sqlserver 2000, adodb 2.8
  • sniknik © (22.03.11 10:12) [19]
    sqlserver 2000. остальное не помню, нужно смотреть. последние. XP со всеми апдейтами (стоит микрософт апдейт, который и за mssql следит).
 
Конференция "Базы" » AdoDb.RecordSet и занимаемая им память. [MSSQL]
Есть новые Нет новых   [134431   +15][b:0][p:0.002]