Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Обработка строк. Почему Perl в 2 раза быстрей c#, Можно ли оптимизировать код на c#?  
:(
    Опции темы
Suppir
Дата 4.9.2010, 12:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 588
Регистрация: 20.4.2009

Репутация: нет
Всего: нет



Добрый день!

У меня в директории 1.5 Гб txt-файлов. Необходимо в каждом файле проверить строки регулярным выражением, и в случае совпадения записать строки в результирующий файл.

Вот код на Perl  

Код

open(OU, ">result.res");
while(<*.txt>){
    print "$_\n";
    open(IN, "$_");
    while(<IN>){
        print OU if /^!/;
    }
}


Время работы perl (perl 5.12 Activestate) - 41 секунда, потребление памяти 25 Мб.


Аналогичный код на c#


Код

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;

namespace parse
{
    class Program
    {
        public static void Main(string[] args)
        {
            string str = "";
            using (StreamWriter sw = new StreamWriter("C:\\projects\\result.res", false, Encoding.GetEncoding(866)))
            {
                foreach (string file in Directory.GetFiles("C:\\projects\\", "*.txt"))
                {
                 Console.WriteLine(file);
                    using (StreamReader sr = new StreamReader(file, Encoding.GetEncoding(866)))
                    {
                        while (!sr.EndOfStream)
                        {
                            str = sr.ReadLine();
                            if (Regex.IsMatch(str, "^!", RegexOptions.Singleline))
                                sw.WriteLine(str);
                        }
                    }
                }
            }
        }
    }
}


Время работы программы (.NET Fraimwork 3.5) - 77 секунд, потребление памяти 5 Мб.


Действительно ли c# медленней Perl в аналогичных задачах, или проблема (как я подозреваю) в неправильном коде? 
Как можно ускорить код c# (используя именно регулярные выражения). Целиком файлы нельзя забирать в переменные, т.к. файлы по 100 - 300 Мб размером.


Это сообщение отредактировал(а) Suppir - 4.9.2010, 13:00
PM MAIL   Вверх
jonie
Дата 4.9.2010, 13:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 6
Всего: 118



Suppir, надо скомпилировать регэксп. Грубо говоря у вас сейчас каждый match регэксп парсится заново. 
Код

private static Regex regexp = new Regex"^!", RegexOptions.Compiled);


ну а вообще конкретно в этой задаче от регэкспа нету пользы ). и да, памяти c# будет кушать больше... да и быстрее врядли будет работать, нежели парловый pcre.


--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
Suppir
Дата 4.9.2010, 14:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 588
Регистрация: 20.4.2009

Репутация: нет
Всего: нет



jonie, для это задачи понятно. У меня В программе несколько десятков рег. выражений - нужно переписать на c# все. Вот и и думаю, почему медленней получается? Ведь это уже скомпилированная программа, а Perl - всего лишь интерпретатор.

Насчет компиляции регулярных выражений. В Perl, если регекс не содержит интерполируемых переменных, то он автоматически компилируется.
Насчет потребления памяти - сама программа на c# меньше памяти потребляет (5 Мб вместо 25 перла).  Однако важнее скорость работы.

PM MAIL   Вверх
Kaerus
Дата 4.9.2010, 23:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


WPF'er
*


Профиль
Группа: Участник
Сообщений: 89
Регистрация: 3.9.2010

Репутация: нет
Всего: 1



Может не стоит считывать файл построчно. А сразу считать целиком с помощью StreamReader.ReadToEnd или хотя-бы блоками

Это сообщение отредактировал(а) Kaerus - 4.9.2010, 23:41
PM MAIL ICQ   Вверх
Suppir
Дата 5.9.2010, 07:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 588
Регистрация: 20.4.2009

Репутация: нет
Всего: нет



Kaerus, файлы очень большие для того, чтобы их целиком помечать в память + нужно перекодировать из CP866 + у меня все алгоритмы рассчитаны на построчное чтение.
Можно считать блоками, разбить блок на массив строк и двигаться по массиву, но это будет (имхо)  медленней работать и менее удобно
PM MAIL   Вверх
jonie
Дата 5.9.2010, 12:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 6
Всего: 118



Suppir, в .net по умолчанию не компилируются регэкспы.


--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
Kaerus
Дата 5.9.2010, 13:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


WPF'er
*


Профиль
Группа: Участник
Сообщений: 89
Регистрация: 3.9.2010

Репутация: нет
Всего: 1



Потестил я твой код на 5 файла по 500 МБ (в сумме 15 мил. строк), вот что показывает профилирование
user posted image
Судя по нему основная нагрузка связана с чтением строк. Немного помогает увеличение буфера файлов до 1 МБ.
PM MAIL ICQ   Вверх
Suppir
Дата 5.9.2010, 16:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 588
Регистрация: 20.4.2009

Репутация: нет
Всего: нет



Kaerus, т.е. основное время тратится на чтение строки?
PM MAIL   Вверх
Kaerus
Дата 5.9.2010, 18:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


WPF'er
*


Профиль
Группа: Участник
Сообщений: 89
Регистрация: 3.9.2010

Репутация: нет
Всего: 1



Да, но IsMatch тоже с счётов сбрасывать не стоит. Пока там одно рег. выражение не страшно, а если их будет 50 - они уже будут сильнее влиять.

Переделал твой код под чтение напрямую из FileStream блоками в буфер, с последующим переводом в строку через Encoding.GetString(...) - выигрыш скорости не более 5% (StreamReader - 40.7 сек, FileStream - 39.8 сек). Кстати разбивание на отдельные потоки (у меня 3 процессора), тоже не дает плюса в производительности.

Вывод: StreamReader хорошо кеширует чтение, так что переделывать не стоит.

Вообще в таких задачах как чтение больших данных с диска, C# не может дать преимущество перед скриптовыми языками
PM MAIL ICQ   Вверх
Suppir
Дата 5.9.2010, 19:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 588
Регистрация: 20.4.2009

Репутация: нет
Всего: нет



Понятно, спасибо.
PM MAIL   Вверх
Suppir
Дата 6.9.2010, 09:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 588
Регистрация: 20.4.2009

Репутация: нет
Всего: нет



Kaerus, 

"C# не может дать преимущество перед скриптовыми языками"

Я делал тесты с Ruby, Python, AutoIt и Perl в подобных задачах

Perl работает намного быстрее всех, Python помедленней (примерно как c#), Ruby 1.9 и AutoIt медленней Perl на порядок, т.е. в 10 раз.
Причем AutoIt был еще медленней (раз в 15), я связался с разработчиками и они в апреле немножко пофиксили функцию чтения строк из файла (раньше чтение было вообще не буферизовано!).

Это сообщение отредактировал(а) Suppir - 6.9.2010, 09:33
PM MAIL   Вверх
DenWPF
Дата 13.9.2010, 10:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1659
Регистрация: 26.9.2009

Репутация: нет
Всего: 1



Ну так есть запас памяти можно к примеру написать потоки, память увеличиться, а время сократиться.

получиться примерно 5метров*5 - память и делим на 5 время, и будет быстрее ... IMHO
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
Partizan
PashaPash

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, Partizan, PashaPash.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | .NET для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0585 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.