Show More
@@ -63,18 +63,27 b' def _numworkers(ui):' | |||||
63 |
|
63 | |||
64 | if pycompat.isposix or pycompat.iswindows: |
|
64 | if pycompat.isposix or pycompat.iswindows: | |
65 | _STARTUP_COST = 0.01 |
|
65 | _STARTUP_COST = 0.01 | |
|
66 | # The Windows worker is thread based. If tasks are CPU bound, threads | |||
|
67 | # in the presence of the GIL result in excessive context switching and | |||
|
68 | # this overhead can slow down execution. | |||
|
69 | _DISALLOW_THREAD_UNSAFE = pycompat.iswindows | |||
66 | else: |
|
70 | else: | |
67 | _STARTUP_COST = 1e30 |
|
71 | _STARTUP_COST = 1e30 | |
|
72 | _DISALLOW_THREAD_UNSAFE = False | |||
68 |
|
73 | |||
69 | def worthwhile(ui, costperop, nops): |
|
74 | def worthwhile(ui, costperop, nops, threadsafe=True): | |
70 | '''try to determine whether the benefit of multiple processes can |
|
75 | '''try to determine whether the benefit of multiple processes can | |
71 | outweigh the cost of starting them''' |
|
76 | outweigh the cost of starting them''' | |
|
77 | ||||
|
78 | if not threadsafe and _DISALLOW_THREAD_UNSAFE: | |||
|
79 | return False | |||
|
80 | ||||
72 | linear = costperop * nops |
|
81 | linear = costperop * nops | |
73 | workers = _numworkers(ui) |
|
82 | workers = _numworkers(ui) | |
74 | benefit = linear - (_STARTUP_COST * workers + linear / workers) |
|
83 | benefit = linear - (_STARTUP_COST * workers + linear / workers) | |
75 | return benefit >= 0.15 |
|
84 | return benefit >= 0.15 | |
76 |
|
85 | |||
77 | def worker(ui, costperarg, func, staticargs, args): |
|
86 | def worker(ui, costperarg, func, staticargs, args, threadsafe=True): | |
78 | '''run a function, possibly in parallel in multiple worker |
|
87 | '''run a function, possibly in parallel in multiple worker | |
79 | processes. |
|
88 | processes. | |
80 |
|
89 | |||
@@ -88,9 +97,13 b' def worker(ui, costperarg, func, statica' | |||||
88 |
|
97 | |||
89 | args - arguments to split into chunks, to pass to individual |
|
98 | args - arguments to split into chunks, to pass to individual | |
90 | workers |
|
99 | workers | |
|
100 | ||||
|
101 | threadsafe - whether work items are thread safe and can be executed using | |||
|
102 | a thread-based worker. Should be disabled for CPU heavy tasks that don't | |||
|
103 | release the GIL. | |||
91 | ''' |
|
104 | ''' | |
92 | enabled = ui.configbool('worker', 'enabled') |
|
105 | enabled = ui.configbool('worker', 'enabled') | |
93 | if enabled and worthwhile(ui, costperarg, len(args)): |
|
106 | if enabled and worthwhile(ui, costperarg, len(args), threadsafe=threadsafe): | |
94 | return _platformworker(ui, func, staticargs, args) |
|
107 | return _platformworker(ui, func, staticargs, args) | |
95 | return func(*staticargs + (args,)) |
|
108 | return func(*staticargs + (args,)) | |
96 |
|
109 |
@@ -65,7 +65,7 b' update with worker processes' | |||||
65 |
|
65 | |||
66 | $ cat <<EOF > forceworker.py |
|
66 | $ cat <<EOF > forceworker.py | |
67 | > from mercurial import extensions, worker |
|
67 | > from mercurial import extensions, worker | |
68 | > def nocost(orig, ui, costperop, nops): |
|
68 | > def nocost(orig, ui, costperop, nops, threadsafe=True): | |
69 | > return worker._numworkers(ui) > 1 |
|
69 | > return worker._numworkers(ui) > 1 | |
70 | > def uisetup(ui): |
|
70 | > def uisetup(ui): | |
71 | > extensions.wrapfunction(worker, 'worthwhile', nocost) |
|
71 | > extensions.wrapfunction(worker, 'worthwhile', nocost) |
General Comments 0
You need to be logged in to leave comments.
Login now