Приходилось читать, в том числе и здесь, о том что .Net быстрее C++. В глубине души, да и по небольшому опыту работы с Java никогда в это не верил.
Однако недавно встала задачка. Сделать превьюшку картинок в папке на .Net. Просто демка типа лабы. Поэтому без изысков. Не проблема.
Пишу:
private void openToolStripMenuItem_Click(object sender, EventArgs e)
{
openFileDialog1.ShowDialog();
int index = 0;
// listView1.BeginUpdate();foreach ( string s in openFileDialog1.FileNames)
{
Image image = Image.FromFile(s);
Application.DoEvents();
imageList1.Images.Add(s, image);
listView1.Items.Add(s, index);
index++;
}
//listView1.EndUpdate();
}
Тормозит. Каталог в 299 jpg размеров 800MB загружает около 2х минут.
Проект собирался в релизной версии в VS2008 для .Net3.0.
Ладно. Делаю на Delphi:
procedure TfrmMain.Open1Click(Sender: TObject);
var
s: WideString;
src,dst: TBitmap;
j: TJPEGImage;
lItem: TListItem;
index, aWidth, aHeight : Integer;
begin
if OpenPictureDialog1.Execute then
begin
src := TBitmap.Create;
dst := TBitmap.Create;
j :=TJPEGImage.Create;
try
src.Dormant;
dst.Dormant;
// ListView1.Items.BeginUpdate;for s in OpenPictureDialog1.Files do
begin
j.LoadFromFile(s);
Application.ProcessMessages;
src.Assign(j);
ResizeImage(src, dst);
dst.SetSize(100, 100);
index := ImageList1.Add(dst, nil);
lItem := ListView1.Items.Add;
lItem.Caption := s;
lItem.ImageIndex := index;
end;//for s in OpenPictureDialog1.Files do
// ListView1.Items.EndUpdate;finally
j.Destroy;
j := nil;
dst.Destroy;
dst := nil;
src.Destroy;
src := nil;
end;
end;
end;
Тот же самый каталог загружает около 4-х минут.
Проект собирался в BDS 2006 со включенной оптимизацией.
Разница в быстродействии почти в 2 раза в пользу .Net....
Размер изображений в ImageList одинаков. 100 на 100.
Оба приложения исполнялись на одном и том же ноутбуке. OS WinXp SP2.
Я прифигел. Честно. Хотя проблема подозреваю в том, что .Net обрабатывает все через GDI+, a Delphi использует свои классы. И если delphi версию переписать через GDI+ то производительность по идее должна сравняться. Но пока некогда разбираться...
09.03.10 12:14: Перенесено модератором из 'Философия программирования' — Хитрик Денис
P.S. BE> Application.ProcessMessages; BE> Application.DoEvents();
Delphi-Style forever
BE> j.Destroy; BE> j := nil;
FreeAndNil(j) если вам не нужна обратная совместимость с Delphi 5(а может 3, не помню)и ниже
Здравствуйте, BlackEric, Вы писали:
BE>Я прифигел. Честно. Хотя проблема подозреваю в том, что .Net обрабатывает все через GDI+, a Delphi использует свои классы. И если delphi версию переписать через GDI+ то производительность по идее должна сравняться. Но пока некогда разбираться...
Одно время sun выпускала java-процессоры. Представь как взлетит скорость когда M$ выпустит .Net-процессор.
A>Одно время sun выпускала java-процессоры. Представь как взлетит скорость когда M$ выпустит .Net-процессор.
M$ врядли, но производители уже на эту тему задумываются
ЗЫ: А если задачку без изысков решить на WPF то загруска будет выполняться в реальном времени и клиент первую партию картинок получит уже через секунду после запуска, и при этом вполне без изысков можно засунуть это в вэб или настольное приложение.
Доброго времени суток! Мир Вам! С уважением Clevelus.
Если мой ответ понравился — оцените, ни на что не влияет, но будет приятно.
Здравствуйте, BlackEric, Вы писали:
BE> Я прифигел. Честно. Хотя проблема подозреваю в том, что .Net обрабатывает все через GDI+, a Delphi использует свои классы. И если delphi версию переписать через GDI+ то производительность по идее должна сравняться. Но пока некогда разбираться...
о скорости своего UTF-8 декодера. Так вот, после небольшого причесывания кода (без алгоритмических изменений) мой декодер дерет (на 200 мсек) системный MultiByteToWideChar (сперва он отставал на ~секунду). Могу ли я сделать на этом основании вывод о рулезности Delphi и соответственно сюксности С/C++?
о скорости своего UTF-8 декодера. Так вот, после небольшого причесывания кода (без алгоритмических изменений) мой декодер дерет (на 200 мсек) системный MultiByteToWideChar (сперва он отставал на ~секунду). Могу ли я сделать на этом основании вывод о рулезности Delphi и соответственно сюксности С/C++?
Относительно применимости к вашей задаче? Можете. Хотя бы потому, что желающих оплачивать переписывание стандартных библиотек обычно не находится.
И я сравниваю не Object Pascal с C#, а Delphi vs .Net. Т.е. в первую очередь библиотеки, а не языки и на конкретной задаче.
Здравствуйте, Clevelus, Вы писали:
C>ЗЫ: А если задачку без изысков решить на WPF то загруска будет выполняться в реальном времени и клиент первую партию картинок получит уже через секунду после запуска, и при этом вполне без изысков можно засунуть это в вэб или настольное приложение.
Здравствуйте, Nonmanual Worker, Вы писали:
NW>Здравствуйте, BlackEric, Вы писали:
NW>Некорректное сравнение.
NW>P.S. BE>> Application.ProcessMessages; BE>> Application.DoEvents(); NW> Delphi-Style forever
В данном случае допустимо, т.к. на общую производительность заметного влияния не оказывает. Нужно лишь чтобы программа не производила впечатление полностью повисшей.
В .Net я так понимаю хорошим тоном является вынесение подобных операций в отдельный поток?
BE>> j.Destroy; BE>> j := nil; NW>FreeAndNil(j) если вам не нужна обратная совместимость с Delphi 5(а может 3, не помню)и ниже
Нужно тянуть за собой SysUtils. Не всегда хорошо.
BE>Тормозит. Каталог в 299 jpg размеров 800MB загружает около 2х минут. BE>Проект собирался в релизной версии в VS2008 для .Net3.0.
BE>Ладно. Делаю на Delphi:
BE>
BE>
BE>Тот же самый каталог загружает около 4-х минут. BE>Проект собирался в BDS 2006 со включенной оптимизацией.
BE>Разница в быстродействии почти в 2 раза в пользу .Net....
BE>Размер изображений в ImageList одинаков. 100 на 100. BE>Оба приложения исполнялись на одном и том же ноутбуке. OS WinXp SP2.
BE>Я прифигел. Честно. Хотя проблема подозреваю в том, что .Net обрабатывает все через GDI+, a Delphi использует свои классы. И если delphi версию переписать через GDI+ то производительность по идее должна сравняться. Но пока некогда разбираться...
Я C# видел только на картинках, а Дельфи — последний раз 6 или 7 лет назад, но, по-моему, в дельфовом варианте у тебя происходит лишнее копирование (+ преобразование из jpg в bmp), так что она у тебя ещё и памяти в два раза должна больше кушать, не говоря уже про скорость. А если в результате программа и свопиться активно начнёт — то в два раза медленней — это не предел. Добавь ещё картинок в пару гигабайт — так и в 10 раз затормозишь в лёгкую.
Курица — это инструмент, с помощью которого одно яйцо производит другие.
Здравствуйте, BlackEric, Вы писали:
BE>В .Net я так понимаю хорошим тоном является вынесение подобных операций в отдельный поток?
Да. И не только в .Net.
Но это ИМХО касается "внешности" серьезных коммерческих приложений, ну и обычно приводит к веселой отладке приложений со сложным многооконным GUI.
BE>Нужно тянуть за собой SysUtils. Не всегда хорошо.
Не могу вспомнить\придумать случая когда это было бы не хорошо.
Буду благодарен если просвятите.
Здравствуйте, BlackEric, Вы писали:
BE>Приходилось читать, в том числе и здесь, о том что .Net быстрее C++. В глубине души, да и по небольшому опыту работы с Java никогда в это не верил.
[..]
Если открыть исходники VCL, например
function TCustomImageList.Add(Image, Mask: TBitmap): Integer;
var
ImageDDB, MaskDDB: TBitmap;
begin
ImageDDB := TBitmap.Create;
try
MaskDDB := TBitmap.Create;
try
HandleNeeded;
Result := ImageList_Add(FHandle, GetImageHandle(Image, ImageDDB),
GetImageHandle(Mask, MaskDDB));
finally
MaskDDB.Free;
end;
finally
ImageDDB.Free;
end;
Change;
end;
то видно что разработчики Delphi совершенно не рассчитывали на то что этот метод будет вставляться в длинный цикл. Если в этом действительно есть надобность, можно допилить TCustomImageList напильником за 5 минут и он будет добавлять изображения с той скоростью, с которой позволяет это делать WinAPI. И так далее, не следует думать что стандартные классы VCL обеспечат оптимальную производительность во всех случаях — исходники под рукой и всегда можно найти потенциальные источники тормозов.
---
The optimist proclaims that we live in the best of all possible worlds; and the pessimist fears this is true
W>то видно что разработчики Delphi совершенно не рассчитывали на то что этот метод будет вставляться в длинный цикл. Если в этом действительно есть надобность, можно допилить TCustomImageList напильником за 5 минут и он будет добавлять изображения с той скоростью, с которой позволяет это делать WinAPI. И так далее, не следует думать что стандартные классы VCL обеспечат оптимальную производительность во всех случаях — исходники под рукой и всегда можно найти потенциальные источники тормозов.
1. Из чего следует, что разработчики Delphi совершенно не рассчитывали на то что этот метод будет вставляться в длинный цикл?
2. Как вы предлагаете его допиливать? Вынести создание и соответственно удаление ImageDDB и MaskDDB в конструктор и деструктор TImageList?
Создать новый компонет? Или непосредственно редактировать исходники VCL?
3. Основные тормоза здесь не при добавлении в ImageList, а при конвертаци jpg to bmp (src.Assign(j); А избежать этой конвертации очень проблематично
Здравствуйте, Nonmanual Worker, Вы писали:
NW>Здравствуйте, BlackEric, Вы писали:
BE>>В .Net я так понимаю хорошим тоном является вынесение подобных операций в отдельный поток? NW>Да. И не только в .Net. NW>Но это ИМХО касается "внешности" серьезных коммерческих приложений, ну и обычно приводит к веселой отладке приложений со сложным многооконным GUI.
BE>>Нужно тянуть за собой SysUtils. Не всегда хорошо. NW>Не могу вспомнить\придумать случая когда это было бы не хорошо. NW>Буду благодарен если просвятите.
Ну практически в каждой фирме есть такое понятите как стандарты кодирования. А вот как и начем они основаны это уже хз.
Здравствуйте, BlackEric, Вы писали:
BE>Здравствуйте, Nonmanual Worker, Вы писали:
NW>>Здравствуйте, BlackEric, Вы писали:
BE>>>Нужно тянуть за собой SysUtils. Не всегда хорошо. NW>>Не могу вспомнить\придумать случая когда это было бы не хорошо. NW>>Буду благодарен если просвятите. BE>Ну практически в каждой фирме есть такое понятите как стандарты кодирования. А вот как и начем они основаны это уже хз.
А в практически каждой нормальной фирме для этих стандартов есть их хоть какое-то обоснование.
о скорости своего UTF-8 декодера. Так вот, после небольшого причесывания кода (без алгоритмических изменений) мой декодер дерет (на 200 мсек) системный MultiByteToWideChar (сперва он отставал на ~секунду). Могу ли я сделать на этом основании вывод о рулезности Delphi и соответственно сюксности С/C++?
BE>Относительно применимости к вашей задаче? Можете. Хотя бы потому, что желающих оплачивать переписывание стандартных библиотек обычно не находится.
Странная логика...
BE>И я сравниваю не Object Pascal с C#, а Delphi vs .Net. Т.е. в первую очередь библиотеки, а не языки и на конкретной задаче.
Не увидел сравнения библиотек Увидел попытку лобового решения. И кстати, уже с седьмой (кажется) версии язык называется именно Delphi, а не Object Pascal.
Здравствуйте, BlackEric, Вы писали:
NW>>Некорректное сравнение.
NW>>P.S. BE>>> Application.ProcessMessages; BE>>> Application.DoEvents(); NW>> Delphi-Style forever BE>В данном случае допустимо, т.к. на общую производительность заметного влияния не оказывает. Нужно лишь чтобы программа не производила впечатление полностью повисшей.
А она именно такое впечатление производить и будет. Попробуй в течении тех 4 минут нажать на кнопку закрытия окна. Кнопка нажимается? Нажимается. А вот окно закроется только после завершения цикла.
BE>В .Net я так понимаю хорошим тоном является вынесение подобных операций в отдельный поток?
Это везде хорошим тоном является.
BE>>> j.Destroy; BE>>> j := nil; NW>>FreeAndNil(j) если вам не нужна обратная совместимость с Delphi 5(а может 3, не помню)и ниже BE>Нужно тянуть за собой SysUtils. Не всегда хорошо.
Типа всякие Graphics, Forms и Controls его за собой не тащат
Здравствуйте, BlackEric, Вы писали:
BE>1. Из чего следует, что разработчики Delphi совершенно не рассчитывали на то что этот метод будет вставляться в длинный цикл?
Из того что этот метод содержит код, который при использовании в цикле следует вынести из цикла
BE>2. Как вы предлагаете его допиливать? Вынести создание и соответственно удаление ImageDDB и MaskDDB в конструктор и деструктор TImageList?
Зависит от конкретной задачи — как угодно.
BE> Создать новый компонет? Или непосредственно редактировать исходники VCL?
Редактировать исходники VCL не стоит. Всё остальное пожалуйста.
BE>3. Основные тормоза здесь не при добавлении в ImageList, а при конвертаци jpg to bmp (src.Assign(j); А избежать этой конвертации очень проблематично
А её по-любому надо делать, потому что виндовый ImageList работает только с битмапами и иконками. Если главный тормоз здесь, значит надо поискать более эффективный конвертор — в гугл не лазил, но думаю найти можно.
---
The optimist proclaims that we live in the best of all possible worlds; and the pessimist fears this is true
Здравствуйте, wallaby, Вы писали:
BE>>3. Основные тормоза здесь не при добавлении в ImageList, а при конвертаци jpg to bmp (src.Assign(j); А избежать этой конвертации очень проблематично W>А её по-любому надо делать, потому что виндовый ImageList работает только с битмапами и иконками. Если главный тормоз здесь, значит надо поискать более эффективный конвертор — в гугл не лазил, но думаю найти можно.
TJpegImage является наследником TGraphic, значит, он должен уметь напрямую рисоваться в прямоугольник заданного размера с помощью метода TCanvas.StretchDraw. Т.е. не преобразовывать в битмап, а рисовать на канве пустого битмапа.
Вообще, libjpeg, на которой основан TJpegImage, является каноническим решением. И такие базовые операции, как создание thumbnail-ов, повороты/обрезания без потерь, в ней должны быть еще со времен, когда .net и в проекте не было. Только может оказаться, что в Дельфи включена еще более древняя версия... Кроме того, едва ли TJpegImage поддерживает 100% возможностей libjpeg.
типа добавления переменной-флага в цикл для выхода из него. происходит какое-то специфичное событие типа закрытия окна — присваиваешь ей true и все ок. относительно конечно.
H>А она именно такое впечатление производить и будет. Попробуй в течении тех 4 минут нажать на кнопку закрытия окна. Кнопка нажимается? Нажимается. А вот окно закроется только после завершения цикла.
я вообще за ним практически никаких возможностей не замечал, скорее затычка для чтения файлов и записи с параметром quality. это чуть-ли не половина всех возможностей.
а вообще, ничего не мешает из Delphi GDI+ использовать для чистоты эксперимента.
SIG>Кроме того, едва ли TJpegImage поддерживает 100% возможностей libjpeg.