Есть ли разница между этими двумя циклами? - PullRequest
0 голосов
/ 19 сентября 2019

Функционально нет никакой разницы между этими двумя циклами, но есть ли преимущество выбора одного из них по сравнению с другим?

for (var i = 0; i < loopLimit; i++)
{

}

VS

for (var i = 0; loopLimit > i; i++)
{

}

Есть ли разница в размещении большего числа слева от знака < против справа?


Выполнение очень простого тестирования. Я заметил, что если поместить большее число слева от <, то оно всегда будет работать немного лучше, чем слева.Вот небольшой пример результатов:

loopLimit > i усредненные 41,479,219 отметки, в то время как i < loopLimit усредненные 41,610,158 отметки для выполнения следующих циклов тестирования:

void MeasureLoop()
{
    const int loopLimit = Int32.MaxValue;

    var timer = new Stopwatch();    
    timer.Start();

    for (var i = 0; i < loopLimit; i++)
    {
        //
    }

    timer.Stop();
}

и

void MeasureLoop()
{
    const int loopLimit = Int32.MaxValue;

    var timer = new Stopwatch();    
    timer.Start();

    for (var i = 0; loopLimit > i; i++)
    {
        //
    }

    timer.Stop();
}

Ответы [ 2 ]

4 голосов
/ 19 сентября 2019

Вопрос помечен , хотя по телу неясно, является ли это строго вопросом производительности или он также открыт для других, возможно, не относящихся к теме различий между двумя стилямитакие как удобочитаемость, общее соглашение и т. д. В любом случае, для решения проблемы производительности я использовал BenchmarkDotNet для написания тестов сравнения двух операторов в случае, когда неитераторный операнд является константой, а такжеслучай, когда это переменная ...

using BenchmarkDotNet.Attributes;

namespace SO58016813
{
    public static class Program
    {
        public static void Main()
        {
            BenchmarkDotNet.Running.BenchmarkRunner.Run<Benchmarks>();
        }
    }

    [ClrJob()]
    [CoreJob()]
    [CategoriesColumn()]
    [GroupBenchmarksBy(BenchmarkDotNet.Configs.BenchmarkLogicalGroupRule.ByCategory)]
    public class Benchmarks
    {
        private const int LoopLimit = int.MaxValue;

        [Benchmark(Baseline = true)]
        [BenchmarkCategory("Constant operand")]
        public void IteratorLessThanConstant()
        {
            for (var i = 0; i < LoopLimit; i++)
            {
                // Do nothing...
            }
        }

        [Benchmark()]
        [BenchmarkCategory("Constant operand")]
        public void ConstantGreaterThanIterator()
        {
            for (var i = 0; LoopLimit > i; i++)
            {
                // Do nothing...
            }
        }

        [Benchmark(Baseline = true)]
        [BenchmarkCategory("Variable operand")]
        public void IteratorLessThanVariable()
        {
            var loopLimit = LoopLimit;

            for (var i = 0; i < loopLimit; i++)
            {
                // Do nothing...
            }
        }

        [Benchmark()]
        [BenchmarkCategory("Variable operand")]
        public void VariableGreaterThanIterator()
        {
            var loopLimit = LoopLimit;

            for (var i = 0; loopLimit > i; i++)
            {
                // Do nothing...
            }
        }
    }
}

Я заранее провел небольшое исследование, чтобы убедиться, что пустые циклы не были оптимизированы, и, согласно Есть ли способ получить .NetJIT или C # компилятор для оптимизации пустых циклов for? , они не делают.Вот результаты, которые я получил на .NET Framework и .NET Core ...

// * Summary *

BenchmarkDotNet=v0.11.5, OS=Windows 10.0.18362
Intel Core i7 CPU 860 2.80GHz (Nehalem), 1 CPU, 8 logical and 4 physical cores
.NET Core SDK=2.1.802
  [Host] : .NET Core 2.1.13 (CoreCLR 4.6.28008.01, CoreFX 4.6.28008.01), 64bit RyuJIT
  Clr    : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.8.4010.0
  Core   : .NET Core 2.1.13 (CoreCLR 4.6.28008.01, CoreFX 4.6.28008.01), 64bit RyuJIT


|                      Method |  Job | Runtime |       Categories |    Mean |    Error |   StdDev | Ratio |
|---------------------------- |----- |-------- |----------------- |--------:|---------:|---------:|------:|
|    IteratorLessThanConstant |  Clr |     Clr | Constant operand | 1.285 s | 0.0063 s | 0.0059 s |  1.00 |
| ConstantGreaterThanIterator |  Clr |     Clr | Constant operand | 1.282 s | 0.0021 s | 0.0020 s |  1.00 |
|                             |      |         |                  |         |          |          |       |
|    IteratorLessThanVariable |  Clr |     Clr | Variable operand | 1.288 s | 0.0065 s | 0.0061 s |  1.00 |
| VariableGreaterThanIterator |  Clr |     Clr | Variable operand | 1.282 s | 0.0028 s | 0.0026 s |  1.00 |
|                             |      |         |                  |         |          |          |       |
|    IteratorLessThanConstant | Core |    Core | Constant operand | 1.286 s | 0.0082 s | 0.0077 s |  1.00 |
| ConstantGreaterThanIterator | Core |    Core | Constant operand | 1.287 s | 0.0072 s | 0.0067 s |  1.00 |
|                             |      |         |                  |         |          |          |       |
|    IteratorLessThanVariable | Core |    Core | Variable operand | 1.284 s | 0.0063 s | 0.0059 s |  1.00 |
| VariableGreaterThanIterator | Core |    Core | Variable operand | 1.286 s | 0.0075 s | 0.0071 s |  1.00 |

Основываясь на приведенных выше результатах ...

  • Если вы спрашиваете, если одиноператор работает быстрее, чем другой, тогда я бы сказал нет.
  • Если вы спрашиваете, какой оператор следует использовать, я бы предложил тот, который, по вашему мнению, дает наибольшую читаемость и ясность вашему коду, так как он намноговажнее любой микрооптимизации, если она вообще существует.
0 голосов
/ 19 сентября 2019

Нет, нет.Но вы должны использовать первый, как это делают все.

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