Страница: 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 Each компилятором "доводится" до For Next
Никакой разницы не будет
Освободятся только после сборки мусора (когда - неизвестно но точно не моментально)
АПИ на дисковой операции? Читай параллельную тему
Лучше на 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:
Dim L As String
Do
L = SR.ReadLine
' Обрататываешь текущую строчку
Loop While L IsNot Nothing
End Using
Скорость работы будет такая же как и у File.ReadAllLines на небольших файлах (т.е. пока не будет нагрузки на память). Чем больше файл тем больше памяти потребуется для его загрузки через ReadAllLines, разумеется, наступит момент когда для загрузки всего файла потребуется файл подкачки, что будет ощутимо влиять на скорость работы.
На файлах по 500 МБ или около того разницу ты увидишь.
Не вижу ничего сложного - можно хранить в переменных 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, показало "" т.е не чего, хотя до конца файла ещё очень далеко, вот, по поводу скорости тоже однозначно медленнее, даже на глаз видно что медленно