Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

perf build: Reduce pmu-events related copying and mkdirs

When building to an output directory the previous code would remove
files and then copy the source files over.

Each source file copy would have a rule to make its directory. All JSON
for every architecture was considered a source file.

This led to unnecessary copying as a file would be deleted and then the
same file copied again, unnecessary directory making, and copying of
files not used in the build.

A side-effect would be a lot of build messages.

This change makes it so that all computed output files are created and
then compared to all files in the OUTPUT directory.

By filtering out the files that would be copied, unnecessary files can
be determined and then deleted - note, this is a phony target which
would remake the pmu-events.c if always depended upon, and so the
dependency is conditional on there being files to remove.

This has some overhead as the $(OUTPUT)/pmu-events is "find" over rather
than just "rm -fr", but the savings from unnecessary copying, etc.
should make up for this new make overhead.

The copy target just does copying but has a dependency on the directory
it needs being built, avoiding repetitive mkdirs.

The source files for copying only consider the JEVENTS_ARCH unless the
JEVENTS_ARCH is all.

The metric JSON is only generated if appropriate, rather than always
being generated and jevents.py deciding whether or not to use the files.

The mypy and pylint targets are fixed as variable names had changed but
the rules not updated.

The line count of a build with "make -C tools/perf O=/tmp/perf clean all"
prior to this change was 2181 lines, after this change it is 1596
lines.

This is a reduction of 585 lines or about 27%.

The generated pmu-events.c for JEVENTS_ARCH "x86" and "all" were
validated as being identical after this change.

Signed-off-by: Ian Rogers <irogers@google.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@linaro.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Leo Yan <leo.yan@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Ian Rogers and committed by
Arnaldo Carvalho de Melo
36a1b006 4479884d

+151 -70
+151 -70
tools/perf/pmu-events/Build
··· 1 - pmu-events-y += pmu-events.o 2 - JSON = $(shell find pmu-events/arch -name '*.json' -o -name '*.csv') 3 - JSON_DIRS = $(shell find pmu-events/arch -type d) 4 - JDIR_TEST = pmu-events/arch/test 5 - JSON_TEST = $(shell [ -d $(JDIR_TEST) ] && \ 6 - find $(JDIR_TEST) -name '*.json') 7 - JEVENTS_PY = pmu-events/jevents.py 8 - METRIC_PY = pmu-events/metric.py 9 - METRIC_TEST_PY = pmu-events/metric_test.py 10 1 EMPTY_PMU_EVENTS_C = pmu-events/empty-pmu-events.c 2 + # pmu-events.c will be generated by jevents.py or copied from EMPTY_PMU_EVENTS_C 11 3 PMU_EVENTS_C = $(OUTPUT)pmu-events/pmu-events.c 12 - METRIC_TEST_LOG = $(OUTPUT)pmu-events/metric_test.log 13 - TEST_EMPTY_PMU_EVENTS_C = $(OUTPUT)pmu-events/test-empty-pmu-events.c 14 - EMPTY_PMU_EVENTS_TEST_LOG = $(OUTPUT)pmu-events/empty-pmu-events.log 15 - LEGACY_CACHE_PY = pmu-events/make_legacy_cache.py 16 - LEGACY_CACHE_JSON = $(OUTPUT)pmu-events/arch/common/common/legacy-cache.json 4 + pmu-events-y += pmu-events.o 17 5 6 + # pmu-events.c file is generated in the OUTPUT directory so it needs a 7 + # separate rule to depend on it properly 8 + $(OUTPUT)pmu-events/pmu-events.o: $(PMU_EVENTS_C) 9 + $(call rule_mkdir) 10 + $(call if_changed_dep,cc_o_c) 11 + 12 + # Message for $(call echo-cmd,cp), possibly remove the src file from 13 + # the destination to save space in the build log. 14 + quiet_cmd_cp = COPY $(patsubst %$<,%,$@) <- $< 15 + 16 + # --- NO_JEVENTS=1 build --- 17 + ifeq ($(NO_JEVENTS),1) 18 + $(PMU_EVENTS_C): $(EMPTY_PMU_EVENTS_C) 19 + $(call rule_mkdir) 20 + $(Q)$(call echo-cmd,cp)cp $< $@ 21 + else 22 + # --- Regular build --- 23 + 24 + # Setup the JEVENTS_ARCH and JEVENTS_MODEL 18 25 ifeq ($(JEVENTS_ARCH),) 19 26 JEVENTS_ARCH=$(SRCARCH) 20 27 endif 21 28 JEVENTS_MODEL ?= all 22 29 23 - # 24 - # Locate/process JSON files in pmu-events/arch/ 25 - # directory and create tables in pmu-events.c. 26 - # 27 - 28 - ifeq ($(NO_JEVENTS),1) 29 - $(PMU_EVENTS_C): $(EMPTY_PMU_EVENTS_C) 30 - $(call rule_mkdir) 31 - $(Q)$(call echo-cmd,gen)cp $< $@ 30 + # The input json/csv files 31 + SRC_DIR := pmu-events/arch 32 + ifeq ($(JEVENTS_ARCH),all) 33 + SRC_JSON := $(shell find $(SRC_DIR) -name '*.json' -o -name '*.csv') 32 34 else 33 - # Functions to extract the model from a extra-metrics.json or extra-metricgroups.json path. 34 - model_name = $(shell echo $(1)|sed -e 's@.\+/\(.*\)/extra-metric.*\.json@\1@') 35 - vendor_name = $(shell echo $(1)|sed -e 's@.\+/\(.*\)/[^/]*/extra-metric.*\.json@\1@') 36 - 37 - # Copy checked-in json to OUTPUT for generation if it's an out of source build 38 - ifneq ($(OUTPUT),) 39 - # Remove all output directories when any source directory timestamp changes 40 - # so there are no stale deleted files 41 - JSON_DIRS_ROOT = $(OUTPUT)pmu-events/arch/ 42 - $(JSON_DIRS_ROOT): $(JSON_DIRS) 43 - $(Q)$(call echo-cmd,gen)rm -rf $@ 44 - $(Q)mkdir -p $@ 45 - 46 - $(OUTPUT)pmu-events/arch/%: pmu-events/arch/% $(JSON_DIRS_ROOT) 47 - $(call rule_mkdir) 48 - $(Q)$(call echo-cmd,gen)cp $< $@ 35 + SRC_JSON := $(shell find $(SRC_DIR)/common $(SRC_DIR)/test $(SRC_DIR)/$(JEVENTS_ARCH) -name '*.json' -o -name '*.csv') 49 36 endif 50 37 51 - $(LEGACY_CACHE_JSON): $(LEGACY_CACHE_PY) $(JSON_DIRS_ROOT) 38 + # Python to build the generic legacy cache events 39 + LEGACY_CACHE_PY = pmu-events/make_legacy_cache.py 40 + LEGACY_CACHE_JSON = $(OUTPUT)pmu-events/arch/common/common/legacy-cache.json 41 + GEN_JSON = $(LEGACY_CACHE_JSON) 42 + 43 + $(LEGACY_CACHE_JSON): $(LEGACY_CACHE_PY) 52 44 $(call rule_mkdir) 53 45 $(Q)$(call echo-cmd,gen)$(PYTHON) $(LEGACY_CACHE_PY) > $@ 54 46 47 + # Python to generate architectural metrics 55 48 GEN_METRIC_DEPS := pmu-events/metric.py pmu-events/common_metrics.py 49 + # Functions to extract the model from an extra-metrics.json or extra-metricgroups.json path. 50 + model_name = $(shell echo $(1)|sed -e 's@.\+/\(.*\)/extra-metric.*\.json@\1@') 51 + vendor_name = $(shell echo $(1)|sed -e 's@.\+/\(.*\)/[^/]*/extra-metric.*\.json@\1@') 56 52 53 + ifeq ($(JEVENTS_ARCH),$(filter $(JEVENTS_ARCH),x86 all)) 57 54 # Generate AMD Json 58 55 ZENS = $(shell ls -d pmu-events/arch/x86/amdzen*) 59 56 ZEN_METRICS = $(foreach x,$(ZENS),$(OUTPUT)$(x)/extra-metrics.json) 60 57 ZEN_METRICGROUPS = $(foreach x,$(ZENS),$(OUTPUT)$(x)/extra-metricgroups.json) 58 + GEN_JSON += $(ZEN_METRICS) $(ZEN_METRICGROUPS) 61 59 62 60 $(ZEN_METRICS): pmu-events/amd_metrics.py $(GEN_METRIC_DEPS) 63 61 $(call rule_mkdir) ··· 65 67 $(call rule_mkdir) 66 68 $(Q)$(call echo-cmd,gen)$(PYTHON) $< -metricgroups $(call model_name,$@) pmu-events/arch > $@ 67 69 70 + endif 71 + 72 + ifeq ($(JEVENTS_ARCH),$(filter $(JEVENTS_ARCH),arm64 all)) 68 73 # Generate ARM Json 69 74 ARMS = $(shell ls -d pmu-events/arch/arm64/arm/*|grep -v cmn) 70 75 ARM_METRICS = $(foreach x,$(ARMS),$(OUTPUT)$(x)/extra-metrics.json) 71 76 ARM_METRICGROUPS = $(foreach x,$(ARMS),$(OUTPUT)$(x)/extra-metricgroups.json) 77 + GEN_JSON += $(ARM_METRICS) $(ARM_METRICGROUPS) 72 78 73 79 $(ARM_METRICS): pmu-events/arm64_metrics.py $(GEN_METRIC_DEPS) 74 80 $(call rule_mkdir) ··· 82 80 $(call rule_mkdir) 83 81 $(Q)$(call echo-cmd,gen)$(PYTHON) $< -metricgroups $(call vendor_name,$@) $(call model_name,$@) pmu-events/arch > $@ 84 82 83 + endif 84 + 85 + ifeq ($(JEVENTS_ARCH),$(filter $(JEVENTS_ARCH),x86 all)) 85 86 # Generate Intel Json 86 87 INTELS = $(shell ls -d pmu-events/arch/x86/*|grep -v amdzen|grep -v mapfile.csv) 87 88 INTEL_METRICS = $(foreach x,$(INTELS),$(OUTPUT)$(x)/extra-metrics.json) 88 89 INTEL_METRICGROUPS = $(foreach x,$(INTELS),$(OUTPUT)$(x)/extra-metricgroups.json) 90 + GEN_JSON += $(INTEL_METRICS) $(INTEL_METRICGROUPS) 89 91 90 92 $(INTEL_METRICS): pmu-events/intel_metrics.py $(GEN_METRIC_DEPS) 91 93 $(call rule_mkdir) ··· 99 93 $(call rule_mkdir) 100 94 $(Q)$(call echo-cmd,gen)$(PYTHON) $< -metricgroups $(call model_name,$@) pmu-events/arch > $@ 101 95 102 - GEN_JSON = $(patsubst %,$(OUTPUT)%,$(JSON)) \ 103 - $(LEGACY_CACHE_JSON) \ 104 - $(JSON_DIRS) \ 105 - $(ZEN_METRICS) $(ZEN_METRICGROUPS) \ 106 - $(ARM_METRICS) $(ARM_METRICGROUPS) \ 107 - $(INTEL_METRICS) $(INTEL_METRICGROUPS) 96 + endif 97 + 98 + OUT_DIR := $(OUTPUT)pmu-events/arch 99 + 100 + ifeq ($(OUTPUT),) 101 + OUT_JSON := $(SRC_JSON) 102 + ORPHAN_FILES := 103 + else 104 + # Things that need to be built in the OUTPUT directory. Note, ensure 105 + # there is a slash after the directory name so that it matches what 106 + # $(dir) gives in COPY_RULE. 107 + OUT_JSON := $(patsubst $(SRC_DIR)/%,$(OUT_DIR)/%,$(SRC_JSON)) 108 + OUT_DIRS := $(sort $(patsubst %/,%,$(dir $(OUT_JSON)))) 109 + 110 + # Things already in the OUTPUT directory 111 + CUR_OUT_JSON := $(shell [ -d $(OUT_DIR) ] && find $(OUT_DIR) -type f) 112 + 113 + # Things in the OUTPUT directory but shouldn't be there as computed by 114 + # OUT_JSON and GEN_JSON. 115 + ORPHAN_FILES := $(filter-out $(OUT_JSON) $(GEN_JSON),$(CUR_OUT_JSON)) 116 + 117 + # Message for $(call echo-cmd,mkd). There is already a mkdir message 118 + # but it assumes $@ is a file to mkdir the directory for. 119 + quiet_cmd_mkd = MKDIR $@ 120 + 121 + $(OUT_DIRS): 122 + $(Q)$(call echo-cmd,mkd)mkdir -p $@ 123 + 124 + # Explicitly generate rules to copy SRC_JSON files as $(dir) cannot 125 + # apply to $@ in a dependency. Exclude from the copy rules any that 126 + # look like they are copying generated json. This happens as a perf 127 + # build within the tools/perf directory will leave generated json 128 + # files within the tree, these then get picked up by SRC_JSON find. 129 + define COPY_RULE 130 + $(2): $(1) | $(3) 131 + $$(Q)$$(call echo-cmd,cp)cp $(1) $(2) 132 + endef 133 + $(foreach src,$(SRC_JSON), \ 134 + $(eval dest := $(patsubst $(SRC_DIR)/%,$(OUT_DIR)/%,$(src))) \ 135 + $(eval ddir := $(patsubst %/,%,$(dir $(dest)))) \ 136 + $(if $(filter $(dest),$(GEN_JSON)),, \ 137 + $(eval $(call COPY_RULE,$(src),$(dest),$(ddir))) \ 138 + ) \ 139 + ) 140 + 141 + endif # ifneq ($(OUTPUT),) 142 + 143 + JEVENTS_PY = pmu-events/jevents.py 144 + METRIC_PY = pmu-events/metric.py 145 + 146 + # Rule to run the metric test. 147 + METRIC_TEST_PY = pmu-events/metric_test.py 148 + METRIC_TEST_LOG = $(OUTPUT)pmu-events/metric_test.log 108 149 109 150 $(METRIC_TEST_LOG): $(METRIC_TEST_PY) $(METRIC_PY) 110 151 $(call rule_mkdir) 111 152 $(Q)$(call echo-cmd,test)$(PYTHON) $< 2> $@ || (cat $@ && false) 112 153 113 - $(TEST_EMPTY_PMU_EVENTS_C): $(GEN_JSON) $(JSON_TEST) $(JEVENTS_PY) $(METRIC_PY) $(METRIC_TEST_LOG) 154 + # Rule to create then ensure the empty-pmu-events.c is in sync. 155 + TEST_EMPTY_PMU_EVENTS_C = $(OUTPUT)pmu-events/test-empty-pmu-events.c 156 + EMPTY_PMU_EVENTS_TEST_LOG = $(OUTPUT)pmu-events/empty-pmu-events.log 157 + 158 + $(TEST_EMPTY_PMU_EVENTS_C): $(OUT_JSON) $(GEN_JSON) $(JEVENTS_PY) $(METRIC_PY) 114 159 $(call rule_mkdir) 115 160 $(Q)$(call echo-cmd,gen)$(PYTHON) $(JEVENTS_PY) none none $(OUTPUT)pmu-events/arch $@ 116 161 ··· 169 112 $(call rule_mkdir) 170 113 $(Q)$(call echo-cmd,test)diff -u $^ 2> $@ || (cat $@ && false) 171 114 115 + 116 + # Dependencies for jevents.py 117 + JEVENTS_DEPS := $(OUT_JSON) $(GEN_JSON) $(JEVENTS_PY) $(METRIC_PY) $(EMPTY_PMU_EVENTS_TEST_LOG) $(METRIC_TEST_LOG) 118 + 119 + # Rules to run mypy if enabled. 172 120 ifdef MYPY 173 - PMU_EVENTS_PY_TESTS := $(wildcard *.py) 174 - PMU_EVENTS_MYPY_TEST_LOGS := $(JEVENTS_PY_TESTS:%=%.mypy_log) 175 - else 176 - PMU_EVENTS_MYPY_TEST_LOGS := 121 + define MYPY_RULE 122 + $(2): $(1) 123 + $$(Q)$$(call echo-cmd,test)mypy $(1) > $(2) || (cat $(2) && rm $(2) && false) 124 + endef 125 + $(foreach src,$(wildcard pmu-events/*.py), \ 126 + $(eval dest := $(patsubst pmu-events/%,$(OUTPUT)pmu-events/%.mypy_log,$(src))) \ 127 + $(eval $(call MYPY_RULE,$(src),$(dest))) \ 128 + ) 129 + 130 + MYPY_INPUTS := $(wildcard pmu-events/*.py) 131 + MYPY_OUTPUTS := $(patsubst pmu-events/%,$(OUTPUT)pmu-events/%.mypy_log,$(MYPY_INPUTS)) 132 + JEVENTS_DEPS += $(MYPY_OUTPUTS) 177 133 endif 178 134 179 - $(OUTPUT)%.mypy_log: % 180 - $(call rule_mkdir) 181 - $(Q)$(call echo-cmd,test)mypy "$<" > $@ || (cat $@ && rm $@ && false) 182 - 135 + # Rules to run pylint if enabled. 183 136 ifdef PYLINT 184 - PMU_EVENTS_PY_TESTS := $(wildcard *.py) 185 - PMU_EVENTS_PYLINT_TEST_LOGS := $(JEVENTS_PY_TESTS:%=%.pylint_log) 186 - else 187 - PMU_EVENTS_PYLINT_TEST_LOGS := 137 + define PYLINT_RULE 138 + $(2): $(1) 139 + $$(Q)$$(call echo-cmd,test)pylint $(1) > $(2) || (cat $(2) && rm $(2) && false) 140 + endef 141 + $(foreach src,$(wildcard pmu-events/*.py), \ 142 + $(eval dest := $(patsubst pmu-events/%,$(OUTPUT)pmu-events/%.pylint_log,$(src))) \ 143 + $(eval $(call PYLINT_RULE,$(src),$(dest))) \ 144 + ) 145 + 146 + PYLINT_INPUTS := $(wildcard pmu-events/*.py) 147 + PYLINT_OUTPUTS := $(patsubst pmu-events/%,$(OUTPUT)pmu-events/%.pylint_log,$(PYLINT_INPUTS)) 148 + JEVENTS_DEPS += $(PYLINT_OUTPUTS) 188 149 endif 189 150 190 - $(OUTPUT)%.pylint_log: % 191 - $(call rule_mkdir) 192 - $(Q)$(call echo-cmd,test)pylint "$<" > $@ || (cat $@ && rm $@ && false) 151 + # If there are orphaned files remove them. 152 + ifneq ($(strip $(ORPHAN_FILES)),) 153 + .PHONY: prune_orphans 193 154 194 - $(PMU_EVENTS_C): $(GEN_JSON) $(JSON_TEST) $(JEVENTS_PY) $(METRIC_PY) $(METRIC_TEST_LOG) \ 195 - $(EMPTY_PMU_EVENTS_TEST_LOG) $(PMU_EVENTS_MYPY_TEST_LOGS) $(PMU_EVENTS_PYLINT_TEST_LOGS) 196 - $(call rule_mkdir) 197 - $(Q)$(call echo-cmd,gen)$(PYTHON) $(JEVENTS_PY) $(JEVENTS_ARCH) $(JEVENTS_MODEL) $(OUTPUT)pmu-events/arch $@ 155 + # Message for $(call echo-cmd,rm). Generally cleaning files isn't part 156 + # of a build step. 157 + quiet_cmd_rm = RM $^ 158 + 159 + prune_orphans: $(ORPHAN_FILES) 160 + $(Q)$(call echo-cmd,rm)rm -f $^ 161 + 162 + JEVENTS_DEPS += prune_orphans 198 163 endif 199 164 200 - # pmu-events.c file is generated in the OUTPUT directory so it needs a 201 - # separate rule to depend on it properly 202 - $(OUTPUT)pmu-events/pmu-events.o: $(PMU_EVENTS_C) 165 + # Finally, the rule to build pmu-events.c using jevents.py. All test 166 + # and inputs are dependencies. 167 + $(PMU_EVENTS_C): $(JEVENTS_DEPS) 203 168 $(call rule_mkdir) 204 - $(call if_changed_dep,cc_o_c) 169 + $(Q)$(call echo-cmd,gen)$(PYTHON) $(JEVENTS_PY) $(JEVENTS_ARCH) $(JEVENTS_MODEL) $(OUT_DIR) $@ 170 + 171 + endif # ifeq ($(NO_JEVENTS),1)