-
-
Notifications
You must be signed in to change notification settings - Fork 21.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Heavy CPU load while downloading export templates #35868
Comments
The export template manager's progress bar only updates twice a second, so it shouldn't be due to the editor re-rendering continuously. As a workaround, you can download the export templates TPZ from the Download page and install them manually from the export template manager using the Install From File option. |
same on macOS |
This still seems to be a problem in 3.3.1. Any ideas what's causing it / why this is assigned to 4.0? |
I don't know what's causing it. As for the milestone, we generally assign issues to a distant milestone unless they are regressions that occurred in a specific release. |
#48902 might help with this once it's cherry-picked to the Can anyone try to use a profiler to see where the CPU usage is coming from? |
Disabling godot/editor/export_template_manager.cpp Line 151 in 242c05d
This can be reproed using HTTPRequest to download a large file in GDScript as well: extends Node2D
func _ready():
var req := HTTPRequest.new()
req.use_threads = true
add_child(req)
var error = req.request("https://downloads.tuxfamily.org/godotengine/3.4.3/Godot_v3.4.3-stable_x11.64.zip")
if error != OK:
push_error("failed") |
I'm guessing because the thread func does a tight busy loop godot/scene/main/http_request.cpp Lines 131 to 137 in 242c05d
|
The 1 microsecond busywait has always been around: ab93fd1 There were merged PRs increasing a similar busywait on the remote debugger and editor export plugin, but none on HTTPRequest yet. Can you try increasing |
There's no noticeable change in download speed. AFAICT the thread is just checking "are we there yet" repeatedly, so I don't think it generally makes more sense to query faster than the framerate. In the export dialog you could probably get away with an even slower poll rate. Maybe it makes sense as a customization option on the |
It seems like a pretty advanced thing to change, so I'm not sure. I'd just leave it at 6900 which is enough to feed any 144 Hz monitor out there (if you want to display the progress somewhere). |
Using a threaded HTTPRequest will currently eat ~100% CPU on Linux (and possibly other OS). The thread is just checking whether the request is done. It generally doesn't make sense to do this any faster than the framerate. Fixes godotengine#35868.
I don't see much of a point to have the thread delay to be equal to the frame rate. The point of using threads is to maximize the download speed (at the cost of CPU), I agree the current usage might be too high, but setting it to the frame rate kind of defeat its purpose. |
It seems like separate bug that non-threaded HTTPRequest performance is framerate-dependent. Should non-threaded requests update in
With a default chunk size of 64k and a poll rate of 1us, we're expending CPU to optimize for a download speed of:
My proposal would be:
Does that sound reasonable? |
Not really to be honest.
I think there is no point adding more hacks than we already have, and the root cause should be fixed instead. EDIT: To clarify, I truly believe this has to be fixed, but I want the fix to be the correct one, not just another hack that might end up biting back. |
Fair, but couldn't you use that argument to say that anything belongs in
Fair enough. Could we leave |
Well, honestly, giving templates it's something you only download when updating the engine, I think the improved download speed is much better then a lower CPU usage when you download them. |
We can probably try various sleep values on a fast fiber connection and figure out a sweet spot between download speed and CPU usage. Think of the laptops 🙂 |
Again, we are talking about the case of downloading the editor templates, on battery, on a laptop, on a slow connection. |
I'm sufficiently convinced that we should not band-aid I still think using a non-threaded request for export templates would be preferable until threaded requests can work without hot-spinning, but I won't continue to harp on it. I suppose those who are concerned can use |
I've tested this on a 60 Hz monitor (and V-Sync enabled) and found the download speed to be negatively impacted too much. For reference, I have a 1000/500 FTTH connection and am quite close to TuxFamily's servers.
To test this on your end, change |
Ok, I'll concede it is better to leave this as-is for now. What follows was just for my own curiosity: I decided to give it a try as well, with this script: extends Node
func _ready():
var req = HTTPRequest.new()
req.set_use_threads(false)
add_child(req)
req.download_file = "templates.zip"
var err = req.request("https://downloads.tuxfamily.org/godotengine/3.4.4/Godot_v3.4.4-stable_x11.64.zip")
if err != OK:
push_error("An error occurred in the HTTP request.")
get_tree().quit()
await req.request_completed
get_tree().quit() I started with
Then I tried with
Same speed as curl, but a lot more time on the CPU. Then I set
Still the same speed, but much more reasonable CPU: Then I set my display to 30hz and tried again with
Ok, that's a fair bit slower. Out of curiosity, I tried patching diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp
index 700ba761f6..b035a14055 100644
--- a/scene/main/http_request.cpp
+++ b/scene/main/http_request.cpp
@@ -372,6 +372,7 @@ bool HTTPRequest::_update_connection() {
}
}
+ while (true) {
client->poll();
if (client->get_status() != HTTPClient::STATUS_BODY) {
return false;
@@ -391,6 +392,8 @@ bool HTTPRequest::_update_connection() {
} else {
body.append_array(chunk);
}
+ } else {
+ break;
}
if (body_size_limit >= 0 && downloaded.get() > body_size_limit) {
@@ -408,6 +411,7 @@ bool HTTPRequest::_update_connection() {
call_deferred(SNAME("_request_done"), RESULT_SUCCESS, response_code, response_headers, body);
return true;
}
+ }
return false;
In a way, that's the best of both worlds, but I'm guessing HTTPRequest deliberately consumes only a single chunk per poll to avoid framerate drops? |
Exactly, polling in a tight loop during process is not okay because it may stall the engine for too long if there the transfer rate is high. |
I can still reproduce this as of 4.3.dev3 on Linux: The download is going between 20 MB/s and 40 MB/s (megabytes) for reference, and the CPU is an i9-13900K. The speed matches a |
Godot version:
3.2 stable
OS/device including version:
$ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Pop!_OS 19.10 Release: 19.10 Codename: eoan
Issue description:
The export template download page seems to be very demanding
The text was updated successfully, but these errors were encountered: