Как я могу быть уверен, что компилятор не оптимизирует мой тест производительности?

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

Я работал над проанализировав необычный и экзотический формат файла, которым является CSV, и ради удовольствия я решил охарактеризовать производительность по сравнению с двумя известными мне языками .net, C # и F #.

Результаты были ... тревожными. F # выиграл с большим отрывом в 2 или более раз (и я на самом деле думаю, что это больше похоже на 0,5n, но получение реальных тестов оказывается сложной задачей, поскольку я тестирую аппаратный ввод-вывод). но сигнатуры производительности предполагают, что я нажимаю на диск, а не занимаюсь оперативной памятью всего файла, что вызывает полуслучайные всплески производительности.

Код F #

//Module used to import data from an arbitrary CSV source
module CSVImport
open System.IO

//imports the data froma path into a list of strings and an associated value
let ImportData (path:string) : List<string []> = 

    //recursively rips through the file grabbing a line and adding it to the 
    let rec readline (reader:StreamReader) (lines:List<string []>) : List<string []> =
        let line = reader.ReadLine()
        match line with
        | null -> lines
        | _ -> readline reader  (line.Split(',')::lines)

    //grab a file and open it, then return the parsed data
    use chaosfile = new StreamReader(path)
    readline chaosfile []

//a recreation of the above function using a while loop
let ImportDataWhile (path:string) : list<string []> =
    use chaosfile = new StreamReader(path)
    //values ina loop construct must be mutable
    let mutable retval = []
    //loop
    while chaosfile.EndOfStream <> true do
        retval <- chaosfile.ReadLine().Split(',')::retval 
    //return retval by just declaring it
    retval

let CSVlines (path:string) : string seq= 
    seq { use streamreader = new StreamReader(path)
          while not streamreader.EndOfStream do
            yield streamreader.ReadLine() }

let ImportDataSeq (path:string) : string [] list =
    let mutable retval = []
    let sequencer = CSVlines path
    for line in sequencer do
        retval <- line.Split()::retval
    retval

Код C #

using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Text;

namespace CSVparse
{
    public class CSVprocess
    {
        public static List<string[]> ImportDataC(string path)
        {
            List<string[]> retval = new List<string[]>();
            using(StreamReader readfile = new StreamReader(path))
            {
                string line = readfile.ReadLine();
                while (line != null)
                {
                    retval.Add(line.Split());
                    line = readfile.ReadLine();
                }
            } 

           return retval;
        }

        public static List<string[]> ImportDataReadLines(string path)
        {
            List<string[]> retval = new List<string[]>();
            IEnumerable<string> toparse = File.ReadLines(path);

            foreach (string split in toparse)
            {
                retval.Add(split.Split());
            }
            return retval;
        }
    }

}

Обратите внимание на разнообразие реализаций там. Использование итераторов, использование последовательностей, использование оптимизаций хвостовых вызовов, а также циклы на 2 языках ...

Основная проблема заключается в том, что я попадаю на диск, и поэтому некоторые особенности могут быть объяснены этим, я намерен переписать этот код для чтения из потока памяти (что должно быть более последовательным, если я не начинаю менять местами)

Но все, что меня учат / читаю, говорит, что циклы while / for быстрее, чем оптимизации / рекурсия хвостовых вызовов, и каждый фактический тест, который я провожу, говорит об обратном.

Итак, я предполагаю, что мой вопрос: следует ли мне подвергать сомнению общепринятую точку зрения?

Действительно ли рекурсия хвостовых вызовов лучше, чем циклы while в экосистеме .net?

Как это работает в Mono?

7
задан Guy Coder 4 March 2016 в 19:32
поделиться