I'm continuing down a rabbit hole that started in jwilm/alacritty#1603 and continued in tomaka/glutin#1070. Specifically, it looks like my terminal (alacritty), which uses glutin, which uses init, is much slower to spawn its initial window in certain cases. In particular, on my laptop (a 6th generation Lenovo X1 Carbon, so new hardware), there is a marked difference in the time it takes to spawn a single winit window depending on whether an external monitor is connected or not.
In particular, running the following code with --release:
extern crate winit;
fn main() {
let mut events_loop = winit::EventsLoop::new();
let _window = winit::WindowBuilder::new()
.with_title("A fantastic window!")
.build(&events_loop)
.unwrap();
events_loop.run_forever(|_| winit::ControlFlow::Break);
}
Without an external monitor connected:
0.01user 0.00system 0:00.14elapsed 14%CPU (0avgtext+0avgdata 6312maxresident)k
0inputs+0outputs (0major+544minor)pagefaults 0swaps
With an external monitor connected:
0.01user 0.00system 0:00.48elapsed 4%CPU (0avgtext+0avgdata 6340maxresident)k
0inputs+0outputs (0major+533minor)pagefaults 0swaps
That's 0.14s to 0.48s on the same system with a different monitor configuration, which seems surprising.
I took some perf profiles, though there's relatively little fidelity since I just spawn and immediately close a window. Without external monitor:
With external monitor:
The relevant lines from xrandr -q in the two configurations are:
Screen 0: minimum 320 x 200, current 2560 x 1440, maximum 8192 x 8192
eDP-1 connected 2560x1440+0+0 (normal left inverted right x axis y axis) 309mm x 174mm
2560x1440 60.01*+ 59.99 59.99 59.96 59.95
and
Screen 0: minimum 320 x 200, current 3120 x 1920, maximum 8192 x 8192
eDP-1 connected 1920x1080+0+0 (normal left inverted right x axis y axis) 309mm x 174mm
1920x1080 60.01 59.97 59.96* 59.93
HDMI-1 connected primary 1200x1920+1920+0 left (normal left inverted right x axis y axis) 546mm x 352mm
1920x1200 59.95*+
1920x1080 60.00 50.00 59.94 59.99
/cc @francesca64
Sorry for the wait! Since I can't reproduce this, and I don't see anything notable in the flame graph, fixing this could be tricky.
To start bisecting this, I've made a branch that doesn't query the monitors at all: https://github.com/francesca64/winit/tree/x11-dummy-monitor. If you try running that, is the speed consistent?
Yup, opening time is completely consistent on that branch:
$ time target/release/examples/open
0.01user 0.00system 0:00.02elapsed 86%CPU (0avgtext+0avgdata 6276maxresident)k
0inputs+0outputs (0major+540minor)pagefaults 0swaps
I have the same problem with alacritty (2.3). 300ms on the laptop. 600ms when external monitor is connected. With @francesca64 dummy monitor hack, alacritty starts in 120ms. Of course it will probably mess up any HIDPI detection. But I am lucky to have a very similar DPI between my laptop and external monitor.
There seem to be multiple issues floating around related to this. For me, it causes Alacritty opening twice sometimes using an i3 keybind. (https://github.com/jwilm/alacritty/issues/1859)
In a previous Alacritty version, we could explicitly disable calling into xrandr to detect the current screen's DPI. Initially, I though winit was shelling out to xrandr, but the flame graph shows a call into libX11; seems that call is also very slow. Setting WINIT_HIDPI_FACTOR does not seem to prevent the xrandr call.
The more screens/adapters a machine has, the longer this call seems to take. My experience with this behaviour seems consistent on different versions across different machines. The codebase also seems to be aware of this: https://github.com/tomaka/winit/blob/master/src/platform/linux/x11/monitor.rs#L134.
➜ ~ time alacritty -e true
alacritty -e true 0.08s user 0.02s system 22% cpu 0.471 total
➜ ~ time xrandr >/dev/null
xrandr > /dev/null 0.01s user 0.00s system 1% cpu 0.348 total
Hope this comment was helpful, might give the hunt for the cause a new spin. :slightly_smiling_face:
When available, we should consider using XRRGetScreenResourcesCurrent instead, which is a couple orders of magnitude faster according to this issue: https://github.com/glfw/glfw/issues/347
To quote:
XRRGetScreenResourcesCurrent: Tipically from 20 to 100 us.
XRRGetScreenResources: Typically from 13600 to 13700 us.
Hey fellas, take this for a spin: https://github.com/tomaka/winit/pull/801
Hmm, I've recently switched out my screen for a non-rotated one, and can no longer produce the increased delay with an external monitor attached sadly :/
@ZeGentzy https://github.com/jwilm/alacritty/issues/782#issuecomment-467629539
Closing this, since #801 was merged and that largely seems to have solved this. Please feel free to re-open this if that's an inaccurate assessment
Most helpful comment
There seem to be multiple issues floating around related to this. For me, it causes Alacritty opening twice sometimes using an i3 keybind. (https://github.com/jwilm/alacritty/issues/1859)
In a previous Alacritty version, we could explicitly disable calling into xrandr to detect the current screen's DPI. Initially, I though winit was shelling out to
xrandr, but the flame graph shows a call into libX11; seems that call is also very slow. SettingWINIT_HIDPI_FACTORdoes not seem to prevent the xrandr call.The more screens/adapters a machine has, the longer this call seems to take. My experience with this behaviour seems consistent on different versions across different machines. The codebase also seems to be aware of this: https://github.com/tomaka/winit/blob/master/src/platform/linux/x11/monitor.rs#L134.
Hope this comment was helpful, might give the hunt for the cause a new spin. :slightly_smiling_face: