Насколько дешево / дорого стоит память DC в Win API?

Я работаю над программой, которая будет иметь много растровых изображений DIB (созданных CreateDIBSection) и придется рисовать на них много текста, используя Win API.

Для рисования на растровом изображении Windows необходим контекст устройства, созданный CreateCompatibleDC,

А теперь вот два подхода:

  1. Я могу создать DC один раз для каждого растрового изображения, используя его для рисования и удаляя его при освобождении растрового изображения.

  2. Или я могу создать DC только тогда, когда мне нужно отрисовать растровое изображение, вызвать функции рисования и удалить DC.

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

Но не слишком ли дорого держать долгоживущий DC для каждого растрового изображения?

Edit1: Приложение на самом деле является библиотекой инструментария GUI, которая может использоваться в будущем непредсказуемым образом, поэтому мне нужно хорошо сбалансированное решение с максимально возможной производительностью и минимальным использованием системных ресурсов.

1

Решение

Объекты GDI ограничены как для процесса, так и для сеанса. Вы боретесь за ресурсы со всеми другими процессами, запущенными в том же сеансе. Имея это в виду, вы должны использовать ресурсы GDI только при необходимости (вариант 2 в вашем вопросе).

Запись в блоге Марка Руссиновича Расширение границ Windows: объекты USER и GDI — часть 2 входит в изрядное количество деталей. Чтобы подвести итог, вот список ограничений, которые оконный менеджер накладывает на ресурсы GDI:

  • 10.000 объектов GDI на процесс (значение по умолчанию, настраивается через раздел реестра) HKEY_LOCAL_MACHINE \ ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ \ Microsoft \ Windows NT \ CurrentVersion \ Windows \ GDIProcessHandleQuota).
  • 65,535 объектов GDI за сеанс пользователя.
  • Предел памяти объекта GDI является пределом выгружаемого пула (см. Расширение границ Windows: выгружаемый и невыгружаемый пул).
3

Другие решения

Вот тест, чтобы проверить, сколько времени потребуется, чтобы позвонить CreateCompatibleDC, Я считаю, что в среднем на каждый звонок уходит от 10 до 15 микросекунд. Это относительно быстро по сравнению с BitBltспециально для больших изображений. Поэтому нет особого преимущества в хранении памяти DC.

case WM_PAINT:
{
static HBITMAP hbitmap = (HBITMAP)LoadImage(0, L"path.bmp",
IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
std::wostringstream oss;

PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);

auto start = std::chrono::system_clock::now();
auto memdc = CreateCompatibleDC(hdc);
oss << L"CreateCompatibleDC: "<< (std::chrono::system_clock::now() - start).count() / 10 << "\n";

auto oldbitmap = SelectObject(memdc, hbitmap);

start = std::chrono::system_clock::now();
BitBlt(hdc, 0, 0, ps.rcPaint.right, ps.rcPaint.bottom, memdc, 0, 0, SRCCOPY);
oss << L"BitBlt: "<< (std::chrono::system_clock::now() - start).count() / 10 << "\n";

SelectObject(memdc, oldbitmap);
DeleteDC(memdc);

EndPaint(hwnd, &ps);

OutputDebugString(oss.str().c_str());
break;
}

Результат на Windows 10:

Результат для 24-битного 5 МБ растрового изображения:

CreateCompatibleDC: 17 микросекунд
BitBlt: 2500 микросекунд

Результат для 8bit 275kb:

CreateCompatibleDC: 12 микросекунд
BitBlt: 500 микросекунд

2

По вопросам рекламы [email protected]