Как обнаружить и оценить фрагментацию "кучи" в моей программе C++?

Предполагая, что вы говорите об элементе управления WPG Toolkit DataGrid, вам нужно только установить свойство CanUserSortColumns в значение true, а затем установить свойство SortMemberPath каждого DataGridColumn в DataGrid.

Что касается первоначальной сортировки коллекции, вы должны использовать CollectionViewSource и установить для нее сортировку, а затем назначить ее в качестве ItemsSource вашей DataGrid. Если вы делаете это в XAML, то это будет так просто:


    
        
           
        
    





ПРИМЕЧАНИЕ: префикс пространства имен «scm» сопоставляется с System.ComponentModel, где живет класс SortDescription.

xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"

РЕДАКТИРОВАТЬ: Я думаю, что достаточное количество людей получило помощь от этого поста, что этот голосующий комментарий должен быть включен в этот ответ:

Я должен был использовать это, чтобы получить его работа:


8
задан sharptooth 19 October 2009 в 14:16
поделиться

5 ответов

Я согласен с Тобиасом - создание собственного диспетчера памяти - отличный способ сделать это. Я знаю только нескольких разработчиков, которым я бы доверил написать такой код ...

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

Другая возможность - время от времени выполнять свою собственную сборку / консолидацию мусора для ваших объектов - при низких нагрузках ... то есть ваша служба может быть неактивна какое-то время, пока она "дефрагментирует" используемую память, но я Я не уверен, что вы можете гарантировать желаемое поведение без собственного управления памятью.

Другая возможность - время от времени выполнять свою собственную сборку / консолидацию мусора для ваших объектов - при низких нагрузках ... то есть ваша служба может быть неактивна какое-то время, пока она "дефрагментирует" используемую память, но я Я не уверен, что вы можете гарантировать желаемое поведение без собственного управления памятью.

0
ответ дан 5 December 2019 в 15:24
поделиться

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

Легче реализовать стратегию - выделить блоки памяти разных размеров и дождаться сбоя - но я не думаю, что это хороший способ. Как бы то ни было - чем больше был размер блока, чтобы он не вышел из строя, тем меньше фрагментация. Но в зависимости от диспетчера памяти выделение блока может изменить результат.


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

http://de.wikipedia.org/wiki/Slab_allocator ( версия babelfish )

http://www.usenix.org/event/usenix01/full_papers/bonwick/bonwick.pdf

2
ответ дан 5 December 2019 в 15:24
поделиться

Switchin on the Low fragmentation heap for Windows can help doing the job on older systems. в новых системах он включен по умолчанию (Vista, Server 2008)

  HANDLE heaps[1025];
  DWORD nheaps = GetProcessHeaps((sizeof(heaps) / sizeof(HANDLE)) - 1, heaps);
  for (DWORD i = 0; i < nheaps; ++i) {
    ULONG  enableLFH = 2;
    HeapSetInformation(heaps[i], HeapCompatibilityInformation, &enableLFH, sizeof(enableLFH));
  }

Существует инструмент VMMap от sysinternals (теперь Microsoft), который дает хороший обзор фрагментации памяти.

2
ответ дан 5 December 2019 в 15:24
поделиться

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

Так как это служба NT, Моделирование месяцев использования в основном состоит из выполнения множества запросов в спешке. Скорее всего, вы сможете делать запросы быстрее, чем обычно ожидается их получение, поэтому вы, вероятно, сможете смоделировать запросы на несколько месяцев всего за несколько часов, а вполне возможно, даже меньше (в зависимости от скорости, с которой вы обычно ожидаете получать запросы.

Как только вы смоделируете многомесячную работу (или даже пока вы это делаете), вам нужно посмотреть на кучу, чтобы увидеть, насколько сильно вы фрагментируете. Это непросто, но обычно возможно. Вы начнете с внедрения потока в процесс обслуживания (поиск в Google по «внедрению потока» или чему-то в этом порядке должен дать достаточно информации). Затем вам нужно будет пройтись по куче, ища (в частности) свободные блоки, но слишком мал, чтобы удовлетворить большинство запросов. Предполагая, что вы используете MS VC ++, вы проходите кучу с помощью _heapwalk, и он проходит через кучу, сообщая вам адрес, размер и статус (свободный или используемый) каждого блока в куче.

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

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

И последняя деталь: для того, чтобы это произвело значимое В результате как исполняемый файл, так и DLL, содержащая ваш внедренный поток, должны быть связаны с библиотекой времени выполнения в DLL. Это означает, что для всего процесса будет одна куча, поэтому ваш внедренный поток будет обходить кучу, используемую вашим сервисом. Если вы свяжете стандартную библиотеку статически, у каждой DLL и службы будет своя куча. DLL будет проходить свою собственную кучу, которая ничего не скажет вам о куче, используемой служебным процессом.

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

И последняя деталь: для того, чтобы это произвело значимое В результате как исполняемый файл, так и DLL, содержащая ваш внедренный поток, должны быть связаны с библиотекой времени выполнения в DLL. Это означает, что для всего процесса будет одна куча, поэтому ваш внедренный поток будет обходить кучу, используемую вашим сервисом. Если вы свяжете стандартную библиотеку статически, у каждой DLL и службы будет своя куча. DLL будет проходить свою собственную кучу, которая ничего не скажет вам о куче, используемой служебным процессом.

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

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

6
ответ дан 5 December 2019 в 15:24
поделиться

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

Сначала вы должны понять, что такое выделения, которые вы выполняете. Я думаю, что самый простой способ сделать это - переопределить операторы new и delete, и из этих новых операторов вы должны подсчитать некоторую статистику ваших выделений, а затем вызвать операторы new и delete по умолчанию вашего компилятора.

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

например блоки от 0 до 15 байтов, блоки от 16 до 32 байтов, блоки от 32 до 48 байтов, ...

Вы также можете добавить Число последовательного выделения каждого диапазона размеров блоков

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

Лучший и простой метод для выравнивания - использовать блоки со степенью 2

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

int align(int size)
{
    return ((size + 15) & ~0x0000000F);
}

Конечно, вы должны использовать свою статистику, чтобы выбрать лучшую степень 2 для согласования. Цель состоит в том, чтобы достичь числа, при котором большая часть вашего распределения будет разделена на несколько диапазонов блоков, и в то же время сохранить разумные накладные расходы на выравнивание.

Удачи ...

0
ответ дан 5 December 2019 в 15:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: