2016-11-15 6 views
1

SO Я попытался сделать быстрый метод подсчета строк unsafe. Я ранее использовал StringReader, но хотел посмотреть, смогу ли я что-то сделать быстрее.Подсчет линий, является ли этот Небезопасный метод действительным?

Так этот код действительно, кажется, работает, но это выглядит немного запутанным,

и я очень новой для указателей на C#, так что я мог бы делать что-то плохое.

Оригинальный метод:

//Return number of (non Empty) lines 
private static int getLineCount(string input) 
{ 
    int lines = 0; 
    string line = null; 

    //Don't count Empty lines 
    using (StringReader reader = new StringReader(input)) 
     while ((line = reader.ReadLine()) != null) 
      if (!string.IsNullOrWhiteSpace(line)) 
       lines++; 

    return lines; 
} 

небезопасный метод:

//Return number of (non Empty) lines (fast method using pointers) 
private unsafe static int getLineCountUnsafe(string input) 
{ 
    int lines = 0; 

    fixed (char* strptr = input) 
    { 

     char* charptr = strptr; 
     int length = input.Length; 
     //Don't count Empty lines 
     for (int i = 0; i < length; i++) 
     { 
      char c = *charptr; 
      //If char is an empty line, look if it's empty 
      if (c == '\n' || c == '\r') 
      { 
       //If char is empty, continue till it's not 
       while (c == '\n' || c == '\r') 
       { 
        if (i >= length) 
         return lines; 
        i++; 
        charptr++; 
        c = *charptr; 
       } 
       //Add a line when line is not just a new line (empty) 
       lines++; 
      } 
      charptr++; 
     } 

     return lines; 
    } 
} 

Benchmark:

(Looped through 100000, 10 times) 
Total Milliseconds used. 

Safe(Original) - AVG = 770.10334, MIN = 765.678, MAX = 778.0017 , TOTAL 07.701 
Unsafe - AVG = 406.91843, MIN = 405.7931, MAX = 408.5505 , TOTAL 04.069 

EDIT:

кажется, что небезопасная версия не всегда правильно , Если это одна строка, она не будет считать ее, она пытается ее решить, не считая ее слишком много; (

+2

Ваш метод * сложный * фактически ускоряет вашу работу? –

+0

В моих тестах да, примерно от «700 мс» до «300-400 мс», я думаю. – Zerowalker

+1

Опишите * действительный *? Если вы спрашиваете, работает ли это, то разве вы не должны его тестировать? – Liam

ответ

3

Ваша вторая реализация выглядит нормально, но не слишком беспокоитесь об учебе unsafe, это не так широко используемый в C#, ни указатели. Это приближается к C++. Разница во времени между обоими подходами может исходить от избегания сборщика мусора для сбора любой памяти внутри метода до его завершения (из-за ключевого слова fixed).

Причина, почему следует редко использовать unsafe потому, что C# обеспечивает большую читаемость и простоту использования в нем уже определены методы, как в вашем случае:

//Return number of (non Empty) lines 
private static int getLineCount(string input) 
{ 
    return Regex.Matches(input, Environment.NewLine).Count; 
} 

который может быть еще быстрее из-за оценивая сразу всю строку.

+0

'new StringReader (input)' создает читатель из строки, затем 'reader.ReadToEnd()' дает строка назад. Кажется очень ненужным. – Magnus

+0

@ Magnus sir, вы совершенно правы, я обновил свой ответ. – meJustAndrew

+1

Для чего я сделал тест. Regex - Среднее = 20,9546, 20,6002 = MIN, MAX = 21,6283, ВСЕГО 00,210 небезопасный - Среднее = 1,61361, MIN = 1,589, MAX = 1,6748, ВСЕГО 00,016 – Zerowalker

 Смежные вопросы

  • Нет связанных вопросов^_^