Страница: 1 | 2 | 3 |
Вопрос: Substring, left, right, mid и скорость в цикле
Добавлено: 26.05.10 00:09
Автор вопроса: Михаил
Здравствуйте, подскажите пожалуйста.
Есть куча файлов по 1-10 мегобайт, в которых перечислена продукция. Генерируются старой сетевой программой, которую заменить и переписать возможности нет. Перечислена продукция смешным образом -
продукт1@цена1$количество1&
продукт2@цена2$количество2&
...
Возникла потребность обработать информацию.
Считываю следующим образом:
fs = New FileStream("имя файла", FileMode.Open)
sr = New StreamReader(fsr, Encoding.Default)
Do Until sr.EndOfStream
... = sr.ReadLine
..........
Далее в цикле приходится использовать
InStr (для считывания позиций @, $, & в строке)
Microsoft.VisualBasic.Left
Microsoft.VisualBasic.right
Microsoft.VisualBasic.mid
Скорость удручает.
Замена mid и left на substring ничего не ускорило, а вместо right тогда ещё и len приходится использовать.
Читал в http://www.vbnet.ru/forum/show.aspx?id=58483 и на забугорных форумах, что .net есть чего-то "родное", что более эффективно, но так и не было сказано что именно.
Буду признателен за подсказку :)
Ответы
Всего ответов: 31
Номер ответа: 1
Автор ответа:
s12
Вопросов: 24
Ответов: 363
Профиль | | #1
Добавлено: 26.05.10 01:28
Я бы загрузил сначала весь файл в StringBuilder он примерно на порядок быстрее String, а потом от этого бы начал плясать.
Номер ответа: 2
Автор ответа:
EROS
Вопросов: 58
Ответов: 4255
Профиль | | #2
Добавлено: 26.05.10 11:14
Это не тот случай когда нужно юзать StringBuilder, тут он не даст прироста скорости.. Reader,имхо, для считывания наиболее быстрый вариант..
Для этого есть IndexOf & LastIndexOf
Это фсе в топку.. используй Substring и Lenght
Кроме всего прочего из "Родных средств" могу рекомендовать ф-ю Split которая на вход принимает массив разделителей (в твом случае это @, $, &, а на выходе получишь строковый массив из 3 элементов В этом случае отпадет необходимость использования всех вышеперечисленных ф-й, что, само по себе, достаточно серьезно упростит код.
И второй вариант - это использовать регулярные выражения..
За быстродействия обоих вариантов ничего сказать не могу - это надо делать бенчмарки...
Номер ответа: 3
Автор ответа:
Sharp
Лидер форума
ICQ: 216865379
Вопросов: 106
Ответов: 9979
Web-сайт:
Профиль | | #3
Добавлено: 26.05.10 14:16
Может, просто пробегать символы и сохранять индекс начала нужной подстроки? Ни одного копирования, пробег по файлу 1 раз.
Номер ответа: 4
Автор ответа:
EROS
Вопросов: 58
Ответов: 4255
Профиль | | #4
Добавлено: 26.05.10 15:03
а смысл? ему копировать по любому надо будет.. Наверняка, все эти пляски с бубном для того чтоб привести эти файлы как какому то другому виду.. или перенос данных в БД..
Номер ответа: 5
Автор ответа:
Михаил
Вопросов: 1
Ответов: 2
Профиль | | #5
Добавлено: 26.05.10 15:07
Substring и Lenght по скорости получились почти такими же, как left, right, mid. И IndexOf & LastIndexOf вместо InStr тоже скорости не прибавил.
Сделал replace всех @, $, & на *(в принципе, так менять могу в самой программе постоянно), т.е получилось:
продукт1*цена1*количество1*
продукт2*цена2*количество2*
...
В цикле:
Т.е. а(0) = продукт1, а(1) = цена1, а(2) = количество1 и т.д.
Заняло в 1,2 раза больше времени.
Извините, не понял. Substring с IndexOf & LastIndexOf это вроде не отменяет? Мне каждое значение между * sr.ReadLine надо проверять в if...then.
Получается Substring и Lenght буду использовать...
Номер ответа: 6
Автор ответа:
EROS
Вопросов: 58
Ответов: 4255
Профиль | | #6
Добавлено: 26.05.10 16:34
Я сделал тест на 500000 строках.. Размер файла получился ~31 метр (у тебя максимально 10 метров).
Тестировал 2 метода:
- Method1: Substring + IndexOf
- Method2: Split
Результаты получил следующие..
=========Begin test=========
Method1: 00:00:00.3906250
Method2: 00:00:00.5625000
=========Begin test=========
Method1: 00:00:00.3906250
Method2: 00:00:00.5468750
=========Begin test=========
Method1: 00:00:00.3750000
Method2: 00:00:00.5625000
имхо,обработать полмиллиона строк за 0,4-0,6 сек вполне нормальный результат..
из результатов очевидно, что первый метод гораздо быстрее второго.. регулярные выражения даже тестировать не стал..
Номер ответа: 7
Автор ответа:
Sharp
Лидер форума
ICQ: 216865379
Вопросов: 106
Ответов: 9979
Web-сайт:
Профиль | | #7
Добавлено: 26.05.10 19:00
Отменяет.
Фига у тебя винтяра.
Номер ответа: 8
Автор ответа:
Artyom
Разработчик
Вопросов: 130
Ответов: 6602
Профиль | | #8
Добавлено: 26.05.10 20:10
Через SR.ReadLine считывается строка
Потом разбирается чем угодно (IndexOf, регулярными выражениями).
Я не могу понять как нжуно написать код, чтоб манипуляции со сторокой длиной в несколько десятков символов занимали хоть сколько-то времени
Номер ответа: 9
Автор ответа:
Михаил
Вопросов: 1
Ответов: 2
Профиль | | #9
Добавлено: 27.05.10 00:11
Время они занимают постольку, поскольку файлов этих на несколько гигабайт, а в циклах прокручиваются они с разбиением строки sr.readline много раз. Просто экономическая статистика обрабатывается в научных целях. Использовал Microsoft.VisualBasic.right/left/mid, который все ругают, думал, что заменив его все ускорится. Однако, заменив на substring быстрей не стало. Со split'ом стало медленней. Вот и все.
Всем спасибо за помощь!
Номер ответа: 10
Автор ответа:
Artyom
Разработчик
Вопросов: 130
Ответов: 6602
Профиль | | #10
Добавлено: 27.05.10 19:07
Считывание данных с диска выполняется несравнимо дольше чем их анализ, и здесь от способа разбиения суммарная скорость не зависит. Разумеется, если ты нигде не накосячил
Номер ответа: 11
Автор ответа:
Smith
ICQ: adamis@list.ru
Вопросов: 153
Ответов: 3632
Профиль | | #11
Добавлено: 29.05.10 00:38
Короче просто
ТС юзал дотнэт без религиозного трепета
и великий бох фрэймворк наказал его за это
Номер ответа: 12
Автор ответа:
VβÐUηìt
Вопросов: 246
Ответов: 3333
Web-сайт:
Профиль | | #12
Добавлено: 30.05.10 15:29
и здесь от способа разбиения суммарная скорость не зависит.
Ну почему... Можно например, чуть-чуть сэкономить время: считываем первые 10'000 строк, запускаем обработку отдельным потоком, тем временем считываем другие десять тысяч строк, запускаем обработку еще одним потоком и т.п. В данном случае время обработки сведется к минимому, так как время будет тратиться только на считывание ботвы с жесткого диска (ибо оброаботки, запущенные параллельно, будут завершаться гораздо быстрее), и обработка не будет задерживать считывание.
Номер ответа: 13
Автор ответа:
Smith
ICQ: adamis@list.ru
Вопросов: 153
Ответов: 3632
Профиль | | #13
Добавлено: 30.05.10 16:35
обработка совсем не будет задерживать чтение если вгрузить всё за один раз
Номер ответа: 14
Автор ответа:
EROS
Вопросов: 58
Ответов: 4255
Профиль | | #14
Добавлено: 30.05.10 18:48
Как раз таки ситуация с точностью до наоборот... там считывание задерживает обработку. Файловые операции ввода-вывода несравнимо тормознутее операций обработки строк, и ускорить ты это не сомжешь.. все ограничено скоростью винта.
она и так ничего не задерживает... а вот грузить в память большие объемы данных - это есть криво.
Номер ответа: 15
Автор ответа:
Smith
ICQ: adamis@list.ru
Вопросов: 153
Ответов: 3632
Профиль | | #15
Добавлено: 30.05.10 20:33
нэтбук сцуко клава моросит
Есть куча файлов по 1-10 мегобайт
Ну даже если и как у тебя
Размер файла получился ~31 метр
большим объемом это не назовешь
сами говорите, что мелочится с ресурсами на современных машинах неприлично