尝试对 haskell 进行基准测试时找不到模块“Criterion.Main”
Could not find module ‘Criterion.Main’ when trying to benchmark haskell
我无法使 Criterion 正常工作。我遵循教程 here,通过执行以下操作安装 Criterion。
cabal update
cabal install -j --disable-tests criterion
当我尝试 ghc -O Fibber.hs
或 ghc -O --make Fibber
时,我收到错误消息
[1 of 1] Compiling Main ( Fibber.hs, Fibber.o )
Fibber.hs:1:1: error:
Could not find module ‘Criterion.Main’
Use -v (or `:set -v` in ghci) to see a list of the files searched for.
|
1 | import Criterion.Main
|
我希望测试和诊断是 运行 并输出到控制台和一个 HTML 文件。
尝试使用堆栈会导致相同的错误。我之前用自己的模块解决了这个问题,方法是将它们包含在我的 .cabal
文件中,就像这样
library
Exposed-Modules:
Geometry.Sphere
Geometry.Cuboid
Geometry.Cube
但是在这种情况下这样做并不能解决问题。我也试过 this SO solution,但没有用。我收到基本上相同的错误:
/Users/me/Documents/projects/haskell/performance/criterion-1.5.13.0/Criterion/Fibber.hs:3:1: error:
Could not find module ‘CriterionMain’
Use -v (or `:set -v` in ghci) to see a list of the files searched for.
|
3 | import CriterionMain
| ^^^^^^^^^^^^^^^^^^^^
Received ExitFailure 1 when running
Raw command: /Users/me/.stack/programs/aarch64-osx/ghc-9.2.2/bin/ghc-9.2.2 -i -i/Users/me/Documents/projects/haskell/performance/criterion-1.5.13.0/Criterion/ -hide-all-packages -fdiagnostics-color=always -packagebase -O2 /Users/me/Documents/projects/haskell/performance/criterion-1.5.13.0/Criterion/Fibber.hs
Run from: /Users/me/Documents/projects/haskell/performance/criterion-1.5.13.0/Criterion/
Standard output:
[1 of 1] Compiling Main ( /Users/me/Documents/projects/haskell/performance/criterion-1.5.13.0/Criterion/Fibber.hs, /Users/me/Documents/projects/haskell/performance/criterion-1.5.13.0/Criterion/Fibber.o )
这是我的 .cabal
文件。
name: criterion
version: 1.5.13.0
synopsis: Robust, reliable performance measurement and analysis
license: BSD3
license-file: LICENSE
author: Bryan O'Sullivan <bos@serpentine.com>
maintainer: Ryan Scott <ryan.gl.scott@gmail.com>
copyright: 2009-2016 Bryan O'Sullivan and others
category: Development, Performance, Testing, Benchmarking
homepage: http://www.serpentine.com/criterion
bug-reports: https://github.com/haskell/criterion/issues
build-type: Simple
cabal-version: >= 1.10
extra-source-files:
README.markdown
changelog.md
examples/LICENSE
examples/*.cabal
examples/*.hs
tested-with:
GHC==7.4.2,
GHC==7.6.3,
GHC==7.8.4,
GHC==7.10.3,
GHC==8.0.2,
GHC==8.2.2,
GHC==8.4.4,
GHC==8.6.5,
GHC==8.8.4,
GHC==8.10.7,
GHC==9.0.2,
GHC==9.2.1
data-files:
templates/*.css
templates/*.tpl
templates/*.js
description:
This library provides a powerful but simple way to measure software
performance. It provides both a framework for executing and
analysing benchmarks and a set of driver functions that makes it
easy to build and run benchmarks, and to analyse their results.
.
The fastest way to get started is to read the
<http://www.serpentine.com/criterion/tutorial.html online tutorial>,
followed by the documentation and examples in the "Criterion.Main"
module.
.
For examples of the kinds of reports that criterion generates, see
<http://www.serpentine.com/criterion the home page>.
flag fast
description: compile without optimizations
default: False
manual: True
flag embed-data-files
description: Embed the data files in the binary for a relocatable executable.
(Warning: This will increase the executable size significantly.)
default: False
manual: True
library
exposed-modules:
Criterion
Criterion.Analysis
Criterion.IO
Criterion.IO.Printf
Criterion.Internal
Criterion.Main
Criterion.Main.Options
Criterion.Monad
Criterion.Report
Criterion.Types
other-modules:
Criterion.Main.Options.Internal
Criterion.Monad.Internal
other-modules:
Paths_criterion
build-depends:
-- TODO: Eventually, we should bump the lower version bounds to >=2 so that
-- we can remove some CPP in Criterion.Report. See #247.
aeson >= 1 && < 2.1,
ansi-wl-pprint >= 0.6.7.2,
base >= 4.5 && < 5,
base-compat-batteries >= 0.10 && < 0.13,
binary >= 0.5.1.0,
binary-orphans >= 1.0.1 && < 1.1,
bytestring >= 0.9 && < 1.0,
cassava >= 0.3.0.0,
code-page,
containers,
criterion-measurement >= 0.1.1.0 && < 0.2,
deepseq >= 1.1.0.0,
directory,
exceptions >= 0.8.2 && < 0.11,
filepath,
Glob >= 0.7.2,
microstache >= 1.0.1 && < 1.1,
js-chart >= 2.9.4 && < 3,
mtl >= 2,
mwc-random >= 0.8.0.3,
-- TODO: Depend on optparse-applicative-0.17 as the minimum (see #258)
optparse-applicative >= 0.13 && < 0.18,
parsec >= 3.1.0,
statistics >= 0.14 && < 0.16,
text >= 0.11,
time,
transformers,
transformers-compat >= 0.6.4,
vector >= 0.7.1,
vector-algorithms >= 0.4
if impl(ghc < 7.6)
build-depends:
ghc-prim
if !impl(ghc >= 8.0)
build-depends:
fail == 4.9.*,
semigroups
default-language: Haskell2010
ghc-options: -Wall -funbox-strict-fields
if impl(ghc >= 6.8)
ghc-options: -fwarn-tabs
if flag(fast)
ghc-options: -O0
else
ghc-options: -O2
if flag(embed-data-files)
other-modules: Criterion.EmbeddedData
build-depends: file-embed < 0.1,
template-haskell
cpp-options: "-DEMBED"
Executable criterion-report
Default-Language: Haskell2010
GHC-Options: -Wall -rtsopts
Main-Is: Report.hs
Other-Modules: Options
Paths_criterion
Hs-Source-Dirs: app
Build-Depends:
base,
base-compat-batteries,
criterion,
optparse-applicative >= 0.13
if impl(ghc < 7.6)
build-depends:
ghc-prim
if !impl(ghc >= 8.0)
build-depends:
semigroups
test-suite sanity
type: exitcode-stdio-1.0
hs-source-dirs: tests
main-is: Sanity.hs
default-language: Haskell2010
ghc-options: -Wall -rtsopts
if flag(fast)
ghc-options: -O0
else
ghc-options: -O2
build-depends:
HUnit,
base,
bytestring,
criterion,
deepseq,
tasty,
tasty-hunit
test-suite tests
type: exitcode-stdio-1.0
hs-source-dirs: tests
main-is: Tests.hs
default-language: Haskell2010
other-modules: Properties
ghc-options:
-Wall -threaded -O0 -rtsopts
build-depends:
QuickCheck >= 2.4,
base,
base-compat-batteries,
criterion,
statistics,
HUnit,
tasty,
tasty-hunit,
tasty-quickcheck,
vector,
aeson
test-suite cleanup
type: exitcode-stdio-1.0
hs-source-dirs: tests
default-language: Haskell2010
main-is: Cleanup.hs
ghc-options:
-Wall -threaded -O0 -rtsopts
build-depends:
HUnit,
base,
base-compat,
bytestring,
criterion,
deepseq,
directory,
tasty,
tasty-hunit
source-repository head
type: git
location: https://github.com/haskell/criterion.git
一种选择是使用 dependency-solved REPL。
% cabal repl --build-depends criterion
> :l Fibber.hs
另一个是创建一个 cabal 包。
% mkdir Fibber
% mv Fibber.hs Fibber
% cd Fibber
% cabal init
<follow prompts, and say you're building an executable with filename Fibber.hs>
% vi Fibber.cabal
<add criterion to the build-depends: stanza>
% cabal run Fibber # or whatever executable name you gave it in the cabal init step
后者的一个优点是,当您发现额外的依赖项时,您可以将所有依赖项记录在一个文件中,而不必每次开始时都记住传递所有依赖项 cabal repl
.另一个是您的代码将被编译,而不是被解释;对于性能测试相当重要,如果您需要标准,这大概就是您正在做的事情!
5 分钟 Cabal 解释
只是对 cabal
工作原理的简短而非完整的解释,以便您理解错误。
一个项目由组件组成:库和“运行nables”(为便于解释而命名)。每个组件在 build-depends
标签下都有 自己的 组依赖项。
库没有入口点,因此它们不需要 main
函数,也不需要指定 main-is
。 cabal 文件只有 one public library,这是包的名称,在文件顶部标记为 name
。您可以拥有内部库,但那是另一个话题。在 criterion
的 cabal 文件中,您会看到:
name
是criterion
(第一行)
library
标签下的库构建配置。 (依赖项、暴露的模块等...)
Runnables 确实需要一个 main
函数和一个标记为 main-is
的模块。 Runnables 可以是可执行文件、测试套件或基准测试。 AFAIK,将 运行nable 标记为其中之一,只会影响通过命令 cabal
compiles/install 它们的方式:cabal build
、cabal run
、cabal test
, cabal bench
, 等等... 例如 cabal build
将编译(默认情况下)库组件和可执行组件,每个可执行文件生成一个二进制文件,但 cabal test
将编译库组件和测试组件,然后 运行 测试。理论上你可以使用 Criterion.Main.defaultMain
作为普通可执行文件的主要功能(在 cabal 文件中定义为 en 可执行组件),在这种情况下,cabal 将生成一个独立的 exe,它将 运行 执行基准.
在 criterion
的 cabal 文件中,您在可执行和三个测试套件中看到:
app
文件夹下名为 criterion-report
的可执行文件
- 测试套件
sanity
、test
和 cleanup
在 test
文件夹下,每个都有不同的主要文件
每个组件都有不同的依赖集,特别是,它们都依赖于 criterion
library 这是在同一个 cabal 文件中定义的组件在 library
部分下,如上所述。
那么我的错误是怎么回事?
所以本质上,您希望 Fibber.hs
文件是一个“运行nable”文件,作为独立的二进制文件或作为项目中的基准套件。因此,您需要根据需要将其添加到 cabal 文件中。作为建议,避免将其添加到 criterion 的 cabal 文件中,否则您将从源代码编译 criterion。按照@DanielWagner 的回答并创建一个新项目,其中 Fibber.hs
是一个主文件,并将 criterion
添加到其依赖项中,或者使用 dependency-repl 替代项。
我无法使 Criterion 正常工作。我遵循教程 here,通过执行以下操作安装 Criterion。
cabal update
cabal install -j --disable-tests criterion
当我尝试 ghc -O Fibber.hs
或 ghc -O --make Fibber
时,我收到错误消息
[1 of 1] Compiling Main ( Fibber.hs, Fibber.o )
Fibber.hs:1:1: error:
Could not find module ‘Criterion.Main’
Use -v (or `:set -v` in ghci) to see a list of the files searched for.
|
1 | import Criterion.Main
|
我希望测试和诊断是 运行 并输出到控制台和一个 HTML 文件。
尝试使用堆栈会导致相同的错误。我之前用自己的模块解决了这个问题,方法是将它们包含在我的 .cabal
文件中,就像这样
library
Exposed-Modules:
Geometry.Sphere
Geometry.Cuboid
Geometry.Cube
但是在这种情况下这样做并不能解决问题。我也试过 this SO solution,但没有用。我收到基本上相同的错误:
/Users/me/Documents/projects/haskell/performance/criterion-1.5.13.0/Criterion/Fibber.hs:3:1: error:
Could not find module ‘CriterionMain’
Use -v (or `:set -v` in ghci) to see a list of the files searched for.
|
3 | import CriterionMain
| ^^^^^^^^^^^^^^^^^^^^
Received ExitFailure 1 when running
Raw command: /Users/me/.stack/programs/aarch64-osx/ghc-9.2.2/bin/ghc-9.2.2 -i -i/Users/me/Documents/projects/haskell/performance/criterion-1.5.13.0/Criterion/ -hide-all-packages -fdiagnostics-color=always -packagebase -O2 /Users/me/Documents/projects/haskell/performance/criterion-1.5.13.0/Criterion/Fibber.hs
Run from: /Users/me/Documents/projects/haskell/performance/criterion-1.5.13.0/Criterion/
Standard output:
[1 of 1] Compiling Main ( /Users/me/Documents/projects/haskell/performance/criterion-1.5.13.0/Criterion/Fibber.hs, /Users/me/Documents/projects/haskell/performance/criterion-1.5.13.0/Criterion/Fibber.o )
这是我的 .cabal
文件。
name: criterion
version: 1.5.13.0
synopsis: Robust, reliable performance measurement and analysis
license: BSD3
license-file: LICENSE
author: Bryan O'Sullivan <bos@serpentine.com>
maintainer: Ryan Scott <ryan.gl.scott@gmail.com>
copyright: 2009-2016 Bryan O'Sullivan and others
category: Development, Performance, Testing, Benchmarking
homepage: http://www.serpentine.com/criterion
bug-reports: https://github.com/haskell/criterion/issues
build-type: Simple
cabal-version: >= 1.10
extra-source-files:
README.markdown
changelog.md
examples/LICENSE
examples/*.cabal
examples/*.hs
tested-with:
GHC==7.4.2,
GHC==7.6.3,
GHC==7.8.4,
GHC==7.10.3,
GHC==8.0.2,
GHC==8.2.2,
GHC==8.4.4,
GHC==8.6.5,
GHC==8.8.4,
GHC==8.10.7,
GHC==9.0.2,
GHC==9.2.1
data-files:
templates/*.css
templates/*.tpl
templates/*.js
description:
This library provides a powerful but simple way to measure software
performance. It provides both a framework for executing and
analysing benchmarks and a set of driver functions that makes it
easy to build and run benchmarks, and to analyse their results.
.
The fastest way to get started is to read the
<http://www.serpentine.com/criterion/tutorial.html online tutorial>,
followed by the documentation and examples in the "Criterion.Main"
module.
.
For examples of the kinds of reports that criterion generates, see
<http://www.serpentine.com/criterion the home page>.
flag fast
description: compile without optimizations
default: False
manual: True
flag embed-data-files
description: Embed the data files in the binary for a relocatable executable.
(Warning: This will increase the executable size significantly.)
default: False
manual: True
library
exposed-modules:
Criterion
Criterion.Analysis
Criterion.IO
Criterion.IO.Printf
Criterion.Internal
Criterion.Main
Criterion.Main.Options
Criterion.Monad
Criterion.Report
Criterion.Types
other-modules:
Criterion.Main.Options.Internal
Criterion.Monad.Internal
other-modules:
Paths_criterion
build-depends:
-- TODO: Eventually, we should bump the lower version bounds to >=2 so that
-- we can remove some CPP in Criterion.Report. See #247.
aeson >= 1 && < 2.1,
ansi-wl-pprint >= 0.6.7.2,
base >= 4.5 && < 5,
base-compat-batteries >= 0.10 && < 0.13,
binary >= 0.5.1.0,
binary-orphans >= 1.0.1 && < 1.1,
bytestring >= 0.9 && < 1.0,
cassava >= 0.3.0.0,
code-page,
containers,
criterion-measurement >= 0.1.1.0 && < 0.2,
deepseq >= 1.1.0.0,
directory,
exceptions >= 0.8.2 && < 0.11,
filepath,
Glob >= 0.7.2,
microstache >= 1.0.1 && < 1.1,
js-chart >= 2.9.4 && < 3,
mtl >= 2,
mwc-random >= 0.8.0.3,
-- TODO: Depend on optparse-applicative-0.17 as the minimum (see #258)
optparse-applicative >= 0.13 && < 0.18,
parsec >= 3.1.0,
statistics >= 0.14 && < 0.16,
text >= 0.11,
time,
transformers,
transformers-compat >= 0.6.4,
vector >= 0.7.1,
vector-algorithms >= 0.4
if impl(ghc < 7.6)
build-depends:
ghc-prim
if !impl(ghc >= 8.0)
build-depends:
fail == 4.9.*,
semigroups
default-language: Haskell2010
ghc-options: -Wall -funbox-strict-fields
if impl(ghc >= 6.8)
ghc-options: -fwarn-tabs
if flag(fast)
ghc-options: -O0
else
ghc-options: -O2
if flag(embed-data-files)
other-modules: Criterion.EmbeddedData
build-depends: file-embed < 0.1,
template-haskell
cpp-options: "-DEMBED"
Executable criterion-report
Default-Language: Haskell2010
GHC-Options: -Wall -rtsopts
Main-Is: Report.hs
Other-Modules: Options
Paths_criterion
Hs-Source-Dirs: app
Build-Depends:
base,
base-compat-batteries,
criterion,
optparse-applicative >= 0.13
if impl(ghc < 7.6)
build-depends:
ghc-prim
if !impl(ghc >= 8.0)
build-depends:
semigroups
test-suite sanity
type: exitcode-stdio-1.0
hs-source-dirs: tests
main-is: Sanity.hs
default-language: Haskell2010
ghc-options: -Wall -rtsopts
if flag(fast)
ghc-options: -O0
else
ghc-options: -O2
build-depends:
HUnit,
base,
bytestring,
criterion,
deepseq,
tasty,
tasty-hunit
test-suite tests
type: exitcode-stdio-1.0
hs-source-dirs: tests
main-is: Tests.hs
default-language: Haskell2010
other-modules: Properties
ghc-options:
-Wall -threaded -O0 -rtsopts
build-depends:
QuickCheck >= 2.4,
base,
base-compat-batteries,
criterion,
statistics,
HUnit,
tasty,
tasty-hunit,
tasty-quickcheck,
vector,
aeson
test-suite cleanup
type: exitcode-stdio-1.0
hs-source-dirs: tests
default-language: Haskell2010
main-is: Cleanup.hs
ghc-options:
-Wall -threaded -O0 -rtsopts
build-depends:
HUnit,
base,
base-compat,
bytestring,
criterion,
deepseq,
directory,
tasty,
tasty-hunit
source-repository head
type: git
location: https://github.com/haskell/criterion.git
一种选择是使用 dependency-solved REPL。
% cabal repl --build-depends criterion
> :l Fibber.hs
另一个是创建一个 cabal 包。
% mkdir Fibber
% mv Fibber.hs Fibber
% cd Fibber
% cabal init
<follow prompts, and say you're building an executable with filename Fibber.hs>
% vi Fibber.cabal
<add criterion to the build-depends: stanza>
% cabal run Fibber # or whatever executable name you gave it in the cabal init step
后者的一个优点是,当您发现额外的依赖项时,您可以将所有依赖项记录在一个文件中,而不必每次开始时都记住传递所有依赖项 cabal repl
.另一个是您的代码将被编译,而不是被解释;对于性能测试相当重要,如果您需要标准,这大概就是您正在做的事情!
5 分钟 Cabal 解释
只是对 cabal
工作原理的简短而非完整的解释,以便您理解错误。
一个项目由组件组成:库和“运行nables”(为便于解释而命名)。每个组件在 build-depends
标签下都有 自己的 组依赖项。
库没有入口点,因此它们不需要 main
函数,也不需要指定 main-is
。 cabal 文件只有 one public library,这是包的名称,在文件顶部标记为 name
。您可以拥有内部库,但那是另一个话题。在 criterion
的 cabal 文件中,您会看到:
name
是criterion
(第一行)library
标签下的库构建配置。 (依赖项、暴露的模块等...)
Runnables 确实需要一个 main
函数和一个标记为 main-is
的模块。 Runnables 可以是可执行文件、测试套件或基准测试。 AFAIK,将 运行nable 标记为其中之一,只会影响通过命令 cabal
compiles/install 它们的方式:cabal build
、cabal run
、cabal test
, cabal bench
, 等等... 例如 cabal build
将编译(默认情况下)库组件和可执行组件,每个可执行文件生成一个二进制文件,但 cabal test
将编译库组件和测试组件,然后 运行 测试。理论上你可以使用 Criterion.Main.defaultMain
作为普通可执行文件的主要功能(在 cabal 文件中定义为 en 可执行组件),在这种情况下,cabal 将生成一个独立的 exe,它将 运行 执行基准.
在 criterion
的 cabal 文件中,您在可执行和三个测试套件中看到:
app
文件夹下名为criterion-report
的可执行文件- 测试套件
sanity
、test
和cleanup
在test
文件夹下,每个都有不同的主要文件
每个组件都有不同的依赖集,特别是,它们都依赖于 criterion
library 这是在同一个 cabal 文件中定义的组件在 library
部分下,如上所述。
那么我的错误是怎么回事?
所以本质上,您希望 Fibber.hs
文件是一个“运行nable”文件,作为独立的二进制文件或作为项目中的基准套件。因此,您需要根据需要将其添加到 cabal 文件中。作为建议,避免将其添加到 criterion 的 cabal 文件中,否则您将从源代码编译 criterion。按照@DanielWagner 的回答并创建一个新项目,其中 Fibber.hs
是一个主文件,并将 criterion
添加到其依赖项中,或者使用 dependency-repl 替代项。