Долгая обработка простого кода

Язык Visual Basic на платформе .NET.

Модераторы: Ramzes, Sebas

Reb Orn
Начинающий
Начинающий
 
Сообщения: 18
Зарегистрирован: 01.05.2011 (Вс) 20:11

Долгая обработка простого кода

Сообщение Reb Orn » 26.10.2011 (Ср) 15:25

Приветствую. У меня есть следующий вопрос:
На форме имеется несоклько picturebox в отдельном panel, а так же textbox просто на форме, вне этой panel. В textbox содержатся координаты секторов "квадратного мира" и тип местности сектора ("X10Y20 001", где X10Y20 - координата участка мира, а 001 тип местности - скажем щебень). Всего в "мире" получается 608 секторов - следовательно 608 строчек в textbox'е.
Picturebox'ы отображают радиус обзора, скажем их 25 (5х5). У каждого picturebox'ов в свойстве tag прописана их текущая координата, например X13Y13. При нажатии кнопки вверх на клавиатуре все 25 picturebox'ов меняют координату, прибавляя к Y единичку. После этого вызывается private sub, который делает следующий код:
Код: Выделить всё
For Each MCell In LocalMapPanel.Controls
            For i = 0 To TextBox1.Lines.Length - 1
                If (TextBox1.Lines(i).Substring(0, 6)).ToString = MCell.Tag Then
                    MCell.BackgroundImage = System.Drawing.Bitmap.FromFile("data/graphic/Enviroment/" + MapDll.Lines(i).Substring(7, 3) + ".jpg")
                End If
            Next
        Next

Т.е. проверяется каждый picturebox на panel и ему присваивается картинка, соответствующая его местности.

Все работает так как надо, но уходит на каждый "шаг" по 1-3 секунды, что очень много, неужели проверка 608 строчек каждым из 25 объектов занимает такое время? :(

ger_kar
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1957
Зарегистрирован: 19.05.2011 (Чт) 19:23
Откуда: Кыргызстан, Иссык-Куль, г. Каракол

Re: Долгая обработка простого кода

Сообщение ger_kar » 26.10.2011 (Ср) 19:48

Код то простой только в представлении на VB, а на деле производится уйма операций по обработке объектов в цикле, в котором получается 608*25=15200 итераций, да еще и файловые операции производятся, вот и тормоза. Соответственно для улучшения производительности нужно от этого избавляться. Вместо обращения каждый раз к свойствам объектов ввести соответствующие переменные и т.д.
Бороться и искать, найти и перепрятать

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 26.10.2011 (Ср) 21:14

Тут ещё и тонна операций со строками в придачу...

FireFenix
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1640
Зарегистрирован: 25.05.2007 (Пт) 10:24
Откуда: Mugen no Sora

Re: Долгая обработка простого кода

Сообщение FireFenix » 26.10.2011 (Ср) 22:25

Загрузи все картинки в память и используй список - получишь профит.

Остальное всё по мелочам.
* Что такое MCell и почему используется Tag? Создайте свой тип, чтобы избежть конвертации Object <-> String
* Смотреть внутренности TextBox.Lines. Если парсит текст только при обращении, то лучше работать с обычным TextBox.Text и посимвольно обрабатывать
* Возможно я не прав, но моё имхо - For Each медленнее обычного For
Птицей Гермеса меня называют, свои крылья пожирая... сам себя я укрощаю
私はヘルメスの鳥 私は自らの羽根を喰らい 飼い慣らされる

iGrok
Артефакт VBStreets
Артефакт VBStreets
 
Сообщения: 4272
Зарегистрирован: 10.05.2007 (Чт) 16:11
Откуда: Сетевое сознание

Re: Долгая обработка простого кода

Сообщение iGrok » 27.10.2011 (Чт) 0:23

Я не совсем понял, там что ли 608 picturebox'ов на форме?!
label:
cli
jmp label

Reb Orn
Начинающий
Начинающий
 
Сообщения: 18
Зарегистрирован: 01.05.2011 (Вс) 20:11

Re: Долгая обработка простого кода

Сообщение Reb Orn » 27.10.2011 (Чт) 7:33

Qwertiy, собственно от них и тормоза. Как верно подметил ger_kar получается 15200 операций.

FireFenix, MCell я забыл указать. Там выше обьявлено у меня:
Код: Выделить всё
Dim MCell As PictureBox

А LocalMapPanel - имя Panel на которой находятся picturebox's.
Проблема в этих 608 строчках, а не в загрузке изображений. Дело в том, что pictureboxы имеют размер 30х30 и очень быстро подгружаются.

iGrok, нет, 608 строчек в textbox'e. А picturebox'ов всего 25. При нажатии на клавиатуре одной из стрелок меняется Tag этих Picturebox'ов (координаты). После чего Tag каждого picturebox'а сверяется с каждой строчкой textbox'a и когда есть совпадение, то присваивается image соответствующий второй части строки (последним трем Char) в нужной Line Textbox'a.

FireFenix
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1640
Зарегистрирован: 25.05.2007 (Пт) 10:24
Откуда: Mugen no Sora

Re: Долгая обработка простого кода

Сообщение FireFenix » 27.10.2011 (Чт) 10:35

Reb Orn писал(а):Проблема в этих 608 строчках, а не в загрузке изображений

Чем обоснован такой вывод?
Птицей Гермеса меня называют, свои крылья пожирая... сам себя я укрощаю
私はヘルメスの鳥 私は自らの羽根を喰らい 飼い慣らされる

Reb Orn
Начинающий
Начинающий
 
Сообщения: 18
Зарегистрирован: 01.05.2011 (Вс) 20:11

Re: Долгая обработка простого кода

Сообщение Reb Orn » 27.10.2011 (Чт) 12:12

FireFenix писал(а):Чем обоснован такой вывод?


Эм. Такой вот код пробовал и увеличивал значительно количество picturebox'ов:
Код: Выделить всё
For Each MCell In LocalMapPanel.Controls
    MCell.BackgroundImage = System.Drawing.Bitmap.FromFile("data/graphic/Enviroment/001.jpg")
Next

В итоге код выполняется моментально, без задержек. Даже на 50-100 picturebox'ов. Он перебирает все кнопки и присваевает стандартную картинку с именем файла 001.jpg, но без сравнения со строчками textbox'a.
При старом коде удавалось увеличить производительность уменьшая количество строчек (т.е. уменьшая размер "мира") или убирая количество picturebox'ов, чем уменьшал количество операций. Программа тормозила меньше, но задержка все равно была.
Из вышеописанных опытов я сделал вывод что тормозит именно из-за большого количества операций.

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

iGrok
Артефакт VBStreets
Артефакт VBStreets
 
Сообщения: 4272
Зарегистрирован: 10.05.2007 (Чт) 16:11
Откуда: Сетевое сознание

Re: Долгая обработка простого кода

Сообщение iGrok » 27.10.2011 (Чт) 12:25

А, пока я писал ответ, ты уже разобрался. Но чтобы посту не пропадать, всё же напишу свои мысли:

Reb Orn писал(а):iGrok, нет, 608 строчек в textbox'e. А picturebox'ов всего 25.

Ага, вижу уже. Невнимательно прочитал.

Во-первых, нужно один раз прогнать все 608 строк, создав двухмерный массив с ключами-координатами и значениями - номером (id) текстуры.
И потом уже проходить по пикчерам один раз, просто выбирая нужную ячейку из массива.

Во-вторых, предварительно загрузить все изображения.

А лучше даже и от 25 pb избавиться, перейдя на рисование текстур на одном большом в нужных позициях.
label:
cli
jmp label

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 27.10.2011 (Чт) 13:24

Такого кода следует избегать:
Код: Выделить всё
For Q As Integer = 0 To Txt.Lines.Count - 1
Лучше использовать
Код: Выделить всё
For Each Line As String In Txt.Lines

Если кто хочет проверить:
Код: Выделить всё
Imports System.Text

Public Class Form1

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
  Dim sb As New StringBuilder

  For Q As Integer = 0 To 2048
    sb.AppendLine(Q)
  Next Q

  Txt.Text = sb.ToString()
End Sub

Private Sub BtnDoIt_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnDoIt.Click
  Dim Start As Date
  Dim Temp As String

  Start = Now()
  For Each Line As String In Txt.Lines
    Temp = Line.ToLower()
  Next Line
  MsgBox((Now() - Start).TotalMilliseconds())

  Start = Now()
  For Q As Integer = 0 To Txt.Lines.Count - 1
    Temp = Txt.Lines(Q).ToLower()
  Next Q
  MsgBox((Now() - Start).TotalMilliseconds())

  Start = Now()
  For Each Line As String In Txt.Lines
    Temp = Line.ToLower()
  Next Line
  MsgBox((Now() - Start).TotalMilliseconds())
End Sub
End Class
0 мс vs 1250 мс - огромная разница.

Вероятная причина - создание массива строк при обращении к Lines. Хотя тут я не уверен.

FireFenix
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1640
Зарегистрирован: 25.05.2007 (Пт) 10:24
Откуда: Mugen no Sora

Re: Долгая обработка простого кода

Сообщение FireFenix » 27.10.2011 (Чт) 22:35

Идёт создание массива и поиск строки каждый раз сначала вот поэтому и медленно...
Код: Выделить всё
Public Property Lines As String()
    Get
        Dim num2 As Integer
        Dim text As String = Me.Text
        Dim list As New ArrayList
        Dim i As Integer = 0
        Do While (i < [text].Length)
            num2 = i
            Do While (num2 < [text].Length)
                Dim ch As Char = [text].Chars(num2)
                If ((ch = ChrW(13)) OrElse (ch = ChrW(10))) Then
                    Exit Do
                End If
                num2 += 1
            Loop
            Dim str2 As String = [text].Substring(i, (num2 - i))
            list.Add(str2)
            If ((num2 < [text].Length) AndAlso ([text].Chars(num2) = ChrW(13))) Then
                num2 += 1
            End If
            If ((num2 < [text].Length) AndAlso ([text].Chars(num2) = ChrW(10))) Then
                num2 += 1
            End If
            i = num2
        Loop
        If (([text].Length > 0) AndAlso (([text].Chars(([text].Length - 1)) = ChrW(13)) OrElse ([text].Chars(([text].Length - 1)) = ChrW(10)))) Then
            list.Add("")
        End If
        Return DirectCast(list.ToArray(GetType(String)), String())
    End Get
    Set(ByVal value As String())
        If ((Not value Is Nothing) AndAlso (value.Length > 0)) Then
            Dim builder As New StringBuilder(value(0))
            Dim i As Integer
            For i = 1 To value.Length - 1
                builder.Append(ChrW(13) & ChrW(10))
                builder.Append(value(i))
            Next i
            Me.Text = builder.ToString
        Else
            Me.Text = ""
        End If
    End Set
End Property
Птицей Гермеса меня называют, свои крылья пожирая... сам себя я укрощаю
私はヘルメスの鳥 私は自らの羽根を喰らい 飼い慣らされる

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 28.10.2011 (Пт) 0:56

FireFenix писал(а):Идёт создание массива и поиск строки каждый раз сначала вот поэтому и медленно...

Сосбственно, я так и думал. А при использовании For Each массив создаётся только один раз.

Reb Orn
Начинающий
Начинающий
 
Сообщения: 18
Зарегистрирован: 01.05.2011 (Вс) 20:11

Re: Долгая обработка простого кода

Сообщение Reb Orn » 05.11.2011 (Сб) 1:03

Qwertiy и FireFenix, еще раз спасибо. Особенно за
Код: Выделить всё
For Each Line As String In Txt.Lines
, ибо культура программирования у меня хромает.

Проблема, как я уже говорил, решилась другим методом. Но интереса ради вернулся к старому коду.
Собственно я попробовал использовать вместо textbox и lines обыкновенные item в listbox'e. Для меня оказалось новостью что к item он обращается сразу, а line в textbox ищет каждый раз заново, перебирая уже проверенное. Код работает без задержек, очень быстро. Причиной оказалось не огромное количество иттераций, а перебирание line у texbox"ов, но я вижу Вы уже разобрались в этом =)


Вернуться в Visual Basic .NET

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 9

    TopList