Создание нескольких критериев критериев одновременно - PullRequest
0 голосов
/ 06 июня 2018

Этот код компилируется и запускается без проблем:

module Main where

import Criterion.Main

main :: IO ()
main =
  defaultMain
    [env (return $ [1,2])
         (\is ->
            bgroup "group" (benchmarks is))]

timesTwo :: Int -> Int
timesTwo i = 2 * i

benchmarks :: [Int] -> [Benchmark]
benchmarks is = [ bench "foo" $ nf timesTwo (is !! 0)
                , bench "foo" $ nf timesTwo (is !! 1) ]

Тем не менее, если я изменяю функцию benchmarks на

benchmarks :: [Int] -> [Benchmark]
benchmarks is = map (\i -> bench "foo" $ nf timesTwo i) is

, она все равно компилируется, но я получаю эту ошибку времени выполнения:

ghci> main
*** Exception: Criterion atttempted to retrieve a non-existent environment!
        Perhaps you forgot to use lazy pattern matching in a function which
        constructs benchmarks from an environment?
        (see the documentation for `env` for details)

Как мне решить эту проблему?

Как вы можете видеть, Моя цель состоит в том, чтобы отобразить список из полученных из среды, чтобы превратить его всписок Benchmark s , который я могу использовать с Criterion.

Примечание: в конечном итоге я хочу использовать гораздо больше элементов, чем просто два, поэтому кортежи здесь не то, что я хочу.

Ответы [ 2 ]

0 голосов
/ 07 июня 2018

Для бенчмаркинга разных размеров я обычно делаю что-то вроде этого:

module Main (main) where

import Criterion.Main
import System.Random
import Control.Monad

import qualified Data.List
import qualified Data.Sequence

int :: Int -> IO Int
int n = randomRIO (0,n)

benchAtSize :: Int -> Benchmark
benchAtSize n =
    env (replicateM n (int n)) $
    \xs ->
         bgroup (show n)
           [ bench "Data.List"     $ nf Data.List.sort xs
           , bench "Data.Sequence" $ nf (Data.Sequence.sort . Data.Sequence.fromList) xs
           ]

main :: IO ()
main = defaultMain (map benchAtSize [100, 1000, 10000])

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

0 голосов
/ 06 июня 2018

env очень требователен со строгостью.Вы не можете использовать это здесь.Структура эталонных тестов, созданных в env, не может зависеть от среды.Таким образом, среда может использоваться кодом, который сравнивается с , но способ, которым сами отметки организованы, названы и т. Д., Не может его использовать.Это связано с тем, что criterion иногда пропускает _|_ вместо реальной среды, когда он хочет просто проверить структуру бенчмарков, не выполняя их.Когда вы используете !!, организация эталонных тестов дается вручную и остается неизменной, даже если is = _|_:

benchmarks _|_ = [ bench "foo" $ nf timesTwo _|_ -- _|_ !! n = _|_; nf is not strict
                 , bench "foo" $ nf timesTwo _|_ ] -- "bench"s are still there

Но map нарушает это:

benchmarks _|_ = map _etc _|_
               = case _|_ of -- definition of map
                      [] -> []
                      x:xs -> _etc x : map _etc xs
               = _|_ -- benchmark structure gone

Ваша лучшая ставка просто не использует env:

main = do is <- _ -- however you calculate is
          defaultMain $ bgroup "group" $ benchmark is
...