【问题标题】:How cheap/expensive is memory DC in Win API?Win API 中的内存 DC 有多便宜/多贵?
【发布时间】:2016-02-02 00:47:46
【问题描述】:

我正在开发一个程序,该程序将包含许多 DIB 位图(由 CreateDIBSection 创建),并且必须使用 Win API 在其上绘制大量文本。

为了在位图上绘图,Windows 需要由CreateCompatibleDC 创建的设备上下文。

现在有两种方法:

  1. 我可以为每个位图创建一次 DC,将其用于绘制并在释放位图时将其删除。

  2. 或者我可以只在需要绘制位图时创建DC,调用绘制函数并删除DC。

什么是更好的方法?我更喜欢第一个,因为调用次数更少 - 这将使我的代码更小,也更快。

但是为每个位图保存一个长寿命的 DC 是不是太贵了?

Edit1:该应用程序实际上是一个 GUI 工具包库,将来可以以不同且不可预知的方式使用,因此我需要一个平衡的决策,以尽可能提高性能和最少的系统资源使用。

【问题讨论】:

  • 通常的做法是调用“GetDC()”(或GetDCEx()),绘制,然后调用“ReleaseDC()”。
  • 我不需要在窗口上绘图,所以 GetDC 不是一个选项。 CreateCompatibleDC 是需要使用的。这是与窗口无关的内存 DC。
  • @selbie 嗯,也许你的意思是#2?而且我仍然不想知道问题的答案。
  • 糟糕——我就是这个意思!是的 #2!
  • @selbie - 所以,您的意见是内存设备上下文足够昂贵(内存、操作系统资源)以尝试以一堆 API 调用为代价来最小化内存中的实例:@987654325 @, 2xNxSelectObjectDeleteDC 在每次绘制操作(即使是更改的像素)上?

标签: c++ c winapi dib


【解决方案1】:

GDI objects 是有限的,无论是每个进程还是每个会话。您正在与在同一会话中运行的所有其他进程竞争资源。考虑到这一点,您应该仅在需要时使用 GDI 资源(您问题中的选项 2)。

Mark Russinovich 的博客条目Pushing the Limits of Windows: USER and GDI Objects – Part 2 进行了相当多的细节。总结要点,这里列出了窗口管理器对 GDI 资源的限制:

  • 每个进程 10.000 个 GDI 对象(默认值,可通过注册表项 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\GDIProcessHandleQuota 进行配置)。
  • 每个用户会话 65.535 个 GDI 对象。
  • GDI 对象内存限制是分页池限制(请参阅Pushing the Limits of Windows: Paged and Nonpaged Pool)。

【讨论】:

    【解决方案2】:

    这是一个测试调用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 上的结果:

    24bit 5MB 位图的结果:

    CreateCompatibleDC:17 微秒
    BitBlt:2500 微秒

    8bit 275kb 的结果:

    CreateCompatibleDC:12 微秒
    BitBlt:500 微秒

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-29
      • 2022-07-29
      • 1970-01-01
      • 1970-01-01
      • 2011-06-01
      • 2015-03-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多