Информация об изменениях

Сообщение Re[9]: Производительность при поиске символа в строке C# от 01.04.2015 6:23

Изменено 01.04.2015 6:55 Sinix

Здравствуйте, koandrew, Вы писали:

K>Да, вы правы. Я только что проверил:


Благородные доны пытаются обогнать string.IndexOf()?
           For:   726ms, ips:   4 128 454,38 | Mem: 8,00 kb, GC0: 0 => 3000000
       IndexOf:   126ms, ips:  23 696 401,70 | Mem: 8,00 kb, GC0: 0 => 3000000

      ForShort:   168ms, ips:  59 179 686,69 | Mem: 8,00 kb, GC0: 0 => 10000000
  IndexOfShort:   204ms, ips:  48 962 005,48 | Mem: 8,00 kb, GC0: 0 => 10000000
Done.

  код
    public static void Main(string[] args)
    {
        const int RepeatCount = 100 * 1000;
        const int RepeatCountShort = 10 * 1000 * 1000;
        string longString = string.Join("", Enumerable.Range(0, 100).Select(i => Path.GetRandomFileName()));
        string shortString = "a";

        Measure("For", () =>
        {
            long result = 0;
            for (int i = 0; i < RepeatCount; i++)
            {
                result += Count(longString, 'a');
            }
            return result;
        });
        Measure("IndexOf", () =>
        {
            long result = 0;
            for (int i = 0; i < RepeatCount; i++)
            {
                result += CountFast(longString, 'a');
            }
            return result;
        });
        Console.WriteLine();
        Measure("ForShort", () =>
        {
            long result = 0;
            for (int i = 0; i < RepeatCountShort; i++)
            {
                result += Count(shortString, 'a');
            }
            return result;
        });
        Measure("IndexOfShort", () =>
        {
            long result = 0;
            for (int i = 0; i < RepeatCountShort; i++)
            {
                result += CountFast(shortString, 'a');
            }
            return result;
        });

        Console.WriteLine("Done.");
        Console.ReadKey();
    }

    static int Count(string inputString, char selector)
    {
        int result = 0;
        for (var i = 0; i < inputString.Length; i++)
        {
            if (inputString[i] == selector)
                result++;
        }
        return result;
    }

    static int CountFast(string inputString, char selector)
    {
        int result = 0;
        int index = 0;
        while (index < inputString.Length)
        {
            index = inputString.IndexOf(selector, index);
            if (index < 0)
            {
                break;
            }
            else
            {
                result++;
                index++;
            }
        }
        return result;
    }

    static void Measure(string name, Func<long> callback)
    {
        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();

        var mem = GC.GetTotalMemory(true);
        var gc = GC.CollectionCount(0);

        var sw = Stopwatch.StartNew();
        var result = callback();
        sw.Stop();

        var mem2 = GC.GetTotalMemory(false);
        var gc2 = GC.CollectionCount(0);

        var memDelta = (mem2 - mem) / 1024.0;
        var gcDelta = gc2 - gc;

        Console.WriteLine(
            "{0,14}: {1,5}ms, ips: {2,14:N} | Mem: {3,4:N2} kb, GC0: {4} => {5,6}",
            name, sw.ElapsedMilliseconds, result / sw.Elapsed.TotalSeconds, memDelta, gcDelta, result);
    }

Ну-ну.
Re[9]: Производительность при поиске символа в строке C#
Здравствуйте, koandrew, Вы писали:

K>Да, вы правы. Я только что проверил:


Благородные доны пытаются обогнать vs string.IndexOf()? (с вычеркнутым не прав, см ниже)
           For:   111ms, ips:  26 999 662,50 | Mem: 8,00 kb, GC0: 0 => 3000000
       IndexOf:    89ms, ips:  33 609 303,06 | Mem: 8,00 kb, GC0: 0 => 3000000

      ForShort:    21ms, ips: 472 929 514,59 | Mem: 8,00 kb, GC0: 0 => 10000000
  IndexOfShort:    63ms, ips: 157 367 803,18 | Mem: 8,00 kb, GC0: 0 => 10000000
Done.

  код
    public static void Main(string[] args)
    {
        const int RepeatCount = 100 * 1000;
        const int RepeatCountShort = 10 * 1000 * 1000;
        string longString = string.Join("", Enumerable.Range(0, 100).Select(i => Path.GetRandomFileName()));
        string shortString = "a";

        Measure("For", () =>
        {
            long result = 0;
            for (int i = 0; i < RepeatCount; i++)
            {
                result += Count(longString, 'a');
            }
            return result;
        });
        Measure("IndexOf", () =>
        {
            long result = 0;
            for (int i = 0; i < RepeatCount; i++)
            {
                result += CountFast(longString, 'a');
            }
            return result;
        });
        Console.WriteLine();
        Measure("ForShort", () =>
        {
            long result = 0;
            for (int i = 0; i < RepeatCountShort; i++)
            {
                result += Count(shortString, 'a');
            }
            return result;
        });
        Measure("IndexOfShort", () =>
        {
            long result = 0;
            for (int i = 0; i < RepeatCountShort; i++)
            {
                result += CountFast(shortString, 'a');
            }
            return result;
        });

        Console.WriteLine("Done.");
        Console.ReadKey();
    }

    static int Count(string inputString, char selector)
    {
        int result = 0;
        for (var i = 0; i < inputString.Length; i++)
        {
            if (inputString[i] == selector)
                result++;
        }
        return result;
    }

    static int CountFast(string inputString, char selector)
    {
        int result = 0;
        int index = 0;
        while (index < inputString.Length)
        {
            index = inputString.IndexOf(selector, index);
            if (index < 0)
            {
                break;
            }
            else
            {
                result++;
                index++;
            }
        }
        return result;
    }

    static void Measure(string name, Func<long> callback)
    {
        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();

        var mem = GC.GetTotalMemory(true);
        var gc = GC.CollectionCount(0);

        var sw = Stopwatch.StartNew();
        var result = callback();
        sw.Stop();

        var mem2 = GC.GetTotalMemory(false);
        var gc2 = GC.CollectionCount(0);

        var memDelta = (mem2 - mem) / 1024.0;
        var gcDelta = gc2 - gc;

        Console.WriteLine(
            "{0,14}: {1,5}ms, ips: {2,14:N} | Mem: {3,4:N2} kb, GC0: {4} => {5,6}",
            name, sw.ElapsedMilliseconds, result / sw.Elapsed.TotalSeconds, memDelta, gcDelta, result);
    }


UPD Умудрился померять debug-версию В релизной разрыв значительно меньше, что логично. И на коротких строках IndexOf проигрывает всухую.

Мораль: сначала проснуться, затем мерять.