autoupdater: update download progress display less frequently

Updating the "XXXXX / XXXXX KiB" display for every run of
recv_image_cb() is a significant bottleneck on slow consoles. This was
reported for a device using a 9600 Baud serial console, but the slowdown
is noticeable even on a 115200 Baud console, especially when the network
is fast.

Replace the output with a "XX.X / XX.X MiB" display and only update it
every 0.1 MiB to fix the issue.

Closes #273
This commit is contained in:
Matthias Schiffer 2024-03-08 20:17:47 +01:00
parent 3d08b0fee8
commit e350f4804d
No known key found for this signature in database
GPG Key ID: 16EF3F64CB201D9C
1 changed files with 29 additions and 7 deletions

View File

@ -72,6 +72,7 @@ struct recv_manifest_ctx {
struct recv_image_ctx {
int fd;
ecdsa_sha256_context_t hash_ctx;
ssize_t downloaded;
};
@ -248,6 +249,32 @@ static void recv_manifest_cb(struct uclient *cl) {
}
}
/** Updates the "XX.X / XX.X MiB" progress display */
static void update_progress(struct recv_image_ctx *ctx, ssize_t downloaded, ssize_t length)
{
/* Numbers in 0.1 MiB units */
ssize_t downloaded_01_mib = ((downloaded / 1024) * 10) / 1024;
ssize_t length_01_mib = ((length / 1024) * 10) / 1024;
if (downloaded_01_mib == ctx->downloaded)
return;
ctx->downloaded = downloaded_01_mib;
/* Integer and 1 digit fractional part in 1 MiB units */
ssize_t downloaded_mib = downloaded_01_mib / 10;
int downloaded_mib_frac = downloaded_01_mib % 10;
ssize_t length_mib = length_01_mib / 10;
int length_mib_frac = length_01_mib % 10;
printf(
"\rDownloading image: % 3zi.%i / %zi.%i MiB",
downloaded_mib, downloaded_mib_frac,
length_mib, length_mib_frac
);
fflush(stdout);
}
/** Receives data from uclient and writes it to file */
static void recv_image_cb(struct uclient *cl) {
@ -260,12 +287,7 @@ static void recv_image_cb(struct uclient *cl) {
if (len <= 0)
return;
printf(
"\rDownloading image: % 5zi / %zi KiB",
uclient_data(cl)->downloaded / 1024,
uclient_data(cl)->length / 1024
);
fflush(stdout);
update_progress(ctx, uclient_data(cl)->downloaded, uclient_data(cl)->length);
if (write(ctx->fd, buf, len) < len) {
fputs("autoupdater: error: downloading firmware image failed: ", stderr);
@ -349,7 +371,7 @@ static bool autoupdate(const char *mirror, struct settings *s, int lock_fd) {
/* Begin download of the image */
run_dir(download_d_dir);
struct recv_image_ctx image_ctx = { };
struct recv_image_ctx image_ctx = { .downloaded = -1 };
image_ctx.fd = open(firmware_path, O_WRONLY|O_CREAT, 0600);
if (image_ctx.fd < 0) {
fprintf(stderr, "autoupdater: error: failed opening firmware file %s\n", firmware_path);