чтение файла большой файл очень медленно, пожалуйста, помогите - PullRequest
0 голосов
/ 26 августа 2011

этот код занимает около 30 минут и интенсивное использование процессора, в чем проблема

Do
  strLine = objReader.ReadLine()
  If strLine Is Nothing Then
    Exit Do
  End If
  'check valid proxy
  m = Regex.Match(strLine.Trim, strProxyParttern)
  strMatch = m.Value.Trim
  If String.IsNullOrEmpty(strMatch) = True OrElse _
    strMatch.Contains("..") = True Then
    Continue Do
  End If
  ' create proxy
  With tmpProxy
    .IP = strMatch.Substring(0, strMatch.IndexOf(":"))
    .Port = CInt(strMatch.Substring(strMatch.IndexOf(":") + 1))
    .Status = "new"
  End With
  ' check 
  If lstProxys.Contains(tmpProxy) = True Then
    Continue Do
  End If
  lstProxys.Add(tmpProxy)
  Debug.Print(lstProxys.Count.ToString)
Loop Until strLine Is Nothing
If lstProxys.Count < 1 Then
  Exit Sub
End If

медлительность из сравнения или чтения файла или из регулярного выражения?

EDIT

профилирование кода следующим образом

 Dim myTimer As New System.Diagnostics.Stopwatch()
        Dim t1 As Integer = 0
        Dim t2 As Integer = 0
        Dim t3 As Integer = 0
        'read the file line by line, collecting valid proxy
        Do
            'Read a line fromn the file
            myTimer.Reset()
            myTimer.Start()
            strLine = objReader.ReadLine()
            If strLine Is Nothing Then
                Exit Do
            End If
            myTimer.Stop()
            t1 = myTimer.Elapsed.Milliseconds
            'check valid proxy
            myTimer.Reset()
            myTimer.Start()
            m = Regex.Match(strLine.Trim, strProxyParttern)
            strMatch = m.Value.Trim
            If String.IsNullOrEmpty(strMatch) = True OrElse _
                strMatch.Contains("..") = True Then
                Continue Do
            End If
            myTimer.Stop()
            t2 = myTimer.Elapsed.Milliseconds
            ' create proxy
            myTimer.Reset()
            myTimer.Start()
            tmpProxy.IP = strMatch.Substring(0, strMatch.IndexOf(":"))
            tmpProxy.Port = CInt(strMatch.Substring(strMatch.IndexOf(":") + 1))
            tmpProxy.Status = "new"

            ' check 
            If lstProxys.Contains(tmpProxy) = True Then
                Continue Do
            End If
            lstProxys.Add(tmpProxy)
            myTimer.Stop()
            t2 = myTimer.Elapsed.Milliseconds
            Debug.Print(String.Format("Read={0}, Match={1}, Add={2}", t1, t2, t3))
        Loop Until strLine Is Nothing

дал эти результаты

Read=0, Match=0, Add=1
Read=0, Match=0, Add=1
Read=0, Match=0, Add=2
...
Read=0, Match=0, Add=9
Read=0, Match=0, Add=9
Read=0, Match=0, Add=10
...
...
Read=0, Match=0, Add=39
Read=0, Match=0, Add=39
Read=0, Match=0, Add=40
etc

похоже, что код в порядке, за исключением добавления в список

Ответы [ 3 ]

2 голосов
/ 27 августа 2011

Скорость связана с тем, что вы используете список (структуры). Метод List.Contains - это линейный поиск (он просматривает каждый элемент списка, чтобы определить, соответствует ли он), поэтому он занимает все больше времени, чем больше уникальных элементов вы добавляете в список.

Поскольку вы имеете дело с большим количеством элементов, измените lstProxys на HashSet (Of T). Вы должны увидеть огромный прирост производительности. Все, что вам нужно сделать, это изменить определение lstProxys:

Dim lstProxys as New HashSet(Of structure)
1 голос
/ 27 августа 2011

Дисковый ввод-вывод обычно является ограничивающим фактором для чего-то подобного.В зависимости от скорости диска можно ожидать пропускную способность около 5–20 мегабайт в секунду.

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

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

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

1 голос
/ 27 августа 2011

является медлительностью из сравнения или чтения файла или из регулярного выражения?

Мы могли бы принять обоснованные догадки, но почему бы не измерить это вместо этого.

Например, запустите следующие три теста отдельно в режиме выпуска и без подключенного отладчика и посмотрите, сколько времени это займет

'Test 1 Just IO

Do
  strLine = objReader.ReadLine()

Loop Until strLine Is Nothing
If lstProxys.Count < 1 Then
  Exit Sub
End If

'Test 2 IO + Regex

Do
  strLine = objReader.ReadLine()
  If strLine Is Nothing Then
    Exit Do
  End If
  'check valid proxy
  m = Regex.Match(strLine.Trim, strProxyParttern)
  strMatch = m.Value.Trim
  If String.IsNullOrEmpty(strMatch) = True OrElse _
    strMatch.Contains("..") = True Then
    Continue Do
  End If

Loop Until strLine Is Nothing
If lstProxys.Count < 1 Then
  Exit Sub
End If

'Test 3 IO + regex and Compare
Do
  strLine = objReader.ReadLine()
  If strLine Is Nothing Then
    Exit Do
  End If
  'check valid proxy
  m = Regex.Match(strLine.Trim, strProxyParttern)
  strMatch = m.Value.Trim
  If String.IsNullOrEmpty(strMatch) = True OrElse _
    strMatch.Contains("..") = True Then
    Continue Do
  End If
  ' create proxy
  With tmpProxy
    .IP = strMatch.Substring(0, strMatch.IndexOf(":"))
    .Port = CInt(strMatch.Substring(strMatch.IndexOf(":") + 1))
    .Status = "new"
  End With
  ' check 
  If lstProxys.Contains(tmpProxy) = True Then
    Continue Do
  End If
  lstProxys.Add(tmpProxy)
  Debug.Print(lstProxys.Count.ToString)
Loop Until strLine Is Nothing
If lstProxys.Count < 1 Then
  Exit Sub
End If
...