Visual Basic, .NET, ASP, VBScript
 

   
   
     

Форум - .NET

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

 

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

Автор вопроса:  traford
Доброго времени суток, ребят подскажите советом, имеются файлы, большого размера, моя задача, проверить каждую строку в файле и при определенном условии скопировать её в переменную, так вот, вот как я делаю:



'Грузим файл в массив
Dim Massiv() As String = System.IO.File.ReadAllLines("TestFile.txt")

'И в цикле чекаем каждую строку на содержимое
   For Each temp As String In massiv
'Тут мой код который проверяет temp (ведь в temp содержимое строки)        
        Next

всё как надо, но ппц скоко она кушает ресурсов :( доходило до 800мб памяти (такие огромные файлы) но по другому я не знаю как реализовать, да и скорость маленькая, хочу узнать у профессионалов, реально ли увеличить производительность и уменьшить потребление ресурсов?

Ответить

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

Номер ответа: 1
Автор ответа:
 VβÐUηìt



Вопросов: 246
Ответов: 3333
 Web-сайт: смекаешь.рф
 Профиль | | #1
Добавлено: 05.03.08 13:27
Если такие жирнющие файлы, то зачем их пихать в RAM? Может проще по надобности считывать по одной строке прямо из файла (медленно, но жрет меньше памяти). Или, если крайность, считывай по кускм.

Ответить

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



Вопросов: 1
Ответов: 18
 Профиль | | #2 Добавлено: 05.03.08 18:32
В принципе можно заставить пользователя самому разделять файл и при загрузке в массив проверять размер, с этим с горем пополам но смириться можно, но при использовании данного метода (который привел в первом посте) после обработки всех строк и всего массива уже когда MsgBox выводиться о том что всё завершено, но в прога до сих пор кушает это же кол-во памяти которое выделялось при работе всего цикла, в чём тут может быть проблема? и подскажите насчёт цикла, есть ли аналог который побыстрее работает, тестировал For to с For each разница не значительна, может быть всё таки как то можно код оптимизировать для скорости? Поделитесь опытом, спасибо

Ответить

Номер ответа: 3
Автор ответа:
 HACKER


 

Разработчик Offline Client

Вопросов: 236
Ответов: 8362
 Профиль | | #3 Добавлено: 05.03.08 18:54
- цикл классический for..next попробуй
- попробуй работать с байтовым массивом
- вынеси обработку в отдельную функцию, тогда при выходе из неё все переменные используемые в ней освободятся.
- попробуй обойдись без дотнетовский классов, считуй данные из файла API функциями
- попробуй выкинуть дотнет и написать на Си++ :)

Ответить

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



Разработчик

Вопросов: 130
Ответов: 6602
 Профиль | | #4 Добавлено: 05.03.08 21:48
Ничего удивительного - ReadAllLines загружает весь файл в массив, и по понятным причинам это отъедает немало памяти.

- цикл классический for..next попробуй

На массивах цикл For Each компилятором "доводится" до For Next

- попробуй работать с байтовым массивом

Никакой разницы не будет

- вынеси обработку в отдельную функцию, тогда при выходе из неё все переменные используемые в ней освободятся.

Освободятся только после сборки мусора (когда - неизвестно но точно не моментально)

- попробуй обойдись без дотнетовский классов, считуй данные из файла API функциями

АПИ на дисковой операции? :) Читай параллельную тему :)

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

Лучше на BrainFuck :)

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

Короче ничего не надо городить.

Работаешь через StreamReader, каждую строчку считываешь через ReadLine и будет тебе счастье.

Ответить

Номер ответа: 5
Автор ответа:
 HACKER


 

Разработчик Offline Client

Вопросов: 236
Ответов: 8362
 Профиль | | #5 Добавлено: 05.03.08 22:03
АПИ на дисковой операции? :) Читай параллельную тему :)
Ссылку можно?
P.S. А что, фреймворк разве не API будет вызывать, когда дёргать классы для работы с ФС?

Ответить

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



Разработчик

Вопросов: 130
Ответов: 6602
 Профиль | | #6 Добавлено: 06.03.08 11:09
будут, но ощутимой разницы не получишь (разумеется если оптимально напишешь код)

http://vbnet.ru/forum/show.aspx?id=161985

Ответить

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



Вопросов: 1
Ответов: 18
 Профиль | | #7 Добавлено: 06.03.08 19:37

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

Не :)


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

Да ту загвостка, но думаю решить можно и со Stream Reader, при определенном условии мне нужен будет доступ к строкам находящиеся выше нынешней и ниже, вот и грузил в массив и обращался через index


Работаешь через StreamReader, каждую строчку считываешь через ReadLine и будет тебе счастье.


И так, как я понял, вот реализация


'Создаём поток для открытия файла (с его помощью получим кол-во строк)
Dim StreamFile As New IO.FileStream("F:\Users\XFq\Desktop\full_log.txt", IO.FileMode.Open)
'А это основной StreamReader который считывает строку
        Dim Reader As New IO.StreamReader(StreamFile, True)
        For i = 1 To StreamFile.Length
            value = Reader.ReadLine()
'тут мой основной код, где происходят разные операции с value
        Next
        StreamFile.Close()


Собственно я вот так представляю себе, насчет FileStream, я просто не догадался больше как узнать кол-во строк без считывания файла в переменную, чтобы не грузить память, ваше мнение, критика :)

Ответить

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



Вопросов: 1
Ответов: 18
 Профиль | | #8 Добавлено: 06.03.08 19:40
Кстате я тут подумал и прочитав второй пост, при работе со StreamReader'ом и при работе с массивом, какое соотношение скорости? что быстрее что медленнее?

Ответить

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



Вопросов: 1
Ответов: 18
 Профиль | | #9 Добавлено: 06.03.08 20:09
жаль :( протестировал, скорость ниже десятки раз, вот код тестирования, во время цикла m увеличивается на 1, размер файла 150mb



     Dim i, j, m As Integer
        Dim d1 As Date
        Dim d2 As Date
        Dim d As New TimeSpan()


        d1 = DateTime.Now
        Dim StreamFile As New IO.FileStream("file.txt", IO.FileMode.Open)
        Dim Reader As New IO.StreamReader(StreamFile, True)
        For i = 1 To StreamFile.Length
            m += 1
        Next
        StreamFile.Close()
        d2 = DateTime.Now
        d = d2.Subtract(d1)
        MsgBox(d.TotalMilliseconds)

        m = 0

'Работа с массивом

        Dim arr() As String
        arr = File.ReadAllLines("file.txt";)
        d1 = DateTime.Now
        For Each data As String In arr
            m += 1
        Next
        d2 = DateTime.Now
        d = d2.Subtract(d1)
        MsgBox(d.TotalMilliseconds)



в первом случае вышло 642,537 во втором 21,483, но загрузка памяти вышла на 400мб возможно низкая работа StreamReader'a в том что я ещё и FileStream использую?

Ответить

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



Вопросов: 1
Ответов: 18
 Профиль | | #10 Добавлено: 06.03.08 20:16
Не :) опять протестировал, скорость та же, если Streamreader с FileStream юзать, что с ним что без :(

P.S Блин жаль что посты не добавляются к уже созданным и не редактируются, а то пол темы уже моих ответов

Ответить

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



Разработчик

Вопросов: 130
Ответов: 6602
 Профиль | | #11 Добавлено: 06.03.08 20:48
что у тебя за код так и не понял, но вариант со StreamReader у тебя написан неправильно.
Вот верный код для чтения через StreamReader:

        Using SR = New StreamReader("C:\1.txt", System.Text.Encoding.UTF8)
            Dim L As String
            Do
                L = SR.ReadLine
                ' Обрататываешь текущую строчку
            Loop While L IsNot Nothing
        End Using

Скорость работы будет такая же как и у File.ReadAllLines на небольших файлах (т.е. пока не будет нагрузки на память). Чем больше файл тем больше памяти потребуется для его загрузки через ReadAllLines, разумеется, наступит момент когда для загрузки всего файла потребуется файл подкачки, что будет ощутимо влиять на скорость работы.

На файлах по 500 МБ или около того разницу ты увидишь.

при определенном условии мне нужен будет доступ к строкам находящиеся выше нынешней и ниже, вот и грузил в массив и обращался через index

Не вижу ничего сложного - можно хранить в переменных N последних обработаных строк.

Ответить

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



Вопросов: 1
Ответов: 18
 Профиль | | #12 Добавлено: 06.03.08 23:04

Не вижу ничего сложного - можно хранить в переменных N последних обработаных строк.


именно так у меня сейчас, спасибо за пример, сейчас буду пробовать

Ответить

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



Вопросов: 1
Ответов: 18
 Профиль | | #13 Добавлено: 06.03.08 23:33
Гм...Протестил, скорость в разы медленней чем у For .. to или For ... each и не до конца файл обрабатывает, вот, тестил с файлами от 10мб до 150мб

Ответить

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



Разработчик

Вопросов: 130
Ответов: 6602
 Профиль | | #14 Добавлено: 07.03.08 00:52
Издеваешься?

Ответить

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



Вопросов: 1
Ответов: 18
 Профиль | | #15 Добавлено: 07.03.08 01:28
Нет :) ну серьезно, так и есть, просто в файле очень много разных данных, есть и пустые строки и т.д, до конца не доходит 100% я даже счётчик запускал, в результате выяснил, в цикле For .. To поставил такой код

 m += 1
 If m = 307016 Then
                Dim s As String = Reader.ReadLine
            End If
'307016 это показание счетчика после которой цикл Do ... loop заканчивался


В режиме отладки посмотрел содержимое переменной s, показало "" т.е не чего, хотя до конца файла ещё очень далеко, вот, по поводу скорости тоже однозначно медленнее, даже на глаз видно что медленно

Ответить

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

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



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