Есть ли причина, по которой GDI + будет работать медленнее в 64-битной операционной системе (или, может быть, это связано с Windows 7) - PullRequest
4 голосов
/ 22 июля 2011

Фон

Я работаю над приложением, которое должно работать на любой платформе Windows начиная с XP и далее одинаково.Через .NET Framework это было очень просто, по большей части.Приложение работает на различных сенсорных поверхностях.Приложение предназначено для .Net 3.0, но если по какой-то причине мне следует перейти на .Net 3.5, я могу это сделать.Я не могу использовать 4.0.

Приложение интенсивно использует GDI + через пространство имен System.Drawing.Теперь я понимаю, что GDI + либо вовсе не аппаратно ускоряется, либо ускоряется только в очень небольшом количестве видеокарт, поэтому я ожидаю проблем с производительностью.Однако эта проблема является явной и значительно снижает удобство использования приложения.Я бы не стал переписывать все приложение для DirectX или OpenGL, если этого можно избежать с помощью простого исправления.

Проблема

Мы недавно установили Windows 7 64-немного на одной из сенсорных таблиц.Это был первый раз, когда приложение запускалось на 64-битной машине с Windows 7.В любом случае, любой рисунок (в частности DrawLine) с более чем одним пальцем на устройстве одновременно вызывает смешную задержку.Эта задержка не очевидна в 32-битной Windows XP или 32-битной Windows 7, поэтому я думаю, что она может быть специфичной для 64-битной Windows 7 (у меня нет 64-битной машины XP для тестирования).

Приложение также было вынуждено запускаться как 32-разрядное приложение, поскольку один из файлов .dll имеет только 32-разрядные библиотеки, доступные для его компиляции.Я где-то читал, что принудительное включение процесса в 32-разрядный режим в 64-разрядной системе может вызвать проблемы с производительностью, но когда я обновил используемый нами SDK и создал 64-разрядный файл .dll и приложение, проблема не исчезла.

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

Итак, к чему это приведет: кто-нибудь из вас знает, почему может быть такая огромная разница в производительности между 32-битной Windows и 64-битной Windows?Если я не смогу найти решение, мне придется потратить немного времени на то, чтобы все рисовать с аппаратным ускорением.Я хотел бы избежать этого, если это вообще возможно.

Спасибо всем!

РЕДАКТИРОВАТЬ: Запрошенный фрагмент кода

    public delegate void drawLineDelegate(Color color, float width, int x1, int y1, int x2, int y2);
    public void drawLine(Color color, float width, int x1, int y1, int x2, int y2)
    {
        if (InvokeRequired)
        {
            Invoke(new drawLineDelegate(drawLine), new object[] { color, width, x1, y1, x2, y2 });
        }
        else
        {
            try
            {
                lock (drawLock)
                {
                    pen.Width = width;
                    pen.Color = color;
                    scaledPen.Width = width * this.Width / Canvas.Width;
                    scaledPen.Color = color;
                    Point p1 = scalePointToScreen(new Point(x1, y1));
                    Point p2 = scalePointToScreen(new Point(x2, y2));

                    graphics.DrawLine(pen, x1, y1, x2, y2);
                    scaledGraphics.DrawLine(scaledPen, p1.X, p1.Y, p2.X, p2.Y);

                    this.Invalidate(new Rectangle(Math.Min(p1.X, p2.X) - (int)scaledPen.Width, Math.Min(p1.Y, p2.Y) - (int)scaledPen.Width,
                          Math.Abs(p2.X - p1.X) + 2 * (int)scaledPen.Width, Math.Abs(p2.Y - p1.Y) + 2 * (int)scaledPen.Width));
                }
            }
            catch (Exception ex)
            {
                if (Scribbler.Properties.Settings.Default.LogLevel >= 2)
                {
                    Scribbler.ScribblerForm.WriteLogMessage(ex.ToString());
                }
            }
        }

Редактировать: Дальнейшие исследования Я провел еще несколько поисков в Интернете в отношении карт NVidia, которые мы используем на наших машинах.Это привело меня к нескольким постам на форумах разработчиков NVidia о людях с такой же проблемой.Распространенный ответ заключается в том, что GDI устарела в Windows 7, а более новые графические драйверы NVidia (начиная с 182.5) страдают от проблем с производительностью GDI.Решением было либо обновить Direct3D, либо использовать старые драйверы.Кто-нибудь знает наверняка, это лучший курс действий?

Ответы [ 2 ]

1 голос
/ 25 июля 2011

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

Вы не должны рисовать из нескольких потоков, если вы точно не знаете, что делаете. В ОС слишком много ошибок, связанных с использованием многопоточной графики.

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

Я думаю, что вы бы значительно выиграли от изменения вашего рабочего процесса рисования, чтобы он вызывался один раз и только из основного потока сообщений.

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

1 голос
/ 23 июля 2011

Прежде всего, я не уверен, что вы получите много преимуществ в производительности при использовании WPF.Если вы решите переписать свой графический код, я предлагаю перейти на Direct2D (вы все равно можете написать код на C #).Вот статья, сравнивающая производительность всех трех библиотек: http://www.teechart.net/reference/articles/WhitePaper_Direct2D.htm

Я разработчик Maperitive , который активно использует GDI + для рендеринга карт.Я не могу сказать, что заметил какие-либо серьезные проблемы с производительностью в 64-битной Windows 7, но опять же, я не тестирую ее на какой-либо другой системе (кроме Monu на Ubuntu на нетбуке, который по понятным причинам намного медленнее).

Полагаю, было бы легче обсудить это, если бы вы показали нам некоторые фрагменты кода рисования линий.С другой стороны, проблема может быть связана с аппаратным обеспечением (драйвер видеокарты?).На скольких различных 64-битных конфигурациях Win 7 вы это тестировали?

ОБНОВЛЕНИЕ:

О "устаревшем" GDI в Windows 7: я очень сомневаюсь, что это будет правдойпотому что тогда вы заметите проблемы с производительностью не только в своем приложении, и я сомневаюсь, что Microsoft будет достаточно смелой, чтобы сделать что-то подобное по причинам обратной совместимости.Есть ли у вас ссылки, подтверждающие это утверждение?

О вашем коде: вы не показали все это и его реальное назначение, но я подозреваю, что из контекста вы используете объект Graphics, созданный с помощью Control.CreateGraphics() метод (и вы вызываете рисование линий из других потоков, что само по себе может быть проблемой производительности).Я подозреваю, что вы делаете это для интерактивного рисования линий (вместо того, чтобы перерисовывать все с помощью метода OnPaint()).В общем, эта практика проблематична ( вот объяснение Боба Пауэлла ).

Кстати, в чем разница между graphics и scaledGraphics?

Если бы вы могли объяснить, чтоименно этим вы пытаетесь достичь, возможно, мы сможем найти лучший (более быстрый) способ сделать это.

...