Skip to content

Commit 99856a6

Browse files
Change --local-executor flag semantics (#907)
* Convert `--local-executor` in an integer flag, defaults to 1 i.e. enabled, use 0 to disable * Consider any value other than 1 as remote mode * Use integer to disable local executor mode in integration tests * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fix mypy errors * Update flags in readme * Check for type * Remove pid file check for now * Update `--local-executor` flag usage Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent f921f56 commit 99856a6

File tree

12 files changed

+50
-40
lines changed

12 files changed

+50
-40
lines changed

.github/workflows/test-library.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -754,7 +754,8 @@ jobs:
754754
$CONTAINER_TAG
755755
--hostname 0.0.0.0
756756
--enable-web-server
757-
--local-executor && ./tests/integration/test_integration.sh 8899
757+
&&
758+
./tests/integration/test_integration.sh 8899
758759
- name: Push to GHCR
759760
run: >-
760761
REGISTRY_URL="ghcr.io/abhinavsingh/proxy.py";

Dockerfile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,4 @@ EXPOSE 8899/tcp
3232
ENTRYPOINT [ "proxy" ]
3333
CMD [ \
3434
"--hostname=0.0.0.0" \
35-
"--local-executor" \
3635
]

Makefile

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,6 @@ lib-profile:
143143
--num-workers 1 \
144144
--enable-web-server \
145145
--plugin proxy.plugin.WebServerPlugin \
146-
--local-executor \
147146
--backlog 65536 \
148147
--open-file-limit 65536 \
149148
--log-file /dev/null
@@ -160,7 +159,6 @@ lib-speedscope:
160159
--num-workers 1 \
161160
--enable-web-server \
162161
--plugin proxy.plugin.WebServerPlugin \
163-
--local-executor \
164162
--backlog 65536 \
165163
--open-file-limit 65536 \
166164
--log-file /dev/null

README.md

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2204,8 +2204,9 @@ To run standalone benchmark for `proxy.py`, use the following command from repo
22042204
```console
22052205
proxy -h
22062206
usage: -m [-h] [--enable-events] [--enable-conn-pool] [--threadless]
2207-
[--threaded] [--num-workers NUM_WORKERS] [--local-executor]
2208-
[--backlog BACKLOG] [--hostname HOSTNAME] [--port PORT]
2207+
[--threaded] [--num-workers NUM_WORKERS]
2208+
[--local-executor LOCAL_EXECUTOR] [--backlog BACKLOG]
2209+
[--hostname HOSTNAME] [--port PORT]
22092210
[--unix-socket-path UNIX_SOCKET_PATH]
22102211
[--num-acceptors NUM_ACCEPTORS] [--version] [--log-level LOG_LEVEL]
22112212
[--log-file LOG_FILE] [--log-format LOG_FORMAT]
@@ -2248,13 +2249,14 @@ options:
22482249
handle each client connection.
22492250
--num-workers NUM_WORKERS
22502251
Defaults to number of CPU cores.
2251-
--local-executor Default: True. Disabled by default. When enabled
2252-
acceptors will make use of local (same process)
2253-
executor instead of distributing load across remote
2254-
(other process) executors. Enable this option to
2255-
achieve CPU affinity between acceptors and executors,
2256-
instead of using underlying OS kernel scheduling
2257-
algorithm.
2252+
--local-executor LOCAL_EXECUTOR
2253+
Default: 1. Enabled by default. Use 0 to disable. When
2254+
enabled acceptors will make use of local (same
2255+
process) executor instead of distributing load across
2256+
remote (other process) executors. Enable this option
2257+
to achieve CPU affinity between acceptors and
2258+
executors, instead of using underlying OS kernel
2259+
scheduling algorithm.
22582260
--backlog BACKLOG Default: 100. Maximum number of pending connections to
22592261
proxy server
22602262
--hostname HOSTNAME Default: 127.0.0.1. Server IP address.

benchmark/_proxy.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
enable_web_server=True,
2424
disable_proxy_server=False,
2525
num_acceptors=10,
26-
local_executor=True,
26+
local_executor=1,
2727
log_file='/dev/null',
2828
) as _:
2929
while True:

proxy/common/flag.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ def initialize(
340340
)
341341
args.timeout = cast(int, opts.get('timeout', args.timeout))
342342
args.local_executor = cast(
343-
bool,
343+
int,
344344
opts.get(
345345
'local_executor',
346346
args.local_executor,

proxy/core/acceptor/acceptor.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,11 @@
4040

4141
flags.add_argument(
4242
'--local-executor',
43-
action='store_true',
44-
default=DEFAULT_LOCAL_EXECUTOR,
45-
help='Default: ' + ('True' if DEFAULT_LOCAL_EXECUTOR else 'False') + '. ' +
46-
'Disabled by default. When enabled acceptors will make use of ' +
47-
'local (same process) executor instead of distributing load across ' +
43+
type=int,
44+
default=int(DEFAULT_LOCAL_EXECUTOR),
45+
help='Default: ' + ('1' if DEFAULT_LOCAL_EXECUTOR else '0') + '. ' +
46+
'Enabled by default. Use 0 to disable. When enabled acceptors ' +
47+
'will make use of local (same process) executor instead of distributing load across ' +
4848
'remote (other process) executors. Enable this option to achieve CPU affinity between ' +
4949
'acceptors and executors, instead of using underlying OS kernel scheduling algorithm.',
5050
)
@@ -149,7 +149,7 @@ def run_once(self) -> None:
149149
if locked:
150150
self.lock.release()
151151
for work in works:
152-
if self.flags.local_executor:
152+
if self.flags.local_executor == int(DEFAULT_LOCAL_EXECUTOR):
153153
assert self._local_work_queue
154154
self._local_work_queue.put(work)
155155
else:
@@ -172,7 +172,7 @@ def run(self) -> None:
172172
type=socket.SOCK_STREAM,
173173
)
174174
try:
175-
if self.flags.local_executor:
175+
if self.flags.local_executor == int(DEFAULT_LOCAL_EXECUTOR):
176176
self._start_local()
177177
self.selector.register(self.sock, selectors.EVENT_READ)
178178
while not self.running.is_set():
@@ -181,7 +181,7 @@ def run(self) -> None:
181181
pass
182182
finally:
183183
self.selector.unregister(self.sock)
184-
if self.flags.local_executor:
184+
if self.flags.local_executor == int(DEFAULT_LOCAL_EXECUTOR):
185185
self._stop_local()
186186
self.sock.close()
187187
logger.debug('Acceptor#%d shutdown', self.idd)

proxy/core/acceptor/pool.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,17 @@ def __exit__(self, *args: Any) -> None:
9898
def setup(self) -> None:
9999
"""Setup acceptors."""
100100
self._start()
101-
logger.info('Started %d acceptors' % self.flags.num_acceptors)
101+
execution_mode = (
102+
'threadless (local)'
103+
if self.flags.local_executor
104+
else 'threadless (remote)'
105+
) if self.flags.threadless else 'threaded'
106+
logger.info(
107+
'Started %d acceptors in %s mode' % (
108+
self.flags.num_acceptors,
109+
execution_mode,
110+
),
111+
)
102112
# Send file descriptor to all acceptor processes.
103113
fd = self.listener.fileno()
104114
for index in range(self.flags.num_acceptors):

proxy/proxy.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
from .core.event import EventManager
2020
from .common.utils import bytes_
2121
from .common.flag import FlagParser, flags
22-
from .common.constants import DEFAULT_LOG_FILE, DEFAULT_LOG_FORMAT, DEFAULT_LOG_LEVEL
22+
from .common.constants import DEFAULT_LOCAL_EXECUTOR, DEFAULT_LOG_FILE, DEFAULT_LOG_FORMAT, DEFAULT_LOG_LEVEL
2323
from .common.constants import DEFAULT_OPEN_FILE_LIMIT, DEFAULT_PLUGINS, DEFAULT_VERSION
2424
from .common.constants import DEFAULT_ENABLE_DASHBOARD, DEFAULT_WORK_KLASS, DEFAULT_PID_FILE
2525

@@ -205,19 +205,19 @@ def shutdown(self) -> None:
205205
self._delete_pid_file()
206206

207207
def _write_pid_file(self) -> None:
208-
if self.flags.pid_file is not None:
209-
# NOTE: Multiple instances of proxy.py running on
210-
# same host machine will currently result in overwriting the PID file
208+
if self.flags.pid_file:
211209
with open(self.flags.pid_file, 'wb') as pid_file:
212210
pid_file.write(bytes_(os.getpid()))
213211

214212
def _delete_pid_file(self) -> None:
215-
if self.flags.pid_file and os.path.exists(self.flags.pid_file):
213+
if self.flags.pid_file \
214+
and os.path.exists(self.flags.pid_file):
216215
os.remove(self.flags.pid_file)
217216

218217
@property
219218
def remote_executors_enabled(self) -> bool:
220-
return self.flags.threadless and not self.flags.local_executor
219+
return self.flags.threadless \
220+
and not (self.flags.local_executor == int(DEFAULT_LOCAL_EXECUTOR))
221221

222222

223223
def main(**opts: Any) -> None:

tests/core/test_acceptor.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def setUp(self) -> None:
2626
self.flags = FlagParser.initialize(
2727
threaded=True,
2828
work_klass=mock.MagicMock(),
29-
local_executor=False,
29+
local_executor=0,
3030
)
3131
self.acceptor = Acceptor(
3232
idd=self.acceptor_id,

tests/integration/test_integration.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ def proxy_py_subprocess(request: Any) -> Generator[int, None, None]:
5959
'proxy_py_subprocess',
6060
(
6161
('--threadless'),
62-
('--threadless --local-executor'),
62+
('--threadless --local-executor 0'),
6363
('--threaded'),
6464
),
6565
indirect=True,

tests/test_main.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ def mock_default_args(mock_args: mock.Mock) -> None:
6868
mock_args.enable_events = DEFAULT_ENABLE_EVENTS
6969
mock_args.enable_dashboard = DEFAULT_ENABLE_DASHBOARD
7070
mock_args.work_klass = DEFAULT_WORK_KLASS
71-
mock_args.local_executor = DEFAULT_LOCAL_EXECUTOR
71+
mock_args.local_executor = int(DEFAULT_LOCAL_EXECUTOR)
7272

7373
@mock.patch('os.remove')
7474
@mock.patch('os.path.exists')
@@ -93,7 +93,7 @@ def test_entry_point(
9393
) -> None:
9494
pid_file = os.path.join(tempfile.gettempdir(), 'pid')
9595
mock_sleep.side_effect = KeyboardInterrupt()
96-
mock_initialize.return_value.local_executor = False
96+
mock_initialize.return_value.local_executor = 0
9797
mock_initialize.return_value.enable_events = False
9898
mock_initialize.return_value.pid_file = pid_file
9999
entry_point()
@@ -141,7 +141,7 @@ def test_main_with_no_flags(
141141
mock_sleep: mock.Mock,
142142
) -> None:
143143
mock_sleep.side_effect = KeyboardInterrupt()
144-
mock_initialize.return_value.local_executor = False
144+
mock_initialize.return_value.local_executor = 0
145145
mock_initialize.return_value.enable_events = False
146146
main()
147147
mock_event_manager.assert_not_called()
@@ -181,7 +181,7 @@ def test_enable_events(
181181
mock_sleep: mock.Mock,
182182
) -> None:
183183
mock_sleep.side_effect = KeyboardInterrupt()
184-
mock_initialize.return_value.local_executor = False
184+
mock_initialize.return_value.local_executor = 0
185185
mock_initialize.return_value.enable_events = True
186186
main()
187187
mock_event_manager.assert_called_once()
@@ -228,8 +228,8 @@ def test_enable_dashboard(
228228
mock_args = mock_parse_args.return_value
229229
self.mock_default_args(mock_args)
230230
mock_args.enable_dashboard = True
231-
mock_args.local_executor = False
232-
main(enable_dashboard=True, local_executor=False)
231+
mock_args.local_executor = 0
232+
main(enable_dashboard=True, local_executor=0)
233233
mock_load_plugins.assert_called()
234234
self.assertEqual(
235235
mock_load_plugins.call_args_list[0][0][0], [
@@ -274,8 +274,8 @@ def test_enable_devtools(
274274
mock_args = mock_parse_args.return_value
275275
self.mock_default_args(mock_args)
276276
mock_args.enable_devtools = True
277-
mock_args.local_executor = False
278-
main(enable_devtools=True, local_executor=False)
277+
mock_args.local_executor = 0
278+
main(enable_devtools=True, local_executor=0)
279279
mock_load_plugins.assert_called()
280280
self.assertEqual(
281281
mock_load_plugins.call_args_list[0][0][0], [

0 commit comments

Comments
 (0)