使用Nix,如何在启用性能分析的情况下指定Haskell依赖项?

时间:2017-12-04 15:05:10

标签: haskell nix

我最初是这样想的:

nix-shell -p "haskell.packages.ghc821.ghcWithPackages (p: with p; [text hspec lens])" -j4 --run 'ghc Main.hs -prof

然后GHC告诉我

Main.hs:4:1: error:
    Could not find module ‘Control.Lens’
    Perhaps you haven't installed the profiling libraries for package ‘lens-4.15.4’?
    Use -v to see a list of the files searched for.

在网上搜索我发现了这个:https://github.com/NixOS/nixpkgs/issues/22340

所以我似乎无法从缓存中下载。但是没关系,如果至少我可以在本地构建配置文件变种。

我可以通过稍微修改给予-p的nix表达式以某种方式做到这一点吗?

然后在写这个问题时,我记得这个资源:https://github.com/NixOS/nixpkgs/blob/bd6ba7/pkgs/development/haskell-modules/lib.nix

我找到了enableLibraryProfiling。所以我试过了:

nix-shell -p "haskell.packages.ghc821.ghcWithPackages (p: with p; [text hspec (haskell.lib.enableLibraryProfiling lens)])" -j4 --run 'ghc Main.hs -prof'

让我遇到了一个新错误:

src/Control/Lens/Internal/Getter.hs:26:1: error:
    Could not find module ‘Data.Functor.Contravariant’
    Perhaps you haven't installed the profiling libraries for package ‘contravariant-1.4’?
    Use -v to see a list of the files searched for.
   |
26 | import Data.Functor.Contravariant
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

因此,如果我可以将所有包映射到它们上的enableLibraryProfiling,那么我想这可行。但是我的nix知识目前并没有完全延伸到目前为止。我怎么能这样做?这甚至是正确的追求途径吗?

2 个答案:

答案 0 :(得分:2)

随着nix-repl中的$ nix-shell -p "(haskell.packages.ghc821.extend (self: super: {mkDerivation = expr: super.mkDerivation (expr // { enableLibraryProfiling = true; });})).ghcWithPackages (p: with p; [text hspec lens])" -j4 --run 'ghc Main.hs -prof'进一步窥探,以及来自FreeNode的#reflex-frp的ElvishJerricco的一些有用的指示,我能够构建它,这似乎有效:

try

答案 1 :(得分:0)

我想出了一个简单的方法,我正在使用Nix进行关于Haskell开发的最大博客文章。现在,这里只是分析部分的文本:

尼克斯相当容易。首先,我们将以下内容添加到~/.config/nixpkgs/config.nix

{
  packageOverrides = super: let self = super.pkgs; in
  {
    profiledHaskellPackages = self.haskellPackages.override {
      overrides = self: super: {
        mkDerivation = args: super.mkDerivation (args // {
          enableLibraryProfiling = true;
        });
      };
    };
  };
}

现在,在我们想要分析的项目中,我们创建了一个新的profiling-shell.nix

let nixpkgs = import <nixpkgs> {};
    orig = nixpkgs.pkgs.profiledHaskellPackages.callPackage ./default.nix {};
in (nixpkgs.pkgs.haskell.lib.doBenchmark orig).env

与我们的普通shell.nix几乎完全相同,但我们刚刚全局定义的profiledHaskellPackages的使用除外。现在,nix-shell profiling-shell.nix的调用将在项目中重建每个依赖项,并启用分析。第一次这样做需要很长时间。幸运的是,这并没有破坏我们的Nix商店 - 一个香草nix-shell似乎确实再次呈现我们的常规依赖,没有重新下载或重建。

警告: nix-collect-garbage -d将从我们的Nix商店中删除所有自定义构建的库,如果需要,我们必须再次构建它们。

如果我们正在编写一个库,那么我们可以分析的最接近的可执行文件将是我们的基准套件。要做到这一点:

  • -prof-fprof-auto添加到我们的基准GHC选项
  • 重新生成default.nix
  • 输入我们的分析shell:nix-shell profiling-shell.nix
  • cabal configure --enable-library-profiling --enable-benchmarks
  • cabal build
  • dist/build/projname/projname-bench +RTS -p
  • 查看生成的projname-bench.prof文件

根据结果,我们可以在正常的Nix Shell中进行代码更改,删除分析选项,重新生成default.nix和基准。