У меня относительно большая система (пока ~ 25000 строк) для мониторинга радиоустройств. Он показывает графики и тому подобное с использованием последней версии ZedGraph. Программа написана с использованием C # на VS2010 с Win7. Проблема в:
- когда я запускаю программу из VS, она работает медленно
- когда я запускаю программу из встроенного EXE, она работает медленно
- когда я запускаю программу через Performance Wizard / CPU Profiler, она запускается Blazing Fast.
- когда я запускаю программу из встроенного EXE, а затем запускаю VS и присоединяю профилировщик к ЛЮБОМУ ДРУГОМ ПРОЦЕССУ, моя программа ускоряется!
Я хочу, чтобы программа всегда работала так быстро!
Каждый проект в решении настроен на RELEASE, Отладка неуправляемого кода ОТКЛЮЧЕНА, Определить константы DEBUG и TRACE ОТКЛЮЧЕНА, Оптимизировать код - я пробовал либо, Уровень предупреждения - я пробовал либо, Подавить JIT - я пробовал, короче, я пробовал все решения, уже предложенные на StackOverflow - ни одно не сработало. Программа работает медленно вне профилировщика, быстро в профилировщике. Я не думаю, что проблема в моем коде, потому что он становится быстрее, если я присоединяю профилировщик к другому, несвязанному процессу!
Пожалуйста помоги! Мне действительно нужно, чтобы он везде работал так быстро, потому что это критически важное для бизнеса приложение, и проблемы с производительностью недопустимы ...
ОБНОВЛЕНИЯ 1–8 подписаны
-------------------- Обновление1: --------------------
Проблема, похоже, не связана с ZedGraph, потому что она все еще проявляется после того, как я заменил ZedGraph своим собственным базовым рисунком.
-------------------- Обновление 2: --------------------
При запуске программы на виртуальной машине программа по-прежнему работает медленно, а запуск профилировщика с хост-машины не делает его быстрым.
-------------------- Обновление 3: --------------------
Запуск захвата экрана в видео также ускоряет работу программы!
-------------------- Update4: --------------------
Если я открою окно настроек графического драйвера Intel (это: http://www.intel.com/support/graphics/sb/img/resolution_new.jpg) и просто постоянно наводите курсор на кнопки, чтобы они светились и т. д., моя программа ускоряется !. Однако он не ускоряется, если я запускаю GPUz или Kombustor, поэтому на GPU не разгоняется - он остается стабильным - 850 МГц.
-------------------- Обновление 5: --------------------
Тесты на разных машинах:
-На моем Core i5-2400S с Intel HD2000 пользовательский интерфейс работает медленно, а загрузка процессора составляет ~ 15%.
-На Core 2 Duo коллеги с Intel G41 Express пользовательский интерфейс работает быстро, но загрузка ЦП составляет ~ 90% (что тоже не нормально)
-На Core i5-2400S с выделенным Radeon X1650 пользовательский интерфейс работает молниеносно, загрузка процессора составляет ~ 50%.
-------------------- Update6: --------------------
Фрагмент кода, показывающий, как я обновляю один график (graphFFT
- это инкапсуляция ZedGraphControl
для простоты использования):
public void LoopDataRefresh() //executes in a new thread
{
while (true)
{
while (!d.Connected)
Thread.Sleep(1000);
if (IsDisposed)
return;
//... other graphs update here
if (signalNewFFT && PanelFFT.Visible)
{
signalNewFFT = false;
#region FFT
bool newRange = false;
if (graphFFT.MaxY != d.fftRangeYMax)
{
graphFFT.MaxY = d.fftRangeYMax;
newRange = true;
}
if (graphFFT.MinY != d.fftRangeYMin)
{
graphFFT.MinY = d.fftRangeYMin;
newRange = true;
}
List<PointF> points = new List<PointF>(2048);
int tempLength = 0;
short[] tempData = new short[2048];
int i = 0;
lock (d.fftDataLock)
{
tempLength = d.fftLength;
tempData = (short[])d.fftData.Clone();
}
foreach (short s in tempData)
points.Add(new PointF(i++, s));
graphFFT.SetLine("FFT", points);
if (newRange)
graphFFT.RefreshGraphComplete();
else if (PanelFFT.Visible)
graphFFT.RefreshGraph();
#endregion
}
//... other graphs update here
Thread.Sleep(5);
}
}
SetLine
is:
public void SetLine(String lineTitle, List<PointF> values)
{
IPointListEdit ip = zgcGraph.GraphPane.CurveList[lineTitle].Points as IPointListEdit;
int tmp = Math.Min(ip.Count, values.Count);
int i = 0;
while(i < tmp)
{
if (values[i].X > peakX)
peakX = values[i].X;
if (values[i].Y > peakY)
peakY = values[i].Y;
ip[i].X = values[i].X;
ip[i].Y = values[i].Y;
i++;
}
while(ip.Count < values.Count)
{
if (values[i].X > peakX)
peakX = values[i].X;
if (values[i].Y > peakY)
peakY = values[i].Y;
ip.Add(values[i].X, values[i].Y);
i++;
}
while(values.Count > ip.Count)
{
ip.RemoveAt(ip.Count - 1);
}
}
RefreshGraph
is:
public void RefreshGraph()
{
if (!explicidX && autoScrollFlag)
{
zgcGraph.GraphPane.XAxis.Scale.Max = Math.Max(peakX + grace.X, rangeX);
zgcGraph.GraphPane.XAxis.Scale.Min = zgcGraph.GraphPane.XAxis.Scale.Max - rangeX;
}
if (!explicidY)
{
zgcGraph.GraphPane.YAxis.Scale.Max = Math.Max(peakY + grace.Y, maxY);
zgcGraph.GraphPane.YAxis.Scale.Min = minY;
}
zgcGraph.Refresh();
}
.
-------------------- Update7: --------------------
Просто прогнал через профилировщик ANTS. Он говорит мне, что количество обновлений ZedGraph
, когда программа работает быстро, точно в два раза выше, чем при медленной. Вот скриншоты:
Мне ОЧЕНЬ странно, что, учитывая небольшую разницу в длине секций, производительность отличается вдвое с математической точностью.
Также я обновил драйвер графического процессора, но это не помогло.
-------------------- Update8: --------------------
К сожалению, в течение нескольких дней я не могу воспроизвести проблему ... Я получаю постоянную приемлемую скорость (которая все еще кажется немного медленнее, чем та, что была у меня в профилировщике две недели назад), на которую не влияет любой из факторов, которые влияли на это две недели назад - профилировщик, захват видео или окно драйвера графического процессора. У меня до сих пор нет объяснения причин этого ...
lock (d.fftDataLock)
. Итак, каково вмешательство между другими ресурсами, использующими ту же блокировку? Что будет, если убрать строчки о вызове метода graphFFT.Refresh / RefreshComplete? - person Oliver   schedule 22.05.2013short[] tempData
, который будет заменен в незаполненной блокировке, поэтому вы можете удалить= new short[2048]
. Или лучше один раз создать буфер внеwhile(true)
и вместо.Clone()
использовать.CopyTo()
. - person Oliver   schedule 22.05.2013.CopyTo()
, но я, хотя внутри он также сделал быmemcpy
и не повторял бы каждый элемент. - person Oliver   schedule 22.05.2013label.Text = text
), возможно, с отметкой времени и т. Д., Чтобы увидеть мерцание. Я готов поспорить, что проблема в графическом драйвере и в том, как библиотека графов вызывает его для рисования чего-либо (GDI, openGL, DirectX и т. Д.), И насколько хорош драйвер графической карты для выполнения этих команд. - person Oliver   schedule 22.05.2013Thread.Sleep
,Timer
и т. Д.), Будет намного более точным. Это объяснило бы оба случая ускорения - например, приложения WPF увеличивают разрешение таймера при необходимости (например, при выполнении плавной анимации), а затем возвращают его обратно (когда анимация останавливается). Профилировщикам, очевидно, также нужны более точные таймеры. - person Luaan   schedule 22.04.2015