diff options
Diffstat (limited to 'Makefile')
| -rw-r--r-- | Makefile | 94 |
1 files changed, 94 insertions, 0 deletions
@@ -1,4 +1,6 @@ .PHONY: all build install doc clean html deb pkg bintar sdist +.PHONY: profile-build profile-rgl-time profile-rgl-memory profile-rgl-clean +.PHONY: bench-build bench-rgl bench-rgl-pre-pmcfg bench-rgl-clean # This gets the numeric part of the version from the cabal file VERSION=$(shell sed -ne "s/^version: *\([0-9.]*\).*/\1/p" gf.cabal) @@ -18,6 +20,51 @@ else endif endif +# Profiling configuration. +# +# The profiling targets intentionally use Stack even when the normal build falls +# back to cabal, because Stack's --work-dir makes it easy to keep profiled and +# unprofiled build products separate. The default RGL target is German, which +# is complex and a good compiler stress test; override +# RGL_PROFILE_MODULES or RGL_PROFILE_GF_OPTIONS for different experiments. +PROFILE_STACK_WORK ?= .stack-work-profile +PROFILE_GHC_OPTIONS ?= -fprof-auto -fprof-cafs +PROFILE_DIR ?= $(CURDIR)/profile + +RGL_DIR ?= ../gf-rgl +RGL_PROFILE_DIR ?= $(PROFILE_DIR)/rgl +RGL_PROFILE_GFO_DIR ?= $(RGL_PROFILE_DIR)/gfo +RGL_PROFILE_PGF_DIR ?= $(RGL_PROFILE_DIR)/pgf +RGL_PROFILE_MODULES ?= $(RGL_DIR)/src/german/LangGer.gf +RGL_PROFILE_IMPORT_DIRS ?= $(RGL_DIR)/src/api +RGL_PROFILE_IMPORT_OPTIONS = $(foreach dir,$(RGL_PROFILE_IMPORT_DIRS),-i $(dir)) +RGL_PROFILE_GF_OPTIONS ?= --make --quiet --src --preproc=mkPresent --gf-lib-path=$(RGL_PROFILE_GFO_DIR) --gfo-dir=$(RGL_PROFILE_GFO_DIR) --output-dir=$(RGL_PROFILE_PGF_DIR) --name=RGLProfile $(RGL_PROFILE_IMPORT_OPTIONS) +RGL_PROFILE_GF = stack --stack-yaml $(CURDIR)/stack.yaml --work-dir $(PROFILE_STACK_WORK) exec --profile gf -- + +RGL_TIME_STEM ?= $(RGL_PROFILE_DIR)/rgl-time +RGL_MEMORY_STEM ?= $(RGL_PROFILE_DIR)/rgl-memory +RGL_MEMORY_RTS ?= -hc +RGL_HEAP_SAMPLE_INTERVAL ?= 0.1 + +BENCH_STACK_WORK ?= $(PROFILE_STACK_WORK) +BENCH_PROFILE_FLAGS ?= --profile +BENCH_GHC_OPTIONS ?= $(PROFILE_GHC_OPTIONS) +BENCH_TARGET ?= gf:bench:gf-compiler-bench +BENCH_TASTY_OPTIONS ?= +BENCH_PRE_PMCFG_FLAG ?= --flag gf:pre-pmcfg +BENCH_PRE_PMCFG_STACK_WORK ?= .stack-work-profile-pre-pmcfg + +RGL_BENCH_DIR ?= $(PROFILE_DIR)/rgl-bench +RGL_BENCH_GFO_DIR ?= $(RGL_BENCH_DIR)/gfo +RGL_BENCH_PGF_DIR ?= $(RGL_BENCH_DIR)/pgf +RGL_BENCH_NAME ?= RGLBench +RGL_BENCH_MODULES ?= +RGL_BENCH_IMPORT_DIRS ?= $(RGL_PROFILE_IMPORT_DIRS) $(RGL_DIR)/src/prelude +RGL_BENCH_PRE_PMCFG_DIR ?= $(PROFILE_DIR)/rgl-bench-pre-pmcfg +RGL_BENCH_PRE_PMCFG_NAME ?= RGLBenchPrePmcfg +BENCH_RTS_OPTIONS ?= +RTS -T -RTS +BENCH_STACK = stack --stack-yaml $(CURDIR)/stack.yaml --work-dir $(BENCH_STACK_WORK) + all: build dist/setup-config: gf.cabal Setup.hs WebSetup.hs @@ -28,6 +75,53 @@ endif build: dist/setup-config ${CMD} ${CMD_PFX}build +profile-build: + stack --work-dir $(PROFILE_STACK_WORK) build --profile --ghc-options "$(PROFILE_GHC_OPTIONS)" + +profile-rgl-time: profile-build + @test -n "$(RGL_PROFILE_MODULES)" || { echo "No RGL modules found. Set RGL_DIR or RGL_PROFILE_MODULES."; exit 1; } + @command -v ghc-prof-flamegraph >/dev/null || { echo "Missing ghc-prof-flamegraph."; exit 1; } + rm -rf $(RGL_PROFILE_GFO_DIR) $(RGL_PROFILE_PGF_DIR) + mkdir -p $(RGL_PROFILE_DIR) $(RGL_PROFILE_GFO_DIR) $(RGL_PROFILE_PGF_DIR) + rm -f $(RGL_TIME_STEM).prof $(RGL_TIME_STEM).svg $(RGL_TIME_STEM).log + $(RGL_PROFILE_GF) $(RGL_PROFILE_GF_OPTIONS) $(RGL_PROFILE_MODULES) +RTS -s -p -po$(RGL_TIME_STEM) -RTS > $(RGL_TIME_STEM).log 2>&1 || { tail -n 80 $(RGL_TIME_STEM).log; exit 1; } + ghc-prof-flamegraph $(RGL_TIME_STEM).prof --output $(RGL_TIME_STEM).svg + +profile-rgl-memory: profile-build + @test -n "$(RGL_PROFILE_MODULES)" || { echo "No RGL modules found. Set RGL_DIR or RGL_PROFILE_MODULES."; exit 1; } + @command -v hp2ps >/dev/null || { echo "Missing hp2ps."; exit 1; } + rm -rf $(RGL_PROFILE_GFO_DIR) $(RGL_PROFILE_PGF_DIR) + mkdir -p $(RGL_PROFILE_DIR) $(RGL_PROFILE_GFO_DIR) $(RGL_PROFILE_PGF_DIR) + rm -f $(RGL_MEMORY_STEM).hp $(RGL_MEMORY_STEM).ps $(RGL_MEMORY_STEM).aux $(RGL_MEMORY_STEM).tmp.ps $(RGL_MEMORY_STEM).log + $(RGL_PROFILE_GF) $(RGL_PROFILE_GF_OPTIONS) $(RGL_PROFILE_MODULES) +RTS -s $(RGL_MEMORY_RTS) -i$(RGL_HEAP_SAMPLE_INTERVAL) -po$(RGL_MEMORY_STEM) -RTS > $(RGL_MEMORY_STEM).log 2>&1 || { tail -n 80 $(RGL_MEMORY_STEM).log; exit 1; } + cd $(dir $(RGL_MEMORY_STEM)) && hp2ps $(notdir $(RGL_MEMORY_STEM)).hp + @if command -v gs >/dev/null 2>&1; then \ + gs -q -dNOPAUSE -dBATCH -sOutputFile=$(RGL_MEMORY_STEM).tmp.ps -sDEVICE=ps2write -c "<</Orientation 1>> setpagedevice" -- $(RGL_MEMORY_STEM).ps && mv $(RGL_MEMORY_STEM).tmp.ps $(RGL_MEMORY_STEM).ps; \ + else \ + echo "Missing gs; leaving $(RGL_MEMORY_STEM).ps without orientation fix."; \ + fi + +profile-rgl-clean: + rm -rf $(RGL_PROFILE_DIR) + +bench-build: + $(BENCH_STACK) build $(BENCH_TARGET) --bench --no-run-benchmarks $(BENCH_PROFILE_FLAGS) --ghc-options "$(BENCH_GHC_OPTIONS)" + +bench-rgl: bench-build + @test -d "$(RGL_DIR)" || { echo "Missing RGL_DIR: $(RGL_DIR)"; exit 1; } + rm -rf $(RGL_BENCH_GFO_DIR) $(RGL_BENCH_PGF_DIR) + mkdir -p $(RGL_BENCH_GFO_DIR) $(RGL_BENCH_PGF_DIR) + GF_BENCH_RGL_DIR="$(RGL_DIR)" GF_BENCH_NAME="$(RGL_BENCH_NAME)" GF_BENCH_GFO_DIR="$(RGL_BENCH_GFO_DIR)" GF_BENCH_PGF_DIR="$(RGL_BENCH_PGF_DIR)" GF_BENCH_MODULES="$(RGL_BENCH_MODULES)" GF_BENCH_IMPORT_DIRS="$(RGL_BENCH_IMPORT_DIRS)" $(BENCH_STACK) bench $(BENCH_TARGET) $(BENCH_PROFILE_FLAGS) --ghc-options "$(BENCH_GHC_OPTIONS)" --benchmark-arguments "$(BENCH_TASTY_OPTIONS) $(BENCH_RTS_OPTIONS)"; \ + status=$$?; \ + if test -f gf-compiler-bench.prof; then mv gf-compiler-bench.prof "$(RGL_BENCH_DIR)/gf-compiler-bench.prof"; fi; \ + exit $$status + +bench-rgl-pre-pmcfg: + $(MAKE) bench-rgl BENCH_STACK_WORK="$(BENCH_PRE_PMCFG_STACK_WORK)" RGL_BENCH_DIR="$(RGL_BENCH_PRE_PMCFG_DIR)" RGL_BENCH_NAME="$(RGL_BENCH_PRE_PMCFG_NAME)" BENCH_PROFILE_FLAGS="$(BENCH_PROFILE_FLAGS) $(BENCH_PRE_PMCFG_FLAG)" + +bench-rgl-clean: + rm -rf $(RGL_BENCH_DIR) $(RGL_BENCH_PRE_PMCFG_DIR) + install: ifeq ($(STACK),1) stack install |
