Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2004.04.18;
Скачать: [xml.tar.bz2];

Вниз

Надо созда 2000 объектов TShape. Как ускорить?   Найти похожие ветки 

 
KSergey ©   (2004-03-26 12:04) [0]

Надо создать порядка 2..3 тысяч объектов TShape.
Но создаются они весьма долго, как оказалось (P-3, 700, win2k = 6 сек)
Потом отрисовка формы идет быстро, а во собственно момент создания - весьма долог...

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

Есть ли тут какие-то нюансы, или так и дожно быть?

Код создания:

procedure TForm1.Button1Click(Sender: TObject);
var x, y: integer;
begin
 DisableAutoRange;

 x := 10;
 while x < 870 do
 begin

   y := Button1.BoundsRect.Bottom + 10;
   while y < 850 do
   begin
     with TShape.Create(Self) do
     begin
       Name := EmptyStr;
       Parent := Self;
       BoundsRect := Rect(x, y, x+10, y+10);
       Brush.Color := RGB(x, y, x MOD y);
       Visible := TRUE;
     end;
     Inc(y, 20);
   end;  // while y < 850 do

   Inc(x, 20);
 end;

 EnableAutoRange;
end;


Ну в самом коде как таковом, по-моему, ничего нет примечательного. Ну разве что выделенные строчки - да, они позволили увеличить скорость раза в 2..2,5 (выше время указано с их учетом)
Цвет задаю не важно какой, в принципе мало что меняется.


 
MetalFan ©   (2004-03-26 12:26) [1]

а зачем это все нужно? может есть более быстрый способ?


 
KSergey ©   (2004-03-26 12:47) [2]

Тогда расскажите какой...
Я же просил - это не обсуждать.

В принципе можно, конечно, все сделать иначе: настряпать собственных объектов, потом в OnPaint их отрисовывать. Да. НО! Есть желание потом отлавливать клик по этим объектам. А это значит, что надо будет по клику мыши определять какому объекту принадлежит эта область окна и диспетчеризировать клик ему.
Но ведь именно так и устроена VCL в части распределения кликов по компонентам не окнам. Так зачем делать свое?
Интересно, что долго идет именно создание!

Что еще интересного обнаружиилось: собственно создание самих объектов происходит практически мнгновенно

(например, код:

procedure TForm1.Button1Click(Sender: TObject);
var x, y: integer;
begin
DisableAutoRange;

x := 10;
while x < 870 do
begin

  y := Button1.BoundsRect.Bottom + 10;
  while y < 850 do
  begin
    with TShape.Create(Self) do
    begin
      Name := EmptyStr;
    end;
    Inc(y, 20);
  end;  // while y < 850 do

  Inc(x, 20);
end;

EnableAutoRange;
end;


Здесь все то же, и кол-во, вот только на форме они не размещаются)

Исследования Spy++ показали, что окну формы на каждый создаваемый (размещаемый) объект посылается через SendMessage WM_GETMINMAXINFO, WM_WINDOWPOSCHANGING. Есть подозрение, что именно в этом вся проблема.

Нельзя ли как-то форме запретить пересчитывать свои размеры пока идет наполнение ее элементами? (пересчет размеров формой - мое предположение; но что-то она явн оделает, раз вызовы оконной ф-ции идут (ей же самой?))


 
sniknik ©   (2004-03-26 12:51) [3]

попробуй с этим (можно скорее всего вместо твоего выделенного)
LockWindowUpdate(handle);
DisableAutoRange;

EnableAutoRange;
LockWindowUpdate(null);


 
MBo ©   (2004-03-26 12:52) [4]

>Давайте не будем обсуждать кому это надо,
А ты предусмотрителен ;)))
Но все равно скоро начнется ;)

убери Name и Visible.

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

Примерно столько же тратится на SetBounds - прорисовку (хотя она и отложенная для TGraphicControl).

Hide форму ;)


 
KSergey ©   (2004-03-26 14:03) [5]

> [3] sniknik ©   (26.03.04 12:51)
> LockWindowUpdate(handle);
> LockWindowUpdate(0);  ;)

Нет, это не возымело эффекта.

> [4] MBo ©   (26.03.04 12:52)
> >Давайте не будем обсуждать кому это надо,
> А ты предусмотрителен ;)))

Да знаю я этих... мастеров...

> убери Name и Visible.

Ну в принципе не изменилось.

> Много времени тратится на назначение Parent

Да вот это я и сам догадываюсь. Вероятно, VCL пересчитывает необходимые размеры WinControl и область скроллирования... Хотя мне пока не удалось наткнуться на эот код. Но кто-то же вызывает оконную ф-цию... Вероятно "непримерные" Width/Heigth пропустил...

> в список дочерних контролов по одному

Дык вот в этом, похоже, вся фигня... Если бы можно было сразу все (ну половину) накидать и потом все просчитать... Может кто знает как? Согласен на "хакерские" методы. ;)

> на SetBounds - прорисовку

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

О! Клево! Оказывается сначала SetBoundsRect, а потом - Parent. Это еще в 1,5 раз ускоряет создание ;)

> Hide форму ;)

Вроде делал - но наверное не так. Точно! Это здорово помогает...
Т.е. в принципе можно на OnCreate формы их создавать - форма как раз еще не видна.

PS
Была еще обнаружена одна особенность VCL: когда Shape создавались разноцветные - это здорово жрало ресурсы. Когда создал 10 тыс. (для пробы) - комп вообще помер... ;)
Если же одного цвета - то без проблем.
Думаю, это не совсем грамотно: по идее каждая кисть для закраски должна создаваться и освобождаться в WM_PAINT, но, видимо, в VCL все немного не так... Хотя, возможно, кажный раз создавать кисти было бы слишком накладно по времени - не знаю.


 
MBo ©   (2004-03-26 14:10) [6]

А теперь пересмотри все в корне - ну не стоит создавать тьму контролов. Расскажи задачу.


 
pasha_golub ©   (2004-03-26 14:22) [7]

MBo ©   (26.03.04 14:10) [6]
Тоже так думаю. Задачу нужно услышать.


 
int64   (2004-03-26 14:36) [8]

А задача, я думаю, приблизительно такая:
Показать лаймерам-недоучкам, что даже оптимизированное до последнего байта приложение по созданию 2000 объектов TShape - маразм высшей степени.


 
KSergey ©   (2004-03-26 14:36) [9]

> Расскажи задачу.

Хорошо. Расскажу ;)
Вот только, не думаю, ... А может зря? Может кто-то и правда что подскажет?... (сомневаюсь, честно)

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

Откуда цифра 2000.
Прикид такой (только погодите кричать и топать, дочитайте).
В газете 200 полос. На полосе примерно 200 макетов. Получаем примерно 40 000 элементов на всю газету. (это больше выше названной цифры, но позже о бъясню)
Начальник требует показать всю газету целиком. Пока мои увещевания о том, что в этом просто нет смысла ни к чему не приводят.

Виже следующие пути решения.

1.Продолжить увещевать, скоро думаю перейти к стучанию по башке.
2.Понятно, что показывать все - смысла нет. Чать элементов при мелком масштабе все равно будет не вида. Вот и не буду их показывать! ;)

Как я думаю решать задачу (есил все же делать через Shape, а не самопал).

На старте создать порядка 2 тыс. элементов, скрыть. (соразу создать, т.к. это весьма долго оказалось). Цифра получена исходя из разрешения мониторов и "нормального" размера объекта на экране, по которому можно попасть мышкой. Хотя, возножно, и недостаточна...

Итак, все визуальные объекты созданы. Теперь в зависимости от того какая часть в данный момент просматривается и в каком масштабе - какими-либо из созданных объектов отрисовываем то, что просматривается в данный момент.
Геморойно, факт. Уже и не знаю: не проще ли будет просто отрисовывать это все самому и обрабатывать клики...
Но пока еще надежда теплится...

Если у кого есть какие иные идеи - буду рад.


 
KSergey ©   (2004-03-26 14:38) [10]

>  [8] int64   (26.03.04 14:36)
> по созданию 2000 объектов TShape
> - маразм высшей степени.

Вы видите альтернативы? Какие?
Буду признателен.


 
int64   (2004-03-26 14:42) [11]


> Геморойно, факт. Уже и не знаю: не проще ли будет просто
> отрисовывать это все самому и обрабатывать клики...
> Но пока еще надежда теплится...

Оставьте надежды.


 
тихий вовочка ©   (2004-03-26 14:43) [12]

Грузишь один заранее состряпанный битмап с 2 тысячями регионами нарисованными(не знаю какие у тебя именно). А потом лови OnMouseUp и по координатам смотри на какой из регионов приходится щелчок. Чем тебе такой подход не нравится?


 
MBo ©   (2004-03-26 14:51) [13]

Так...
Все 200 страниц сразу - явно перебор.
Отображаем одну страницу (разворот), или, по максимуму, печатный лист, делаем перелистывание.
Для каждой страницы создаем список, хоть TList, содержащий структуры из Rect, цвета и ссылки на текст или др. информацию.
При отображении страницы рисуем список в битмап, затем его отображаем. При перетаскивании мышью меняем Rect, при переносе на другую страницу запись переносим в соответствующий список.


 
Romkin ©   (2004-03-26 14:54) [14]

ДА даже не битмап, просто отрисовывать через TCanvas.poligon по надобности (включив doubleBuffered), а когда Начальник ткнет мышкой в полигон - только тогда делать Shape и работать с ней. CorelDraw так работает, а для него такое количество шейпов - раз плюнуть.
Макет тогда просто хранится в массивах точек, ну и класс небольшой написать для прорисовки, шейпирования и тд


 
KSergey ©   (2004-03-26 14:59) [15]

Все же нет больше альтернативы.
Понятно.


 
TButton ©   (2004-03-26 15:16) [16]

сабж.
не маяться дурью и найти другой вариант реализации. если понадобилось 2-3 тысячи шейпов - пора расти над собой =)


 
KSergey ©   (2004-03-26 15:17) [17]

Почитал еще разок... Захотелось высказаться.

> [8] int64   (26.03.04 14:36)
> А задача, я думаю, приблизительно такая:
> Показать лаймерам-недоучкам, что даже оптимизированное до
> последнего байта приложение по созданию 2000 объектов TShape
> - маразм высшей степени.

Хотя оно так и получается по сути, но все же хотелось бы поспорить. И вот почему.
Что буду делать я при отрисовке "ручками": создам необходимое кол-во структур хранения информации об объектах и буду на основе это инфы в WM_PAINT рисовать квадратики. Возражений нет, надеюсь?

Что делают TShape, будучи потомками TGraphicControl: они хранят информацию о своих размерах и отрисовывают себя (те же квадритики) на DC парента по необходимости.

А теперь укажите мне 10 отличий.

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


 
KSergey ©   (2004-03-26 15:20) [18]

>  [16] TButton ©   (26.03.04 15:16)
> сабж.
> не маяться дурью и найти другой вариант реализации. если
> понадобилось 2-3 тысячи шейпов - пора расти над собой =)

Хорошо, отклонимся от темы.
Вы альтернативы еще не озвученные видите? А главное, я никак не пойму разницы между двумя озвученными вариантами, кроме того, что реализация TShape несколько не приспособлена к таким объемам. Да и идеология построения VCL в части графических контролов.


 
pasha_golub ©   (2004-03-26 15:20) [19]

KSergey ©   (26.03.04 14:59) [15]
Есть альтернатива. Толькj расскажиет мне, пожалуйста, какая у вас программа верстки. Если Corel Ventura 10, то поздравляю, я работаю над аналогичной задачей. :-) Решаю с помощью OLE Automation.

Если нет, то создание TShape, это все равно не решение.


 
TButton ©   (2004-03-26 15:24) [20]

>создание TShape, это все равно не решение
ППКС


 
KSergey ©   (2004-03-26 15:28) [21]

>  [19] pasha_golub ©   (26.03.04 15:20)
> Если нет, то создание TShape, это все равно не решение.

А если да - то решение? ;)

Вообще-то я не вижу разницы, какая программа верстки. Или это из любопытства? А может вообще скооперироваться, если есть желание? ;) Правда, подозреваю, структура данных будет разительно отличаться, что позволит использовать лишь самые общие наработки визуализации...

Верстка - в QuarkExpress.
Пробовал Addobe In Design (тоже через COM вроде бы) - но он не потянул наши объемы. Да и фич говорят в нем нет, которые для газеты характерны. Впрочем, в этом я не разбираюсь. ;)

(СОМ - это здорово, это все видно, надежно, пусть не быстро... А Quark - это ворованное XDK и почти год разбора поставляемых с ним примеров, экспериментов... Впрочем, к делу это не относится)

Впрочем самый задевающий меня вопрос, на который я не заню ответа, озвучен в > [17] KSergey ©   (26.03.04 15:17) (про 10)


 
pasha_golub ©   (2004-03-26 15:44) [22]

KSergey ©   (26.03.04 15:28) [21]
200 страниц это по вашему простенький редактор? Вы глубоко ошибаетесь. Даже если вы сделаете этот редактор, начальство навернет вам еще несколько фич. Уж поверте.

Расскажу вам как это реализовано у нас.

У нас 56 полос. В 4 раза меньше. Если писать с нуля (по вашему), то вешаться можно сразу, а выгоды не вижу абсолютно. У нас правда, базы по рекламе нет, а вся реклама лежит в одной директории и одним махом импортируется в публикацию. Все тоже самое, если у вас нету текста, можно решить в CorelDraw. Даже лучше в draw. Так вот если нужно чего-нить. ТО мой клиент подключается к программе верстки и пролистывает ее массив Objects, а у него тама и название, и размер, и кто, и откуда. А preview можно сделать лишь только средствами самой программы верстки, благо для этого они и пишутся. Извини за скомканное изложение, бегу.

Буду рад отзывам, можно по мылу.


 
int64   (2004-03-26 15:56) [23]

KSergey ©   (26.03.04 15:17) [17]

> Что буду делать я при отрисовке "ручками": создам необходимое
> кол-во структур хранения информации об объектах и буду на
> основе это инфы в WM_PAINT рисовать квадратики. Возражений
> нет, надеюсь?

Есть. Даже просто объекты для этих целей не рекомендую использовать. А тем более TControl.


 
KSergey ©   (2004-03-26 16:08) [24]

>  [23] int64   (26.03.04 15:56)

Не понял суть возражений.
Не использовать объекты?
А какая разница? Ширины, высоты, прочая сопутствующая инфа - боюсь, что по сравнению с этим накландые расходы на память для объекта беудут не так велики.
Опять же - в чем разница?

ну разве что опять столкнусь с реалиями жизни: после выделения памяти под массив из 1000 элементов и одиночного создания 1000 объектов, возможно ситуация в памяти будет неодинакова... Да, возможно реалии тут сильно отличаются от теории...

Или есть еще какие-то отличия?


 
sts ©   (2004-03-26 16:31) [25]

первоначальный код выполнялся 1400 мс
то, что ниже приведено выполняется 150мс (это явно не предел)

procedure TForm1.Button1Click(Sender: TObject);
var x, y: integer;
begin
PerfTimer.Time;
Panel1.Visible := false;
DisableAlign;
DisableAutoRange;

x := 10;
while x < 870 do
begin
  y := Button1.BoundsRect.Bottom + 10;
  while y < 850 do
  begin
    with TShape.Create(nil) do
    begin
//       Name := EmptyStr;
      BoundsRect := Rect(x, y, x+10, y+10);
      Brush.Color := RGB(x, y, x MOD y);
      Parent := Panel1;
//       Visible := true;
    end;
    Inc(y, 20);
  end;  // while y < 850 do

  Inc(x, 20);
end;
EnableAutoRange;
EnableAlign;
Panel1.Visible := true;
MessageDlg( IntToStr(PerfTimer.Difference)+PerfTimer.ResolutionSymbols, mtWarning, [mbOK], 0);
end;


 
int64   (2004-03-26 16:42) [26]

KSergey ©   (26.03.04 16:08) [24]

Что такое, напимер, VTM? Знаете? Это ещё и к вопросу о памяти.
Если не собираетесь вызывать методы из объекта, то зачем их держать.
Если собираетесь, то лучше вынести все операции в отдельный другой объект. Который и будет управлять рекордами.


 
KSergey ©   (2004-03-26 17:04) [27]

>  [25] sts ©   (26.03.04 16:31)
> DisableAlign;

Во! Наконец-то кто-то дело говорит, а не просто обычные ля-ля про консерваторию. (читай: делать надо не так)
Про то, что паретна - в последнюю очередь - ага, это я тоже почти сделал, только не довел до конца, что еще и после кисти.
Спасибо.

> (это явно не предел)

Очень заманчиво, вот только знать бы как к нему приблизиться, к этому пределу ;)

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

Теперь немного о грустном.
Вы это делали на панели, попробовал - да, на ней действительно раза в 2-3 быстрее. На потомках TScrollingWinControl (форма, например) получается не в пример дольше.

> with TShape.Create(nil) do

А вот тут я бы не согласился, ведь не только в скорости цель ;)
При таком подходе никто эти TShape не освободит.
Впрочем, присвоение здесь какого-либо компонента на скорость особо не влияет. Проверял. Или я вообще сделал TObjectList, в нем - Capacity на требуемое кол-во и туда добавляю ссылки. Ну да это детали.

Есть ли у кого еще какие Disable_что_нибудь в заначке? Или так и будем лишь ламеров по углам страшными клижками шугать? ;)


 
KSergey ©   (2004-03-26 17:10) [28]

>  [26] int64   (26.03.04 16:42)

Ну в принципе я, конечно, согласен. Все зависит лишь от соотношения между служебной памятью под объектом и размером своей информации.
Да и у TObject лишь деструктор виртуальный (из вызываемых!). Хотя кое что там есть, конечно...

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

В общем да, вариант конечно здравый, особенно учитывая предполагаемые объемы (хотя, конечно, уйдем от них). Спасибо. Шибко попытки "объектного мышления" иногда через чур переть начинают не в нужных местах. ;)


 
Anatoly Podgoretsky ©   (2004-03-26 19:31) [29]

KSergey ©   (26.03.04 14:36) [9]
Решение у увещеванием простое сделай чтобы отрисовывалось секунд 100 или более и при каждом чихе.


 
KSergey ©   (2004-03-26 20:26) [30]

> Anatoly Podgoretsky ©   (26.03.04 19:31) [29]

Тогда может встать вопрос о соответствии меня занимаемой скромной должности ;)


 
Romkin ©   (2004-03-26 21:29) [31]

Беее. Создание 1000 объектов, рисующих тожесамо, что и один объект - дурной тон :)
ТЕм более, если учитывать, какие это объекты. TShape - это не только ценный мех... тьфу, линия, это еще и куча внутренней работы каждого экземпляра.
И вместе с тем, отрисовка простого полигона на основе массива - достаточно рядовая операция. Есть же разница!


 
KSergey ©   (2004-03-27 14:39) [32]

Ладно, уболтали! ;)

Под завязку дополнительный вопросик, если можно. Но отдельной веткой.


 
Bear   (2004-03-27 16:06) [33]

KSergey - не заморачивайся с TShape, ибо это решение сильно притянуто за уши :) используй какой нибудь готовый векторный компонент для отображения макета.
А используя 2000 TShape, боюсь что может получится, что кроме твоей проги больше ничего не запустишь в системе т.к. не будет свободных ресурсов


 
Veon ©   (2004-03-27 22:05) [34]

Помоему 2000!! Объектов в Delphi ях.... ух как это долго работать, в любом случае!!! Даже с применением супер оптимизации!! Просто тебе надо нарисовать 2000 прямогольников, создай массив и просто смотри куда тукнули мышкой, просматривая массив.
 Динамический массив.
 + ограничение, чтоб не рисовать прямоугольники с 0 площадью
 Заставить винду общаться с твоими 2000 Shape"ами с их Parent"ами, и кучей ненужных тебе свойств.... перегиб



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2004.04.18;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.57 MB
Время: 0.048 c
8-1072626254
tchn
2003-12-28 18:44
2004.04.18
странное дело с рисованием...


7-1076416013
aleman
2004-02-10 15:26
2004.04.18
Как из программы отключить сеть?


4-1076447378
Олег
2004-02-11 00:09
2004.04.18
Запуск программы от разных пользователей.


14-1080113981
ИМХО
2004-03-24 10:39
2004.04.18
Еще одна задачка для шахматистов


1-1080397559
TGrigory
2004-03-27 17:25
2004.04.18
Как сделать приподнимающуюся кнопку при наведении на нее мышой





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский