Skip to content

Commit 54bf1f3

Browse files
committed
Startup 3.5x faster
Pull Request resolved: #2099 Fixing various simple things that claude helped find. 1.7 seconds --> .5 seconds. * Don't start the exponential backoff for initial connections at 50ms. We hit these like 20 times in a row and it adds up to 1/2 second! * We need to rethink the batched aggregation interval. We probably need a simple predictor that assumes the average time between messages in `inf` for the first message, and just sends it, that way we do not add another 50 ms on every process start. * Do not import ipython to check if ipython is active. If it isn't active this adds 1/2 second to startup time because it happens in three processes. ghstack-source-id: 328496691 @exported-using-ghexport Differential Revision: [D88810033](https://our.internmc.facebook.com/intern/diff/D88810033/) **NOTE FOR REVIEWERS**: This PR has internal Meta-specific changes or comments, please review them on [Phabricator](https://our.internmc.facebook.com/intern/diff/D88810033/)!
1 parent bf3b8ff commit 54bf1f3

File tree

6 files changed

+39
-38
lines changed

6 files changed

+39
-38
lines changed

hyperactor/src/channel/net/client.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -543,7 +543,7 @@ impl<S: Stream> Conn<S> {
543543
fn reconnect_with_default() -> Self {
544544
Self::Disconnected(Box::new(
545545
ExponentialBackoffBuilder::new()
546-
.with_initial_interval(Duration::from_millis(50))
546+
.with_initial_interval(Duration::from_millis(1))
547547
.with_multiplier(2.0)
548548
.with_randomization_factor(0.1)
549549
.with_max_interval(Duration::from_millis(1000))

hyperactor/src/config.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ declare_attrs! {
7474
env_name: Some("HYPERACTOR_SPLIT_MAX_BUFFER_AGE".to_string()),
7575
py_name: None,
7676
})
77-
pub attr SPLIT_MAX_BUFFER_AGE: Duration = Duration::from_millis(50);
77+
pub attr SPLIT_MAX_BUFFER_AGE: Duration = Duration::from_millis(1);
7878

7979
/// Timeout used by proc mesh for stopping an actor.
8080
@meta(CONFIG = ConfigAttr {

python/monarch/_src/actor/__init__.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,10 @@
1111
"""
1212

1313
from monarch.config import configure
14+
from monarch._src.ipython_check import is_ipython
1415

1516
# Detect if we're running in IPython/Jupyter
16-
_in_ipython = False
17-
try:
18-
# pyre-ignore[21]
19-
from IPython import get_ipython
20-
21-
_in_ipython = get_ipython() is not None
22-
except ImportError:
23-
pass
17+
_in_ipython = is_ipython()
2418

2519
# Set notebook-friendly defaults for stdio piping when spawning procs.
2620
# These config is read by:

python/monarch/_src/actor/logging.py

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,9 @@
2121
)
2222
from monarch._src.actor.actor_mesh import context
2323
from monarch._src.actor.future import Future
24+
from monarch._src.ipython_check import is_ipython
2425

25-
IN_IPYTHON = False
26-
try:
27-
# Check if we are in ipython environment
28-
# pyre-ignore[21]
29-
from IPython import get_ipython
30-
31-
# pyre-ignore[21]
32-
from IPython.core.interactiveshell import ExecutionResult # noqa: F401
33-
34-
IN_IPYTHON = get_ipython() is not None
35-
except ImportError:
36-
pass
26+
IN_IPYTHON = is_ipython()
3727

3828
logger: logging.Logger = logging.getLogger(__name__)
3929

@@ -88,7 +78,12 @@ def register_flusher_if_in_ipython(self) -> None:
8878
with _global_flush_lock:
8979
global _global_flush_registered
9080
if not _global_flush_registered:
91-
get_ipython().events.register(
81+
# pyre-ignore[21]: IPython is already loaded if IN_IPYTHON is True
82+
from IPython import get_ipython
83+
84+
ipython = get_ipython()
85+
assert ipython is not None
86+
ipython.events.register(
9287
"post_run_cell",
9388
lambda _: flush_all_proc_mesh_logs(
9489
self._logging_mesh_client is not None
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Copyright (c) Meta Platforms, Inc. and affiliates.
2+
# All rights reserved.
3+
#
4+
# This source code is licensed under the BSD-style license found in the
5+
# LICENSE file in the root directory of this source tree.
6+
7+
# pyre-strict
8+
9+
"""
10+
Fast IPython detection by checking sys.modules instead of importing.
11+
"""
12+
13+
import sys
14+
15+
16+
def is_ipython() -> bool:
17+
"""
18+
Check if code is running in an IPython/Jupyter environment.
19+
Avoids slow IPython import by checking sys.modules first.
20+
"""
21+
if "IPython" not in sys.modules:
22+
return False
23+
24+
# pyre-ignore[16]: get_ipython exists in IPython module
25+
get_ipython = sys.modules["IPython"].get_ipython
26+
return get_ipython() is not None

python/monarch/controller/debugger.py

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,8 @@
66

77
# pyre-strict
88
import sys
9-
from typing import Optional
109

11-
_is_ipython: Optional[bool] = None
12-
13-
14-
def is_ipython() -> bool:
15-
global _is_ipython
16-
if _is_ipython is not None:
17-
return _is_ipython
18-
try:
19-
from IPython import get_ipython
20-
21-
_is_ipython = get_ipython() is not None
22-
except ImportError:
23-
_is_ipython = False
24-
return _is_ipython
10+
from monarch._src.ipython_check import is_ipython
2511

2612

2713
def write(msg: str) -> None:

0 commit comments

Comments
 (0)