Ускорение графического вывода
От: Gregory Россия ICQ 300403361
Дата: 17.03.03 21:22
Оценка:
А не знает-ли кто, господа, как оптимизировать графический вывод в View. А то скролинг страшный как война с Иракаом.
Если на прямую выводить, то мигает как аварийная сигнализация, а если сначала в память а потом BitBit, то тормозит страшно. Если бы вот как в Excel...И как им это удается?
Не дай своим глазам увидеть, а ушам услышать то, что ты не сможешь объяснить.
Абрахам ван Хелсинг
Re: Ускорение графического вывода
От: TepMuHyc  
Дата: 17.03.03 21:51
Оценка:
Здравствуйте, Gregory, Вы писали:

G>А не знает-ли кто, господа, как оптимизировать графический вывод в View. А то скролинг страшный как война с Иракаом.

G>Если на прямую выводить, то мигает как аварийная сигнализация, а если сначала в память а потом BitBit, то тормозит страшно. Если бы вот как в Excel...И как им это удается?

Общая рекомендация — делать поменьше тупой работы.
А именно:
— При скроллинге как правило шлется куча сообщений — и далеко не при всех сообщениях надо вызывать перерисовку. Ты сначала вычисли положение сколлера, а потом посмотри, может оно совпадает с текущим — и только потом давай команду на перерисовку.
— Чтобы вызвать перерисовку вызывай InvalidateWindow и только. Не надо извращаться с RedrawWindow и прочей мутью.
— При перерисовке надо перерисовывать — и только. Если ты в процессе перерисовки ведешь какие-то более или менее трудоемкие расчеты, делай их где-нибудь в другом месте.
____________________
God obviously didn't debug, hasn't done any maintenance, and no documentation can be found. Truly amateur work.
Re[2]: Ускорение графического вывода
От: Gregory Россия ICQ 300403361
Дата: 18.03.03 08:24
Оценка:
Здравствуйте, TepMuHyc, Вы писали:

TMH>- При скроллинге как правило шлется куча сообщений — и далеко не при всех сообщениях надо вызывать перерисовку. Ты сначала вычисли положение сколлера, а потом посмотри, может оно совпадает с текущим — и только потом давай команду на перерисовку.

TMH>- Чтобы вызвать перерисовку вызывай InvalidateWindow и только. Не надо извращаться с RedrawWindow и прочей мутью.
TMH>- При перерисовке надо перерисовывать — и только. Если ты в процессе перерисовки ведешь какие-то более или менее трудоемкие расчеты, делай их где-нибудь в другом месте.

Все выше изложеное изначально было принято во внимание. Вконце скролинга(если действительно необходима перерисовка) вызывается
Invalidate(FALSE);
OnPaint();

Вычисления действительно производятся, но исключительно целочисленные и их не много. Дело в том, что тормозят, похоже, как-раз функции CDC.
Не дай своим глазам увидеть, а ушам услышать то, что ты не сможешь объяснить.
Абрахам ван Хелсинг
Re[3]: Ускорение графического вывода
От: Gregory Россия ICQ 300403361
Дата: 18.03.03 09:00
Оценка:
G>Вычисления действительно производятся, но исключительно целочисленные и их не много. Дело в том, что тормозят, похоже, как-раз функции CDC.

В подтверждение своих слов привожу результаты измерений:
Full time: 191 Paint time: 120
Full time: 332 Paint time: 182
Full time: 311 Paint time: 180
Full time: 321 Paint time: 211
Full time: 332 Paint time: 192
Full time: 331 Paint time: 200
Full time: 332 Paint time: 202
Full time: 341 Paint time: 181
Full time: 352 Paint time: 232
Full time: 332 Paint time: 242


Здесь "Full time" общее время выполнения функции OnPaint() в клоках, а "Paint time" время потраченое собственно на отрисовку, а имено — на вызов двух функций Rectangle и DrawText.
Не дай своим глазам увидеть, а ушам услышать то, что ты не сможешь объяснить.
Абрахам ван Хелсинг
Re[4]: Ускорение графического вывода
От: Denwer Россия  
Дата: 18.03.03 10:24
Оценка:
Здравствуйте, Gregory, Вы писали:

G>>Вычисления действительно производятся, но исключительно целочисленные и их не много. Дело в том, что тормозят, похоже, как-раз функции CDC.


G>В подтверждение своих слов привожу результаты измерений:

G>
G>Full time: 191 Paint time: 120
G>Full time: 332 Paint time: 182
G>Full time: 311 Paint time: 180
G>Full time: 321 Paint time: 211
G>Full time: 332 Paint time: 192
G>Full time: 331 Paint time: 200
G>Full time: 332 Paint time: 202
G>Full time: 341 Paint time: 181
G>Full time: 352 Paint time: 232
G>Full time: 332 Paint time: 242
G>


G>Здесь "Full time" общее время выполнения функции OnPaint() в клоках, а "Paint time" время потраченое собственно на отрисовку, а имено — на вызов двух функций Rectangle и DrawText.


Похожий вопрос как то поднимался. Поищи.
Совет: НЕ ИСПОЬЗУЙ DrawText
Вместо нее можно например взять ExtTextOut и доработать самому
Re[3]: Ускорение графического вывода
От: TepMuHyc  
Дата: 18.03.03 11:00
Оценка:
Здравствуйте, Gregory, Вы писали:

G>Вконце скролинга(если действительно необходима перерисовка) вызывается

Invalidate(FALSE);
OnPaint(); //<-- искоренить нафиг!!!!


По сути дела ты вызываешь:
— синхронную перерисовку через OnPaint();
— асинхронную перерисовку через Invalidate(FALSE);

Налицо никому не нужная работа.
____________________
God obviously didn't debug, hasn't done any maintenance, and no documentation can be found. Truly amateur work.
Re: Ускорение графического вывода
От: Всеволод Россия  
Дата: 18.03.03 11:03
Оценка: 6 (1)
Здравствуйте, Gregory, Вы писали:

G>А не знает-ли кто, господа, как оптимизировать графический вывод в View. А то скролинг страшный как война с Иракаом.

G>Если на прямую выводить, то мигает как аварийная сигнализация, а если сначала в память а потом BitBit, то тормозит страшно. Если бы вот как в Excel...И как им это удается?

А мигает, потому что сначала все окно закрашивается кистью с цветом фона, а уже потом происходит собственно вывод всего остального.
Что бы от этого избавиться есть два способа.
1) Перехватывать WM_ERASEBKGND и там ничего не делать.
2) При регистрации оконного класса установить параметр hbrBackground в NULL.
Re[2]: Ускорение графического вывода
От: Gregory Россия ICQ 300403361
Дата: 18.03.03 11:39
Оценка: 3 (1)
Здравствуйте, Всеволод, Вы писали:

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

В>Что бы от этого избавиться есть два способа.
В>1) Перехватывать WM_ERASEBKGND и там ничего не делать.

Перехватывается, и что-то делается при необходимости. Мигает из-за крайне медленой отрисовки.
Не дай своим глазам увидеть, а ушам услышать то, что ты не сможешь объяснить.
Абрахам ван Хелсинг
Re[4]: Ускорение графического вывода
От: Gregory Россия ICQ 300403361
Дата: 18.03.03 11:45
Оценка:
Здравствуйте, TepMuHyc, Вы писали:

TMH>OnPaint(); //<-- искоренить нафиг!!!!
TMH>


TMH>Налицо никому не нужная работа.


Согласен, ляпа. Искоренил, но скорости это ощутимо не добавило, т.к. после вызова Invalidate(FALSE); клиент окна становился валидным и OnPaint(); фактически ничего не делала.
Не дай своим глазам увидеть, а ушам услышать то, что ты не сможешь объяснить.
Абрахам ван Хелсинг
Re[4]: Ускорение графического вывода
От: Всеволод Россия  
Дата: 18.03.03 11:57
Оценка: 4 (1)
Здравствуйте, Gregory, Вы писали:

G>>Вычисления действительно производятся, но исключительно целочисленные и их не много. Дело в том, что тормозят, похоже, как-раз функции CDC.


G>В подтверждение своих слов привожу результаты измерений:

G>
G>Full time: 191 Paint time: 120
G>Full time: 332 Paint time: 182
G>Full time: 311 Paint time: 180
G>Full time: 321 Paint time: 211
G>Full time: 332 Paint time: 192
G>Full time: 331 Paint time: 200
G>Full time: 332 Paint time: 202
G>Full time: 341 Paint time: 181
G>Full time: 352 Paint time: 232
G>Full time: 332 Paint time: 242
G>


G>Здесь "Full time" общее время выполнения функции OnPaint() в клоках, а "Paint time" время потраченое собственно на отрисовку, а имено — на вызов двух функций Rectangle и DrawText.



Попробуй вместо того, что бы рисовать прямоугольники вызовом Rectangle, сначала сформировать координаты углов всех прямоугольников, а потом отрисовать их все за один раз вызвав PolyPolygon.
Re[2]: Ускорение графического вывода
От: Nikeware http://www.nikeware.com
Дата: 18.03.03 12:06
Оценка:
Здравствуйте, Всеволод, Вы писали:

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


В>Что бы от этого избавиться есть два способа.

В>1) Перехватывать WM_ERASEBKGND и там ничего не делать.
В>2) При регистрации оконного класса установить параметр hbrBackground в NULL.
Проходили мы все это. У меня другой прикол. На "дохлой" машине P3 400Mhz
"летает", а вот на 1,5Ghz строки во View при скроллинге как бы размазываются .
Кто бы мне все это объяснил? Упарился уже.

зы. требования 1 и 2 соблюдены

"To merge or not to merge?"
www.visual-comparer.com
Re[5]: Ускорение графического вывода
От: Gregory Россия ICQ 300403361
Дата: 18.03.03 12:09
Оценка:
Здравствуйте, Всеволод, Вы писали:

В>

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

Поясняю. Изображивается сетка(таблица) а-ля Excel. Каждая клетка может иметь собственные атрибуты (цвет фона, толщину рамки и т.п).
Поэтому PolyPolygon не прокатывает.
Не дай своим глазам увидеть, а ушам услышать то, что ты не сможешь объяснить.
Абрахам ван Хелсинг
Re[6]: Ускорение графического вывода
От: Всеволод Россия  
Дата: 18.03.03 12:20
Оценка:
Здравствуйте, Gregory, Вы писали:

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


В>>

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

G>Поясняю. Изображивается сетка(таблица) а-ля Excel. Каждая клетка может иметь собственные атрибуты (цвет фона, толщину рамки и т.п).

G>Поэтому PolyPolygon не прокатывает.

Может все-таки код покажешь ?
Re[7]: Ускорение графического вывода
От: Gregory Россия ICQ 300403361
Дата: 18.03.03 13:24
Оценка:
Здравствуйте, Всеволод, Вы писали:

В>Может все-таки код покажешь ?


void CGridView::OnPaint()
{
  CPaintDC dcPaint(this);
  int nSaveDC = dcPaint.SaveDC();
  CDC dcMem;
  dcMem.CreateCompatibleDC(&dcPaint);
  CRect ClientRect;
  GetClientRect(&ClientRect);
  CBitmap bitmap, *pBitmap;
  bitmap.CreateCompatibleBitmap(&dcPaint, ClientRect.right, ClientRect.bottom);
  pBitmap = dcMem.SelectObject(&bitmap);
  int nRows = GetRowCount();
  int nCols = GetColumnCount();
  CCellID CellID = m_BaseCell; // текущая левая верхняя клетка
  int x = 0,
      y = 0 ;
  for (; CellID.Row() < nRows && y <= ClientRect.bottom; CellID.Row()++) 
  {
    CellID.Col() = m_BaseCell.Col();
    x = 0;
    for (;CellID.Col() < nCols && x <= ClientRect.right; CellID.Col()++) 
    {
      CSize size;
      if (GetCellSize(CellID, size))
      {
        CELLINFO ci = m_DefCell;
        GetCellInfo(CellID, ci);
        CPen pen(PS_SOLID | PS_INSIDEFRAME, ci.brdWidth, ci.crBrdClr);
        CFont font;
        font.CreateFontIndirect(&ci.lfFont);
        dcMem.SelectObject(&pen);
        dcMem.SelectObject(&font);
        dcMem.SetTextColor(ci.crFgClr);
        dcMem.SetBkColor(ci.crBkClr);
        CRect rect(x, y, x + size.cx + 1, y + size.cy + 1);
        dcMem.Rectangle(&rect);
        rect.DeflateRect(ci.brdWidth, ci.brdWidth);
        dcMem.DrawText(ci.strText, &rect, ci.nFormat);
        font.DeleteObject();
      }
      x += m_waColWidth[CellID.Col()];
    }
    y += m_waRowHeight[CellID.Row()];
  }
  BOOL bErase = FALSE;
  if (ClientRect.right <= x)
    m_VisibleSize.cx = ClientRect.right;
  else if (x != m_VisibleSize.cx)
  {
    m_VisibleSize.cx = x;
    bErase = TRUE;
  }
  if (ClientRect.bottom <= y)
    m_VisibleSize.cy = ClientRect.bottom;
  else if (y != m_VisibleSize.cy)
  {
    m_VisibleSize.cy = y;
    bErase = TRUE;
  }
  dcPaint.BitBlt(0, 0, m_VisibleSize.cx, m_VisibleSize.cy, &dcMem, 0, 0, SRCCOPY);
  if (bErase)
    OnEraseBkgnd(&dcPaint);
  if (pBitmap)
    dcMem.SelectObject(pBitmap);
  dcMem.DeleteDC();
  dcPaint.RestoreDC(nSaveDC);
}
Не дай своим глазам увидеть, а ушам услышать то, что ты не сможешь объяснить.
Абрахам ван Хелсинг
Re[8]: Ускорение графического вывода
От: Всеволод Россия  
Дата: 18.03.03 13:37
Оценка:
Здравствуйте, Gregory, Вы писали:

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


В>>Может все-таки код покажешь ?


G>
G>void CGridView::OnPaint()
G>{
skipped
G>}

G>


Некоторые вещи приходят на ум...

1) Контекст памяти можно сделать один раз, не нужно его формировать при каждом вызове функции OnPaint.
Кстати сделать его можно и в другой функции.
2) То же самое касается и Bitmap. Сделай ее один раз максимально возможного размера.
Как мне понимается, максимальный размер окна может быть не больше текущего разрешения desktop'а.
Вот такого размера и должна быть bitmap.
3) Зачем ты делаешь SaveDC()/RestoreDC() ?
4) Поясни, пожалуйста, что у тебя там со стиранием происходит ?
Re[8]: Ускорение графического вывода
От: VVV Россия  
Дата: 18.03.03 13:46
Оценка: 11 (3)
Здравствуйте, Gregory, Вы писали:

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


В>>Может все-таки код покажешь ?


G>
G>void CGridView::OnPaint()
G>{
...
G>  CDC dcMem;
G>  dcMem.CreateCompatibleDC(&dcPaint);
G>  CRect ClientRect;
G>  GetClientRect(&ClientRect);
G>  CBitmap bitmap, *pBitmap;
G>  bitmap.CreateCompatibleBitmap(&dcPaint, ClientRect.right, ClientRect.bottom);
...
G>      if (GetCellSize(CellID, size))
G>      {
G>        CELLINFO ci = m_DefCell;
G>        GetCellInfo(CellID, ci);
G>        CPen pen(PS_SOLID | PS_INSIDEFRAME, ci.brdWidth, ci.crBrdClr);
G>        CFont font;
G>        font.CreateFontIndirect(&ci.lfFont);
...
G>        font.DeleteObject();
G>      }

G>  if (pBitmap)
G>    dcMem.SelectObject(pBitmap);
G>  dcMem.DeleteDC();
G>  dcPaint.RestoreDC(nSaveDC);
G>}
G>


Самая первая напрашиваемая оптимизация — сделать dcMem переменной CGridView и создать его только один раз — сразу при создании окна. То же самое с битмапом, но пересоздавать его по WM_SIZE с учётом нового размера клиентской области. И с фонтами и перьями можно сделать аналогично — сделать для них кэш — ведь, скорее всего, количество используемых фонтов намного меньше ячеек.
Re[9]: Ускорение графического вывода
От: Patalog Россия  
Дата: 18.03.03 13:47
Оценка:
Здравствуйте, Всеволод, Вы писали:

[]

В>1) Контекст памяти можно сделать один раз, не нужно его формировать при каждом вызове функции OnPaint.

В> Кстати сделать его можно и в другой функции.
В>2) То же самое касается и Bitmap. Сделай ее один раз максимально возможного размера.
В> Как мне понимается, максимальный размер окна может быть не больше текущего разрешения desktop'а.
В> Вот такого размера и должна быть bitmap.

+ то же самое насчет шрифтов
Почетный кавалер ордена Совка.
Re[10]: Ускорение графического вывода
От: Всеволод Россия  
Дата: 18.03.03 13:49
Оценка:
Здравствуйте, Patalog, Вы писали:

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


P>[]


В>>1) Контекст памяти можно сделать один раз, не нужно его формировать при каждом вызове функции OnPaint.

В>> Кстати сделать его можно и в другой функции.
В>>2) То же самое касается и Bitmap. Сделай ее один раз максимально возможного размера.
В>> Как мне понимается, максимальный размер окна может быть не больше текущего разрешения desktop'а.
В>> Вот такого размера и должна быть bitmap.

P>+ то же самое насчет шрифтов


А я так понял, что шрифт не фиксированный и у каждой ячейки он может быть свой.
Если количество используемых шрифтов ограничено, то тогда клнечно имеет смысл и их сформировать один раз и на всегда.
Re[9]: Ускорение графического вывода
От: Gregory Россия ICQ 300403361
Дата: 18.03.03 15:33
Оценка:
Здравствуйте, Всеволод, Вы писали:

В>1) Контекст памяти можно сделать один раз, не нужно его формировать при каждом вызове функции OnPaint.

В> Кстати сделать его можно и в другой функции.
В>2) То же самое касается и Bitmap. Сделай ее один раз максимально возможного размера.
В> Как мне понимается, максимальный размер окна может быть не больше текущего разрешения desktop'а.
В> Вот такого размера и должна быть bitmap.
Все это совершено верно, но если вернуться к моему посту с анализом времени выполенеия всей функции и отрисовки, то станет ясно, что клоков 10-20 на этом сэкономить можно, но кардинально это проблему не решит.
В>3) Зачем ты делаешь SaveDC()/RestoreDC() ?

Машков с Тихомировым попутали.

В>4) Поясни, пожалуйста, что у тебя там со стиранием происходит ?

Закрашивается незанятая сеткой часть клиента.
Не дай своим глазам увидеть, а ушам услышать то, что ты не сможешь объяснить.
Абрахам ван Хелсинг
Re[10]: Ускорение графического вывода
От: Gregory Россия ICQ 300403361
Дата: 18.03.03 15:55
Оценка:
Здравствуйте, Gregory, Вы писали:

G>Все это совершено верно, но если вернуться к моему посту с анализом времени выполенеия всей функции и отрисовки, то станет ясно, что клоков 10-20 на этом сэкономить можно, но кардинально это проблему не решит.


Проведенный эксперимент подтвердил истиность предыдущих строк.
Не дай своим глазам увидеть, а ушам услышать то, что ты не сможешь объяснить.
Абрахам ван Хелсинг
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.