Merge lp:~jtv/launchpad/parallel-make into lp:launchpad

Proposed by Jeroen T. Vermeulen on 2010-11-17
Status: Merged
Approved by: Jeroen T. Vermeulen on 2010-11-18
Approved revision: no longer in the source branch.
Merged at revision: 11937
Proposed branch: lp:~jtv/launchpad/parallel-make
Merge into: lp:launchpad
Diff against target: 163 lines (+38/-29)
1 file modified
Makefile (+38/-29)
To merge this branch: bzr merge lp:~jtv/launchpad/parallel-make
Reviewer Review Type Date Requested Status
Edwin Grubbs (community) code 2010-11-17 Approve on 2010-11-17
Benji York (community) code* Approve on 2010-11-17
Review via email: mp+41108@code.launchpad.net

Commit Message

[r=benji,edwin-grubbs][ui=none][no-qa] Support "make -j2"

Description of the Change

= Parallel make =

This fixes the Makefile so that the default target (or "build") can be built in parallel. So instead of "make" you can do "make -j2" and get a nice speedup: on my system right after a "make clean" it takes the build time from 2:43 to 1:32. Should be a welcome change.

What changes? A single buildout run in the makefile produces bin/py and a bunch of other files. But "make" isn't aware that there's no point to running two buildout instances at once, and indeed it's likely to break.

So I channeled all the files produced by buildout through a single virtual target. Now "make" realizes when it's about to run two buildout instances in parallel that they are actually producing the same target—and wait for the existing run to complete instead of starting a redundant one.

(Actually I had to start out with completing dependencies on bin/py, because not all targets that used it depended on it. These things become more noticeable when you run parallel builds.)

The good news is that the build parallelizes almost perfectly to two processes; the bad news is that that's where the ride ends. This is because one single-process job, the generation of WADL files, takes up just about half the build time. With two processors, the two halvse will complete almost simultaneously at just over half the single-process build time. Adding a third CPU won't help the WADL target, and so can't do much for overall build time. At best it gets you to the point where everything waits for that one big job a little faster. On my dual-core SMT laptop, a third process even slows the build down a little.

Jeroen

To post a comment you must log in.
Benji York (benji) wrote :

This branch looks good. Edwin, my review mentor, will also be reviewing this branch.

The transformation you applied is straightforward. (And welcome, my first day working on LP I ran into this issue).

It's probably not worth adding, because changes are rare, but for completeness I'll note that the buildout_bin rule has an unlisted dependency: buildout.cfg uses template files in buildout-templates (which at the moment is just _pythonpath.py.in).

review: Approve (code*)
Jeroen T. Vermeulen (jtv) wrote :

Thanks. I'm tempted to add that dependency right now, but a quick glance doesn't tell me enough to see how it fits in so I'll leave that for someone else who does see it.

Edwin Grubbs (edwin-grubbs) wrote :

Jeroen,

This branch looks good. Can you add the dependencies that Benji asked for, and next time, can you submit a really difficult branch for Benji to review so he gets more practice? Oh wait, that means I have to review it, too. Nevermind.

-Edwin

review: Approve (code)
Jeroen T. Vermeulen (jtv) wrote :

I added the dependency, and broke some over-length lines because, surprisingly, "make lint" also checks the makefile!

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Makefile'
2--- Makefile 2010-11-02 01:34:05 +0000
3+++ Makefile 2010-11-18 04:52:18 +0000
4@@ -45,6 +45,8 @@
5 bin/start_librarian bin/stxdocs bin/tags bin/test bin/tracereport \
6 bin/twistd bin/update-download-cache bin/windmill
7
8+BUILDOUT_TEMPLATES = buildout-templates/_pythonpath.py.in
9+
10 # DO NOT ALTER : this should just build by default
11 default: inplace
12
13@@ -55,10 +57,10 @@
14 newsampledata:
15 $(MAKE) -C database/schema newsampledata
16
17-hosted_branches: $(PY)
18+hosted_branches: buildout_bin
19 $(PY) ./utilities/make-dummy-hosted-branches
20
21-$(API_INDEX): $(BZR_VERSION_INFO)
22+$(API_INDEX): $(BZR_VERSION_INFO) buildout_bin
23 mkdir -p $(APIDOC_DIR).tmp
24 LPCONFIG=$(LPCONFIG) $(PY) ./utilities/create-lp-wadl-and-apidoc.py --force "$(WADL_TEMPLATE)"
25 mv $(APIDOC_DIR).tmp $(APIDOC_DIR)
26@@ -66,12 +68,12 @@
27 apidoc: compile $(API_INDEX)
28
29 # Run by PQM.
30-check_merge: $(PY)
31+check_merge: buildout_bin
32 [ `PYTHONPATH= bzr status -S database/schema/ | \
33 grep -v "\(^P\|pending\|security.cfg\|Makefile\|unautovacuumable\|_pythonpath.py\)" | wc -l` -eq 0 ]
34 ${PY} lib/canonical/tests/test_no_conflict_marker.py
35
36-check_db_merge: $(PY)
37+check_db_merge: buildout_bin
38 ${PY} lib/canonical/tests/test_no_conflict_marker.py
39
40 check_config: build
41@@ -109,16 +111,16 @@
42 ${PY} -t ./test_on_merge.py $(VERBOSITY) $(TESTOPTS) \
43 --layer=MailmanLayer
44
45-lint: ${PY}
46+lint: buildout_bin
47 @bash ./bin/lint.sh
48
49-lint-verbose: ${PY}
50+lint-verbose: buildout_bin
51 @bash ./bin/lint.sh -v
52
53-xxxreport: $(PY)
54+xxxreport: buildout_bin
55 ${PY} -t ./utilities/xxxreport.py -f csv -o xxx-report.csv ./
56
57-check-configs: $(PY)
58+check-configs: buildout_bin
59 ${PY} utilities/check-configs.py
60
61 pagetests: build
62@@ -140,12 +142,14 @@
63 ${SHHH} bin/sprite-util create-image
64
65 jsbuild_lazr: bin/jsbuild
66- # We absolutely do not want to include the lazr.testing module and its
67- # jsTestDriver test harness modifications in the lazr.js and launchpad.js
68- # roll-up files. They fiddle with built-in functions! See Bug 482340.
69- ${SHHH} bin/jsbuild $(JSFLAGS) -b $(LAZR_BUILT_JS_ROOT) -x testing/ -c $(LAZR_BUILT_JS_ROOT)/yui
70+ # We absolutely do not want to include the lazr.testing module and
71+ # its jsTestDriver test harness modifications in the lazr.js and
72+ # launchpad.js roll-up files. They fiddle with built-in functions!
73+ # See Bug 482340.
74+ ${SHHH} bin/jsbuild $(JSFLAGS) -b $(LAZR_BUILT_JS_ROOT) -x testing/ \
75+ -c $(LAZR_BUILT_JS_ROOT)/yui
76
77-jsbuild: jsbuild_lazr bin/jsbuild bin/jssize
78+jsbuild: jsbuild_lazr bin/jsbuild bin/jssize buildout_bin
79 ${SHHH} bin/jsbuild \
80 $(JSFLAGS) \
81 -n launchpad \
82@@ -173,12 +177,12 @@
83 @exit 1
84 endif
85
86-buildonce_eggs: $(PY)
87+buildonce_eggs: buildout_bin
88 find eggs -name '*.pyc' -exec rm {} \;
89
90 # The download-cache dependency comes *before* eggs so that developers get the
91-# warning before the eggs directory is made. The target for the eggs directory
92-# is only there for deployment convenience.
93+# warning before the eggs directory is made. The target for the eggs
94+# directory is only there for deployment convenience.
95 # Note that the buildout version must be maintained here and in versions.cfg
96 # to make sure that the build does not go over the network.
97 bin/buildout: download-cache eggs
98@@ -192,19 +196,22 @@
99 # and the other bits might run into problems like bug 575037. This
100 # target runs buildout, and then removes everything created except for
101 # the eggs.
102-build_eggs: $(BUILDOUT_BIN) clean_buildout
103+build_eggs: buildout_bin clean_buildout
104+
105+$(BUILDOUT_BIN): buildout_bin
106
107 # This builds bin/py and all the other bin files except bin/buildout.
108 # Remove the target before calling buildout to ensure that buildout
109 # updates the timestamp.
110-$(BUILDOUT_BIN): bin/buildout versions.cfg $(BUILDOUT_CFG) setup.py
111+buildout_bin: bin/buildout versions.cfg $(BUILDOUT_CFG) setup.py \
112+ $(BUILDOUT_TEMPLATES)
113 $(RM) $@
114 $(SHHH) PYTHONPATH= ./bin/buildout \
115 configuration:instance_name=${LPCONFIG} -c $(BUILDOUT_CFG)
116
117 # bin/compile_templates is responsible for building all chameleon templates,
118 # of which there is currently one, but of which many more are coming.
119-compile: $(PY) $(BZR_VERSION_INFO)
120+compile: buildout_bin $(BZR_VERSION_INFO)
121 mkdir -p /var/tmp/vostok-archive
122 ${SHHH} $(MAKE) -C sourcecode build PYTHON=${PYTHON} \
123 LPCONFIG=${LPCONFIG}
124@@ -405,7 +412,8 @@
125 # We insert the absolute path to the branch-rewrite script
126 # into the Apache config as we copy the file into position.
127 sed -e 's,%BRANCH_REWRITE%,$(shell pwd)/scripts/branch-rewrite.py,' configs/development/local-launchpad-apache > /etc/apache2/sites-available/local-launchpad
128- cp configs/development/local-vostok-apache /etc/apache2/sites-available/local-vostok
129+ cp configs/development/local-vostok-apache \
130+ /etc/apache2/sites-available/local-vostok
131 touch /var/tmp/bazaar.launchpad.dev/rewrite.log
132 chown $(SUDO_UID):$(SUDO_GID) /var/tmp/bazaar.launchpad.dev/rewrite.log
133
134@@ -430,8 +438,9 @@
135
136 lp.sfood:
137 # Generate import dependency graph
138- sfood -i -u -I lib/sqlobject -I lib/schoolbell -I lib/devscripts -I lib/contrib \
139- -I lib/canonical/not-used lib/canonical lib/lp 2>/dev/null | grep -v contrib/ \
140+ sfood -i -u -I lib/sqlobject -I lib/schoolbell -I lib/devscripts \
141+ -I lib/contrib -I lib/canonical/not-used lib/canonical \
142+ lib/lp 2>/dev/null | grep -v contrib/ \
143 | grep -v sqlobject | grep -v BeautifulSoup | grep -v psycopg \
144 | grep -v schoolbell > lp.sfood.tmp
145 mv lp.sfood.tmp lp.sfood
146@@ -463,10 +472,10 @@
147 --docformat restructuredtext --verbose-about epytext-summary \
148 $(PYDOCTOR_OPTIONS)
149
150-.PHONY: apidoc check tags TAGS zcmldocs realclean clean debug stop\
151- start run ftest_build ftest_inplace test_build test_inplace pagetests\
152- check check_merge \
153- schema default launchpad.pot check_merge_ui pull scan sync_branches\
154- reload-apache hosted_branches check_db_merge check_mailman check_config\
155- jsbuild jsbuild_lazr clean_js clean_buildout buildonce_eggs build_eggs\
156- sprite_css sprite_image css_combine compile check_schema pydoctor
157+.PHONY: apidoc buildout_bin check tags TAGS zcmldocs realclean clean debug \
158+ stop start run ftest_build ftest_inplace test_build test_inplace \
159+ pagetests check check_merge schema default launchpad.pot \
160+ check_merge_ui pull scan sync_branches reload-apache hosted_branches \
161+ check_db_merge check_mailman check_config jsbuild jsbuild_lazr \
162+ clean_js clean_buildout buildonce_eggs build_eggs sprite_css \
163+ sprite_image css_combine compile check_schema pydoctor