diff options
author | Kimiyuki Onaka <kimiyuki@google.com> | 2020-08-28 10:05:27 +0900 |
---|---|---|
committer | Mike Frysinger <vapier@google.com> | 2020-09-09 03:52:24 +0000 |
commit | 0501b29e7ae072e0b10ea9ddd913ec6d5975f690 (patch) | |
tree | 95cc04852cbebe2365d0667c865c3995780fdda7 /subcmds/status.py | |
parent | 4e1fc1013c9203d3f5e7bdfba909d175a522c1f3 (diff) | |
download | git-repo-0501b29e7ae072e0b10ea9ddd913ec6d5975f690.tar.gz |
status: Use multiprocessing for `repo status -j<num>` instead of threading
This change increases the speed of the command with parallelization with
processes. The parallelization with threads doesn't work well, and
increasing the number of jobs to many (8 threads ~) didn't increase the speed.
Possibly, the global interpreter lock of Python affects.
Bug: https://crbug.com/gerrit/12389
Change-Id: Icbe5df8ba037dd91422b96f4e43708068d7be924
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/279936
Tested-by: Kimiyuki Onaka <kimiyuki@google.com>
Reviewed-by: Mike Frysinger <vapier@google.com>
Diffstat (limited to 'subcmds/status.py')
-rw-r--r-- | subcmds/status.py | 48 |
1 files changed, 15 insertions, 33 deletions
diff --git a/subcmds/status.py b/subcmds/status.py index 8537e6c5..c380dba3 100644 --- a/subcmds/status.py +++ b/subcmds/status.py | |||
@@ -16,17 +16,13 @@ | |||
16 | 16 | ||
17 | from __future__ import print_function | 17 | from __future__ import print_function |
18 | 18 | ||
19 | import functools | ||
19 | import glob | 20 | import glob |
20 | import itertools | 21 | import multiprocessing |
21 | import os | 22 | import os |
22 | 23 | ||
23 | from command import PagedCommand | 24 | from command import PagedCommand |
24 | 25 | ||
25 | try: | ||
26 | import threading as _threading | ||
27 | except ImportError: | ||
28 | import dummy_threading as _threading | ||
29 | |||
30 | from color import Coloring | 26 | from color import Coloring |
31 | import platform_utils | 27 | import platform_utils |
32 | 28 | ||
@@ -95,25 +91,20 @@ the following meanings: | |||
95 | p.add_option('-q', '--quiet', action='store_true', | 91 | p.add_option('-q', '--quiet', action='store_true', |
96 | help="only print the name of modified projects") | 92 | help="only print the name of modified projects") |
97 | 93 | ||
98 | def _StatusHelper(self, project, clean_counter, sem, quiet): | 94 | def _StatusHelper(self, quiet, project): |
99 | """Obtains the status for a specific project. | 95 | """Obtains the status for a specific project. |
100 | 96 | ||
101 | Obtains the status for a project, redirecting the output to | 97 | Obtains the status for a project, redirecting the output to |
102 | the specified object. It will release the semaphore | 98 | the specified object. |
103 | when done. | ||
104 | 99 | ||
105 | Args: | 100 | Args: |
101 | quiet: Where to output the status. | ||
106 | project: Project to get status of. | 102 | project: Project to get status of. |
107 | clean_counter: Counter for clean projects. | 103 | |
108 | sem: Semaphore, will call release() when complete. | 104 | Returns: |
109 | output: Where to output the status. | 105 | The status of the project. |
110 | """ | 106 | """ |
111 | try: | 107 | return project.PrintWorkTreeStatus(quiet=quiet) |
112 | state = project.PrintWorkTreeStatus(quiet=quiet) | ||
113 | if state == 'CLEAN': | ||
114 | next(clean_counter) | ||
115 | finally: | ||
116 | sem.release() | ||
117 | 108 | ||
118 | def _FindOrphans(self, dirs, proj_dirs, proj_dirs_parents, outstring): | 109 | def _FindOrphans(self, dirs, proj_dirs, proj_dirs_parents, outstring): |
119 | """find 'dirs' that are present in 'proj_dirs_parents' but not in 'proj_dirs'""" | 110 | """find 'dirs' that are present in 'proj_dirs_parents' but not in 'proj_dirs'""" |
@@ -133,27 +124,18 @@ the following meanings: | |||
133 | 124 | ||
134 | def Execute(self, opt, args): | 125 | def Execute(self, opt, args): |
135 | all_projects = self.GetProjects(args) | 126 | all_projects = self.GetProjects(args) |
136 | counter = itertools.count() | 127 | counter = 0 |
137 | 128 | ||
138 | if opt.jobs == 1: | 129 | if opt.jobs == 1: |
139 | for project in all_projects: | 130 | for project in all_projects: |
140 | state = project.PrintWorkTreeStatus(quiet=opt.quiet) | 131 | state = project.PrintWorkTreeStatus(quiet=opt.quiet) |
141 | if state == 'CLEAN': | 132 | if state == 'CLEAN': |
142 | next(counter) | 133 | counter += 1 |
143 | else: | 134 | else: |
144 | sem = _threading.Semaphore(opt.jobs) | 135 | with multiprocessing.Pool(opt.jobs) as pool: |
145 | threads = [] | 136 | states = pool.map(functools.partial(self._StatusHelper, opt.quiet), all_projects) |
146 | for project in all_projects: | 137 | counter += states.count('CLEAN') |
147 | sem.acquire() | 138 | if not opt.quiet and len(all_projects) == counter: |
148 | |||
149 | t = _threading.Thread(target=self._StatusHelper, | ||
150 | args=(project, counter, sem, opt.quiet)) | ||
151 | threads.append(t) | ||
152 | t.daemon = True | ||
153 | t.start() | ||
154 | for t in threads: | ||
155 | t.join() | ||
156 | if not opt.quiet and len(all_projects) == next(counter): | ||
157 | print('nothing to commit (working directory clean)') | 139 | print('nothing to commit (working directory clean)') |
158 | 140 | ||
159 | if opt.orphans: | 141 | if opt.orphans: |