string.StartsWith очень-очень медленная. С чего вдруг?
От: Kore Sar  
Дата: 10.12.08 10:09
Оценка:
Запустите этот код.
U.StartWith работает в 10 раз быстрее, чем String.StartsWith.
Какого черта?

U.StartWith: 00:00:00.0259870
String.StartsWith: 00:00:00.2118940



using System;

namespace ConsoleApplication1
{
    class U
    {
        public static bool StartWith(string pattern, string number)
        {
            bool match = true;
            for (int digitIndex = 0; digitIndex < pattern.Length && match; digitIndex++)
            {
                match = match && number[digitIndex].Equals(pattern[digitIndex]);
            }
            return match;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            const int max = 1000000;

            string[] myStrings = new string[max];
            string[] patterns = new string[max];
            var rnd = new Random();
            for (int i = 0; i < max; i++)
            {
                myStrings[i] = rnd.Next(1000000).ToString("{0:D6}"); // 6 digits
                patterns[i] = rnd.Next(1000).ToString(); // 1-3 digits
            }

            DateTime tU = DateTime.Now;
            for (int i = 0; i < max; i++)
            {
                U.StartWith(patterns[i], myStrings[i]);
            }
            Console.WriteLine("U.StartWith: " + (DateTime.Now - tU).ToString());

            DateTime tString = DateTime.Now;
            for (int i = 0; i < max; i++)
            {
                myStrings[i].StartsWith(patterns[i]);
            }
            Console.WriteLine("String.StartsWith: " + (DateTime.Now - tString).ToString());
        }
    }
}
Re: string.StartsWith очень-очень медленная. С чего вдруг?
От: C...R...a...S...H  
Дата: 10.12.08 10:23
Оценка: :)
Здравствуйте, Kore Sar, Вы писали:

KS>Запустите этот код.

KS>U.StartWith работает в 10 раз быстрее, чем String.StartsWith.
KS>Какого черта?

KS>

KS>U.StartWith: 00:00:00.0259870
KS>String.StartsWith: 00:00:00.2118940


Потому что StartsWith реализован на сях
Там было написано русским по белому...
Re[2]: string.StartsWith очень-очень медленная. С чего вдруг
От: Kore Sar  
Дата: 10.12.08 10:24
Оценка:
Здравствуйте, C...R...a...S...H, Вы писали:

CRA>Здравствуйте, Kore Sar, Вы писали:


KS>>Запустите этот код.

KS>>U.StartWith работает в 10 раз быстрее, чем String.StartsWith.
KS>>Какого черта?

KS>>

KS>>U.StartWith: 00:00:00.0259870
KS>>String.StartsWith: 00:00:00.2118940


CRA>Потому что StartsWith реализован на сях


Ок. А что это означает? Подробности можно?
Re[3]: string.StartsWith очень-очень медленная. С чего вдруг
От: C...R...a...S...H  
Дата: 10.12.08 10:36
Оценка:
Здравствуйте, Kore Sar, Вы писали:

KS>Ок. А что это означает? Подробности можно?

Данная функция реализована не как Managed code, а как Unmanaged
Какая разница в этих понятиях можно посмотреть здесь
Там было написано русским по белому...
Re[4]: string.StartsWith очень-очень медленная. С чего вдруг
От: Kore Sar  
Дата: 10.12.08 10:46
Оценка:
Здравствуйте, C...R...a...S...H, Вы писали:

CRA>Здравствуйте, Kore Sar, Вы писали:


KS>>Ок. А что это означает? Подробности можно?

CRA>Данная функция реализована не как Managed code, а как Unmanaged
1) Вы забыли упомянуть на каких конкретно сях заимплеменчен string.StrartsWith. Т.е. вы забыли сказать в вашем первом сообщении про Unmanaged.
2) Я знаю различия между этими вещами.

CRA>Какая разница в этих понятиях можно посмотреть здесь

3) Я даже прочитал на всякий случай эту бесполезнаю для меня статью.
4) А вот ответа на вопрос "Почему мой код быстрее string.StartsWith?" я так и не нашел.

Спрашиваю еще раз.
Почему мой Managed код работает в 10 раз быстрее Unmanaged кода фреймворка?
Re[5]: string.StartsWith очень-очень медленная. С чего вдруг
От: C...R...a...S...H  
Дата: 10.12.08 11:05
Оценка:
Здравствуйте, Kore Sar, Вы писали:

KS>Здравствуйте, C...R...a...S...H, Вы писали:



KS>Спрашиваю еще раз.

KS>Почему мой Managed код работает в 10 раз быстрее Unmanaged кода фреймворка?
Я очень сильно извиняюсь.
Просто я протупил
Я почему то подумал, что ваша функция работает медленнее.
Еще раз извиняюсь.
Теперь по сути дела:
String.StartsWith работает с использование культур, что очень сказывается на его производительности.
Но вы можете на это влиять используя myStrings[i].StartsWith(patterns[i], StringComparison.Ordinal);
Тогда производительность ваших методов будет одинакова.
Там было написано русским по белому...
Re: string.StartsWith очень-очень медленная. С чего вдруг?
От: s.and  
Дата: 10.12.08 11:08
Оценка: 2 (1)
Здравствуйте, Kore Sar, Вы писали:

KS>Запустите этот код.

KS>U.StartWith работает в 10 раз быстрее, чем String.StartsWith.
KS>Какого черта?

Такого черта, что ты сравниваешь значения коде-поинты, т.е. 2-байтных элементов utf-16-строки,
а public bool StartsWith(string value) сравнивает с учетом CultureInfo.CurrentCulture.

Если нужна скорость, юзай
public bool StartsWith(
string value,
StringComparison comparisonType
),
где comparisonType = Ordinal.
Re[2]: string.StartsWith очень-очень медленная. С чего вдруг
От: Kore Sar  
Дата: 10.12.08 11:13
Оценка:
Здравствуйте, s.and, Вы писали:

SA>Здравствуйте, Kore Sar, Вы писали:


KS>>Запустите этот код.

KS>>U.StartWith работает в 10 раз быстрее, чем String.StartsWith.
KS>>Какого черта?

SA>Такого черта, что ты сравниваешь значения коде-поинты, т.е. 2-байтных элементов utf-16-строки,

SA>а public bool StartsWith(string value) сравнивает с учетом CultureInfo.CurrentCulture.

SA>Если нужна скорость, юзай

SA>public bool StartsWith(
SA> string value,
SA> StringComparison comparisonType
SA>),
SA>где comparisonType = Ordinal.

А вот этого я не знал. Спасибо.

Новые результаты такие:

U.StartWith: 00:00:00.0310000
String.StartsWith: 00:00:00.0370000


Моя функция всё-равно немного быстрее.
Re[3]: string.StartsWith очень-очень медленная. С чего вдруг
От: desco США http://v2matveev.blogspot.com
Дата: 10.12.08 11:17
Оценка:
Здравствуйте, Kore Sar, Вы писали:


KS>Моя функция всё-равно немного быстрее.


чтобы совсем честно
myStrings[i].StartsWith(patterns[i], StringComparison.OrdinalIgnoreCase)
... << RSDN@Home 1.2.0 alpha 4 rev. 1090>>
Re: string.StartsWith очень-очень медленная. С чего вдруг?
От: icool  
Дата: 10.12.08 11:17
Оценка:
Пример мне кажется не коректным
При выбранной генерации коротких случайных строк совпадений почти нет
т.е. методы выходят проверив только первый символ
другими словами проверяем на сколько быстро вызываются методы
Re[4]: string.StartsWith очень-очень медленная. С чего вдруг
От: Kore Sar  
Дата: 10.12.08 11:21
Оценка:
Здравствуйте, desco, Вы писали:

D>Здравствуйте, Kore Sar, Вы писали:



KS>>Моя функция всё-равно немного быстрее.


D>чтобы совсем честно

D>
D>myStrings[i].StartsWith(patterns[i], StringComparison.OrdinalIgnoreCase)
D>


Наверное Вы попутали что-то, да?

U.StartWith: 00:00:00.0260000
String.StartsWith: 00:00:00.1210000

Re[2]: string.StartsWith очень-очень медленная. С чего вдруг
От: Kore Sar  
Дата: 10.12.08 11:25
Оценка:
Здравствуйте, icool, Вы писали:

I>Пример мне кажется не коректным

I>При выбранной генерации коротких случайных строк совпадений почти нет
I>т.е. методы выходят проверив только первый символ
I>другими словами проверяем на сколько быстро вызываются методы

Сделал так, чтобы половина результатов проверяли все символы.
                myStrings[i] = rnd.Next(1000000).ToString("{0:D6}"); // 6 digits
                patterns[i] = rnd.Next(2) == 0 ? rnd.Next(1000).ToString() : myStrings[i].Substring(3);



Результат еще хужа для фреймворка:

U.StartWith: 00:00:00.0330000
String.StartsWith: 00:00:00.0490000


Так что врядли вы правы.
Re: string.StartsWith очень-очень медленная. С чего вдруг?
От: cvetkov  
Дата: 10.12.08 12:53
Оценка:
ну если еще добавить проверок которые есть в String то скорее всего вы сравняетесь.
например ваша функция некорректно работакт если pattern длиннее number
Re[2]: string.StartsWith очень-очень медленная. С чего вдруг
От: Kore Sar  
Дата: 10.12.08 12:58
Оценка:
Здравствуйте, cvetkov, Вы писали:

C>ну если еще добавить проверок которые есть в String то скорее всего вы сравняетесь.

C>например ваша функция некорректно работакт если pattern длиннее number

Добавил проверки. Результат абсолютно тот же самый.

U.StartWith: 00:00:00.034
String.StartsWith: 00:00:00.038

Re[3]: string.StartsWith очень-очень медленная. С чего вдруг
От: Аноним  
Дата: 10.12.08 13:12
Оценка:
KS>Сделал так, чтобы половина результатов проверяли все символы.
KS>
KS>                myStrings[i] = rnd.Next(1000000).ToString("{0:D6}"); // 6 digits
KS>                patterns[i] = rnd.Next(2) == 0 ? rnd.Next(1000).ToString() : myStrings[i].Substring(3);
KS>



KS>Результат еще хужа для фреймворка:

KS>

KS>U.StartWith: 00:00:00.0330000
KS>String.StartsWith: 00:00:00.0490000


KS>Так что врядли вы правы.


На самом деле ничего не изменилось )
наверно имелось ввиду ... : myStrings[i].Substring(0,3);
а в цифрах опечатка так как они близки и в 10 раз не отличаются
это ладно

на самом деле с myStrings[i].Substring(3,3); // нет совпадений
тоже 10 раз

00:00:00.014
00:00:00.143

myStrings[i] = rnd.Next(1000000).ToString("{0:D6}"); // 6 digits
patterns[i] = myStrings[i].Substring(0,3); // все совпадает
00:00:00.017
00:00:00.155

прибавили они почти одинаково
т.е. как мне кажется составляющая вызова и маршалинга параметров остается доминирующей
Re[4]: string.StartsWith очень-очень медленная. С чего вдруг
От: Kore Sar  
Дата: 10.12.08 13:22
Оценка:
Здравствуйте, Аноним, Вы писали:

KS>>Сделал так, чтобы половина результатов проверяли все символы.

KS>>
KS>>                myStrings[i] = rnd.Next(1000000).ToString("{0:D6}"); // 6 digits
KS>>                patterns[i] = rnd.Next(2) == 0 ? rnd.Next(1000).ToString() : myStrings[i].Substring(3);
KS>>



KS>>Результат еще хужа для фреймворка:

KS>>

KS>>U.StartWith: 00:00:00.0330000
KS>>String.StartsWith: 00:00:00.0490000


KS>>Так что врядли вы правы.


А>На самом деле ничего не изменилось )

А>наверно имелось ввиду ... : myStrings[i].Substring(0,3);

Точно. Спасибо. Исправил на Substring(0, 3).
Терерь результаты вот такие (Используя StringComparison.Ordinal конечно).

U.StartWith: 00:00:00.041
String.StartsWith: 00:00:00.052



А>прибавили они почти одинаково

А>т.е. как мне кажется составляющая вызова и маршалинга параметров остается доминирующей

Скорей всего оно так и есть. Можно выдать даже универсальный совет всем.


ИСПОЛЬЗУЙТЕ ЭТО ВСЕГДА!
public static class MyExtentionMethods
{
    public static bool AsciiStartsWith(this string str, string pattern)
    {
            if (pattern.Length > number.Length) return false;
            bool match = true;
            for (int digitIndex = 0; digitIndex < pattern.Length && match; digitIndex++)
            {
                match = match && number[digitIndex].Equals(pattern[digitIndex]);
            }
            return match;
    }
}
Re[5]: string.StartsWith очень-очень медленная. С чего вдруг
От: _FRED_ Черногория
Дата: 10.12.08 14:22
Оценка: 3 (2) +3
Здравствуйте, Kore Sar, Вы писали:

KS>ИСПОЛЬЗУЙТЕ ЭТО ВСЕГДА!

KS>public static class MyExtentionMethods
KS>{
KS>    public static bool AsciiStartsWith(this string str, string pattern)
KS>    {
KS>            if (pattern.Length > number.Length) return false;
KS>            bool match = true;
KS>            for (int digitIndex = 0; digitIndex < pattern.Length && match; digitIndex++)
KS>            {
KS>                match = match && number[digitIndex].Equals(pattern[digitIndex]);
KS>            }
KS>            return match;
KS>    }
KS>}


Прежде чем капслочить тут на всех, выставил бы для начала проверку аргументов что ль… во-вторых, надо бы всё-тки поточнее определиться, как называется первый параметр. Ну, и в-третьих, раз уж крутишься в цикле до тех пор, пока предекат (match) истинный, то чего его запоминать и умножать на самого себя? Достаточно было бы
for(var i = 0; i < pattern.Length; i++) {
  if(!number[i].Equals(pattern[i])) {
    return false;
  }//if
}//for
return true;


А на последок: слово "Ascii" в имени метода не соответствует тому, что происходит внутри метода — проверки, что обрабатываемые строки содержат символы лишь Askii-диапазона нигде нет. Так что название тоже не мешает подобрать более подходящее.
Help will always be given at Hogwarts to those who ask for it.
Re[4]: string.StartsWith очень-очень медленная. С чего вдруг
От: _d_m_  
Дата: 11.12.08 01:47
Оценка: +2
Здравствуйте, desco, Вы писали:

D>Здравствуйте, Kore Sar, Вы писали:



KS>>Моя функция всё-равно немного быстрее.


D>чтобы совсем честно

D>
D>myStrings[i].StartsWith(patterns[i], StringComparison.OrdinalIgnoreCase)
D>



Где пересоздаются сравниваемые строки в верхнем регистре
Re[5]: string.StartsWith очень-очень медленная. С чего вдруг
От: Воронков Василий Россия  
Дата: 22.12.08 11:40
Оценка:
Здравствуйте, _d_m_, Вы писали:

___>

___>Где пересоздаются сравниваемые строки в верхнем регистре

Откуда такая информация? Там все заканчивается вызовом некой:

private static extern unsafe int nativeCompareOrdinalIgnoreCaseEx(void* pNativeTextInfo, string strA, int indexA, string strB, int indexB, int length);
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Re[5]: string.StartsWith очень-очень медленная. С чего вдруг
От: Воронков Василий Россия  
Дата: 22.12.08 11:48
Оценка:
Здравствуйте, Kore Sar, Вы писали:


KS>ИСПОЛЬЗУЙТЕ ЭТО ВСЕГДА!

KS>
KS>public static class MyExtentionMethods
KS>{
KS>    public static bool AsciiStartsWith(this string str, string pattern)
KS>    {
KS>            if (pattern.Length > number.Length) return false;
KS>            bool match = true;
KS>            for (int digitIndex = 0; digitIndex < pattern.Length && match; digitIndex++)
KS>            {
KS>                match = match && number[digitIndex].Equals(pattern[digitIndex]);
KS>            }
KS>            return match;
KS>    }
KS>}
KS>



if (pattern.Length > number.Length) return false;

А что такое number.Length? И почему pattern.Length > number.Length, а не pattern.Length != number.Length? А если pattern null?

Вообще в 99.99% случаях производительность штатной функции будет достаточна. Поэтому делать какой-то самопал, в котором еще придется кому-то разбираться, пожалуй не стоит.
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.