C # очень медленный StreamReader - PullRequest
2 голосов
/ 31 марта 2012

Я использую неоптимальный код, написанный мной ...: - |

У меня есть следующий код:

string fmtLine = "";
            string[] splitedFmtLine;
            int counterFMTlines = 0;

            foreach (string fmtF in fmtFiles)
            {
                using (StreamReader sr = new StreamReader(fmtF))
                {
                    while ((fmtLine = sr.ReadLine()) != null)
                    {
                        Console.WriteLine(counterFMTlines++);
                        foreach (L3Message message in rez)
                        {
                            splitedFmtLine = Regex.Split(fmtLine, "\t");

                            if (message.Time == splitedFmtLine[0])
                            {
                                message.ScramblingCode = splitedFmtLine[7];      
                            }
                        }
                    }
                }
            }

Я тестировал этот код, когда список был пуст и был только один файл (с разделителями табуляции, 280000 строк), и даже тогда потребовалось время жизни (1 минута), чтобы пройти все 280000 строк моего файла. Это означает, что выполнение пропустило цикл foreach, где находится мой список myObjs.

Я не могу понять, почему это заняло так много времени?

Как пример, я заполнял свой Список myObjs (древовидная иерархия) другим текстовым файлом (исходным файлом), но больше, чем разделитель этой вкладки (разделитель табуляции: 16 МБ, исходный файл: 36 МБ), и это заняло всего секунду против этого 1 минут.

Ответы [ 2 ]

7 голосов
/ 31 марта 2012

Вы пишете в консоль 280.000 раз, что очень медленно. Удалить консольный вывод. Кроме того, используйте string.Split ('\ t'), который намного быстрее, чем этот конкретный вызов регулярного выражения.

0 голосов
/ 31 марта 2012

Помимо проблемы записи в консоль, у вас также есть O (m * n) время выполнения , где n - это количество строк в файле, а m - это количество сообщений. Это плохо, если m или n большое. Вы можете уменьшить это до операции O (n), используя вместо этого Dictionary и исключив внутренний цикл.

Вы можете поместить свои сообщения в Dictionary, используя время в качестве ключа. В цикле вам нужно только запросить в словаре сообщения в определенное время:

        string fmtLine = "";
        string[] splitedFmtLine;
        int counterFMTlines = 0;

        var messageTimes = new Dictionary<string, LinkedList<L3Message>>();
        foreach (L3Message message in rez)
        {
            LinkedList<L3Message> list=null;
            messageTimes.TryGetValue(message.Time, out list);

            list = list ?? new LinkedList<L3Message>();

            list.AddLast(message);
            messageTimes[message.Time] = list;
        }

        foreach (string fmtF in fmtFiles)
        {
            using (StreamReader sr = new StreamReader(fmtF))
            {
                while ((fmtLine = sr.ReadLine()) != null)
                {
                    //Console.WriteLine(counterFMTlines++);
                    splitedFmtLine = fmtLine.Split('\t');

                    LinkedList<L3Message> messageList = null;
                    messageTimes.TryGetValue(splitedFmtLine[0], out messageList);

                    if(messageList != null)
                    {
                        foreach (var message in messageList)
                        {
                            message.ScramblingCode = splitedFmtLine[7];                                
                        }
                        messageTimes.Remove(splitedFmtLine[0]); //see comments
                    }

                    if(messageTimes.Count==0) break; //see comments
                }
            }
            if(messageTimes.Count==0) break; //see comments
        } 

Это должно быть очень быстро.

Редактировать: Я изменил пример так, чтобы он поддерживал случаи, когда в один раз было более одного сообщения.

Edit2: Я добавил оптимизацию, основанную на том факте, что время сообщения и код шифрования всегда коррелируют (см. Комментарии).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...