Как с Nix указать зависимости Haskell при включенном профилировании?

Сначала я пытался так:

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

Так что вроде из кеша скачать не получится. Но ничего страшного, если хотя бы я смогу построить профилированные варианты локально.

Могу ли я сделать это как-нибудь, просто немного изменив выражение nix, заданное для -p?

Тогда, когда я писал этот вопрос, я вспомнил этот ресурс: 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 на них, я думаю, это могло бы сработать. Но на данный момент мои познания в никс не так уж далеко. Как я мог это сделать? И действительно ли это правильный путь?


person Wizek    schedule 04.12.2017    source источник
comment
Вероятно, вы можете определить функцию, которая включает свой аргумент, как пакет с профилированием. Вы также можете просто сделать это медленным, повторяющимся способом в файле shell.nix вместо того, чтобы указывать все в командной строке.   -  person chepner    schedule 04.12.2017
comment
Для тех, кто может оказаться здесь от Google: nixos.org/ nixpkgs / manual / # how-to-build-with-profiling-enabled   -  person Răzvan Flavius Panda    schedule 20.04.2018


Ответы (2)


При дальнейшем поиске в nix-repl и некоторых полезных указателях от ElvishJerricco на # reflex-frp на FreeNode я смог сконструировать это, что, похоже, работает:

$ 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'

person Wizek    schedule 04.12.2017
comment
Как оказалось, мне может понадобиться пробраться -fprof-auto где-то там. - person Wizek; 05.12.2017

Я придумал простой подход, над которым работаю, в крупнейшем сообщении в блоге о разработке Haskell с использованием Nix. А пока вот текст только раздела профилирования:

Nix делает это довольно просто. Сначала мы добавляем в ~/.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 Store, и нам придется создавать их заново, если они понадобятся.

Если мы пишем библиотеку, ближайшим исполняемым файлом, который мы могли бы профилировать, был бы наш набор тестов. Для этого:

  • Добавьте -prof и -fprof-auto в параметры GHC нашего теста
  • Регенерировать default.nix
  • Войдите в нашу оболочку профилирования: nix-shell profiling-shell.nix
  • cabal configure --enable-library-profiling --enable-benchmarks
  • cabal build
  • dist/build/projname/projname-bench +RTS -p
  • Посмотрите на созданный projname-bench.prof файл

Основываясь на результатах, мы можем внести изменения в код, удалить параметры профилирования, повторно создать default.nix и протестировать, как обычно, в нашей обычной оболочке Nix Shell.

person Colin Woodbury    schedule 22.01.2018
comment
fosskers.ca/#orgc7fbdab Полагаю, это сообщение в блоге? :) - person Chris Stryczynski; 16.11.2019
comment
@ChrisStryczynski, вот более безопасная ссылка: fosskers.ca/blog/nix-en.html < / а> - person Colin Woodbury; 18.11.2019