Visual Basic, .NET, ASP, VBScript
 

   
   
     

Форум - .NET

Страница: 1 | 2 | 3 | 4 | 5 |

 

  Вопрос: Оптимизация кода для быстродействия (массивы) Добавлено: 05.03.08 02:59  

Автор вопроса:  traford

Ответить

  Ответы Всего ответов: 63  

Номер ответа: 16
Автор ответа:
 Artyom



Разработчик

Вопросов: 130
Ответов: 6602
 Профиль | | #16 Добавлено: 07.03.08 01:39
Файл почти 500 МБ.

Вот код:

        Dim Count = 0
        Dim Path = "C:\1.txt"

        Dim start = DateTime.Now

        Using SR = New StreamReader(Path)
            Dim L = SR.ReadLine
            Do While (L IsNot Nothing)
                Count += 1
                Dim Length = L.Length
                L = SR.ReadLine
            Loop
        End Using
        Console.WriteLine("Stream Reader: {0}", Now.Subtract(start).ToString)
        Console.WriteLine("Count: {0}", Count)

        start = Now
        Dim Data = File.ReadAllLines(Path)
        Console.WriteLine("ReadAllLines: {0}", Now.Subtract(start).ToString)
        Console.WriteLine("Length: {0}", Data.Length)

        start = Now
        Count = 0
        For Each L In Data
            Count += 1
            Dim Length = L.Length
        Next
        Console.WriteLine("For Each: {0}", Now.Subtract(start).ToString)
        Console.WriteLine("Count: {0}", Data.Length)

        start = Now
        Count = 0
        For i = 0 To Data.Length - 1
            Count += 1
            Dim Length = Data(i).Length
        Next
        Console.WriteLine("For Next: {0}", Now.Subtract(start).ToString)
        Console.WriteLine("Count: {0}", Data.Length)

        Console.ReadLine()


Stream Reader: 00:00:09.9950000
Count: 10000001

ReadAllLines: 00:00:24.7500000
Length: 10000001

For Each: 00:00:00.3710000
Count: 10000001

For Next: 00:00:00.2990000
Count: 10000001


Хочу отметить что при выполнении ReadAllLines программа "отъела" в ОЗУ 1.3 с лишним ГБ, и по сути заполнила бОльшую часть моих 2 ГБ ОЗУ.
В принципе просто повезло что памяти хватило - если бы ее не хватило то пошел бы своппинг и на переборе самого массива скорость бы еще упала.

Результаты могу пояснить - считывание данных в массив через ReadAllLines занимает гораздо больше времени, чем обычный перебор строк через StreamReader по той причине что ReadAllLines загружает все стрчоки в массив что сопровождается постоянным выделением новых объемов памяти.
Хотя, если посмотришь рефлектором, сам код чтения данных у меня идентичен тому что используется в ReadAllLines.

Сам процес перебора загруженного массива в ОЗУ происходит очень быстро - как видишь разница между For Next и For Each минимальна (хотя я ожидал что она вообще будет отсутствовать, видимо в For Each вводятся дополнительные проверки), и не сравнима с самим временем загрузки данных.

Для относительно маленького файла (50 мб) время выглядит так:

Stream Reader: 00:00:00.4140000
Count: 1000001

ReadAllLines: 00:00:01.3580000
Length: 1000001

For Each: 00:00:00.0340000
Count: 1000001

For Next: 00:00:00.0310000
Count: 1000001

Т.е. в любом случае перебор через StreamReader будет быстрее.

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

Но на таком синтетическом тесте - сам видишь какой результат.

Ответить

Номер ответа: 17
Автор ответа:
 Artyom



Разработчик

Вопросов: 130
Ответов: 6602
 Профиль | | #17 Добавлено: 07.03.08 01:41
Покажи ВЕСЬ свой код, тогда можно будет о чем-то говорить.

А так ты кидаешь какие-то обрывки с непонятными объяснениями, даже из которых ясно что ты где-то налажал.

StreamReader не может быть медленнее ReadAllLines - тупо потому что ReadAllLines работает с этим классом.

Ответить

Номер ответа: 18
Автор ответа:
 traford



Вопросов: 1
Ответов: 18
 Профиль | | #18 Добавлено: 07.03.08 01:54
Да я не говорю что StreamReader медленнее :) я про Do loop говорил, тот же StreamReader с For...Next быстрей работает, вообщем ща

Ответить

Номер ответа: 19
Автор ответа:
 Artyom



Разработчик

Вопросов: 130
Ответов: 6602
 Профиль | | #19 Добавлено: 07.03.08 02:23
Do Loop медленнее чем For Next?
Какой сказочный тупизъм...

Ответить

Номер ответа: 20
Автор ответа:
 traford



Вопросов: 1
Ответов: 18
 Профиль | | #20 Добавлено: 07.03.08 02:44
Вот щас гуд, и тот файл обрабатывает где пустая строка была тоже гуд, до этого было как было, в 3 раза дольше, и это не сказочный тупизьм :) в файле не 1 2 3 4 5 6 7 :) чего только нету, а смысл темы не что быстрее StreamReader или ReadLines смысл чем быстрее обрабатывать данные, самое быстрое работа с массивом, но он жрёт память, со стримриадером не получиться т.к медленно, в итоге, всё таки юзать массив? с массивом даже секунды не было при обработке строк, а StreamReader'ом 12 секунд

Ответить

Номер ответа: 21
Автор ответа:
 traford



Вопросов: 1
Ответов: 18
 Профиль | | #21 Добавлено: 07.03.08 02:50
Я к тому что у меня очень много условий по обработке строк, если построчно считывать + обработка и проверка на все условия скорость ещё ниже упадёт

Ответить

Номер ответа: 22
Автор ответа:
 traford



Вопросов: 1
Ответов: 18
 Профиль | | #22 Добавлено: 07.03.08 02:54
Кстати такой вопрос, принудительно вызвать сборщик мусора никак нельзя? скажем после обработки файла перед переходом к другому, тогда он освободит память, читал в статье что можно, даже код был, только статья под первую бету VS и уже синтаксис не подходит, или убрали эту возможность, х.з

Ответить

Номер ответа: 23
Автор ответа:
 BG(Алексей)



Вопросов: 26
Ответов: 295
 Профиль | | #23 Добавлено: 07.03.08 05:23
А какие условия проверки строк?

Ответить

Номер ответа: 24
Автор ответа:
 traford



Вопросов: 1
Ответов: 18
 Профиль | | #24 Добавлено: 07.03.08 10:11
Много If'ов с разными условиями, также много if "переменная со строкой".Contains("что то там";) при некоторых условиях нужны будут данные из других строк, а результат выводиться в String.Builder, и всё это в цикле :( вообщем быстрее тут походу не чего нельзя сделать, придеться ставить ограничение на входящий файл, одна проблема со сборкой мусора, т.к память слишком долго не освобождается, и при открытии другого файла он заново отъедет память + та что ещё осталась занята от прошлого файла


попробуй выкинуть дотнет и написать на Си++ :)

Наверно стоит задуматься над советом HACKER'a :))

Ответить

Номер ответа: 25
Автор ответа:
 mc-black



ICQ: 308-534-060 

Вопросов: 20
Ответов: 1860
 Web-сайт: mc-black.narod.ru/dzp.htm
 Профиль | | #25
Добавлено: 07.03.08 13:01
Можно много спорить про Stream Reader и другие методы, но вот если писать на API, то я бы тебе настоятельно порекомендовал бы прочесть документацию на тему Memory Maped Files. Так можно существенно уменьшить прожорливость программы до памяти, можно открывать сколь угодно большие файлы. И это даже при наличии не слишком ёмкой памяти на борту.

Ответить

Номер ответа: 26
Автор ответа:
 traford



Вопросов: 1
Ответов: 18
 Профиль | | #26 Добавлено: 07.03.08 16:12
mc-black
Спасибо, поищу инфу почитаю, а пока такая лажа у меня получилось :( оказывается все тормоза из-за прогресс бара...я был в шоке, когда убрал код из цикла и результат получился 2 миллисекунды вместо 20! секунд с прогресс баром, с чем это связанно я до сих пор не могу разобраться, ниже полный код, кидаем на форму прогрессбар ProgressBar1 и кнопку Button1, Код сканит все папки и подпапки и открывает все файлы поочереди, вот код:



Imports System.Text
Imports System.IO

Public Class Form1

    Dim arr() As String
    Dim SearchLines() As String = {"test"}
    Dim start As Date

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        start = DateTime.Now
        Dim DI As New DirectoryInfo("C:\TestFolder\";)


        For Each FI As FileInfo In DI.GetFiles()
            arr = File.ReadAllLines(FI.FullName)

            ProgressBar1.Maximum = arr.Count

            Dim output As New System.Text.StringBuilder

            For Each data As String In arr

                ProgressBar1.Value += 1

                For Each source As String In SearchLines
                    
                        output.AppendLine(data)
                   
                Next

            Next
            ProgressBar1.Value = 0
        Next


        MsgBox(Now.Subtract(start).ToString)



    End Sub
End Class



Не могу понять что не так :( с прогресс баром результат: 00:00:13, без него (а именно без ProgressBar1.Value += 1) 00:00:00.2197125, обрабатывалось 2 файла, один весом 1.5мб друго 3.3мб вот х.з что не так, кто что думает? :)

P.S Все представленные примеры я тестил в новом проекте, после переноса заметил такой глюк

Ответить

Номер ответа: 27
Автор ответа:
 traford



Вопросов: 1
Ответов: 18
 Профиль | | #27 Добавлено: 07.03.08 20:01
Проблему с висением файлов в памяти победил :) банально вызовом сборщика мусора, именно в тот момент когда нужно, вот код вызова


GC.Collect()


Осталась проблема с прогрессбаром, спасибо Steel Brand'у за то что научил работать со StreamReader'ом и объяснил в теории и на практике :)

Ответить

Номер ответа: 28
Автор ответа:
 Artyom



Разработчик

Вопросов: 130
Ответов: 6602
 Профиль | | #28 Добавлено: 07.03.08 22:10
Поставь прогрес бару максимум - 100 и устанавливай текущее значение исходя из количество обработанных строк.

Ответить

Номер ответа: 29
Автор ответа:
 Artyom



Разработчик

Вопросов: 130
Ответов: 6602
 Профиль | | #29 Добавлено: 07.03.08 22:11
То есть - устанавливай это значение не на каждой строчке, а грубо говоря, когда кол-во обработанных строк увеличивается на 1%

Ответить

Номер ответа: 30
Автор ответа:
 traford



Вопросов: 1
Ответов: 18
 Профиль | | #30 Добавлено: 08.03.08 09:07
То есть - устанавливаи это значение не на каждой строчке, а грубо говоря, когда кол-во обработанных строк увеличивается на 1%

Великолепная идея!! Спасибо! я вроде реализовал, возможно криво, если что поправь :) вот код:


Imports System.Text
Imports System.IO

Public Class Form1

    Dim arr() As String
    Dim SearchLines() As String = {"test"}
    Dim start As Date

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim m As Integer
        start = DateTime.Now
        Dim DI As New DirectoryInfo("C:\TestFolder\";)


        For Each FI As FileInfo In DI.GetFiles()
            arr = File.ReadAllLines(FI.FullName)



            Dim output As New System.Text.StringBuilder

            For Each data As String In arr
                m += 1
                If m = Fix(arr.Count / 100) Then
                    ProgressBar1.Value += 1
                    m = 0
                End If

                For Each source As String In SearchLines
                    output.AppendLine(data)
                Next

            Next
            ProgressBar1.Value = 0
        Next
        MsgBox(Now.Subtract(start).ToString)



    End Sub
End Class

Ответить

Страница: 1 | 2 | 3 | 4 | 5 |

Поиск по форуму



© Copyright 2002-2011 VBNet.RU | Пишите нам