Skip to content

Commit

Permalink
update: Pick servers based on the average of the last 5 ping measurem…
Browse files Browse the repository at this point in the history
…ents. [V]

At least in my test case, this (very arbitrary) value provided enough of
a buffer against the ping time spikes that happen from time to time.

Unfortunately, this is also as fast as we can possibly go right now,
with wininet lacking support for either HTTP/1.1 pipelining or HTTP/2,
and the console model expecting a linear sequence of downloads. (Or do
you *really* want multiple parallel downloads being logged all over the
place?)
  • Loading branch information
nmlgc committed Apr 20, 2017
1 parent cd12f20 commit fcb8a32
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 9 deletions.
33 changes: 29 additions & 4 deletions thcrap_update/src/update.cpp
Expand Up @@ -145,6 +145,30 @@ void http_exit(void)

/// Internal C++ server connection handling
/// ---------------------------------------
LONGLONG server_t::ping_average() const
{
LONGLONG ret = 0;
int divisor = 0;
for(auto i : this->ping) {
ret += i;
if(i != 0) {
divisor++;
}
}
if(divisor == 0) {
return 0;
}
return ret / divisor;
}

void server_t::ping_push(LONGLONG newval)
{
auto type_size = sizeof(this->ping[0]);
auto elements = sizeof(this->ping) / type_size;
memmove(&this->ping[0], &this->ping[1], (elements - 1) * type_size);
ping[elements - 1] = newval;
}

void* server_t::download(
DWORD *file_size, get_result_t *ret, const char *fn, const DWORD *exp_crc
)
Expand Down Expand Up @@ -228,7 +252,7 @@ void* server_t::download(
"(%d b, %.1f + %.1f ms)\n",
*file_size, diff_ping_ms, diff_transfer_ms
);
this->ping = diff_ping;
this->ping_push(diff_ping);

if(exp_crc) {
auto crc = crc32(0, ctx.file_buffer, ctx.file_size);
Expand All @@ -254,8 +278,9 @@ int servers_t::get_first() const
// Get fastest server from previous data
for(i = 0; i < this->size(); i++) {
const auto &server = (*this)[i];
if(server.visited() && server.ping < last_time) {
last_time = server.ping;
auto ping_average = server.ping_average();
if(server.visited() && ping_average < last_time) {
last_time = ping_average;
fastest = i;
} else if(server.unused()) {
tryout = i;
Expand Down Expand Up @@ -324,7 +349,7 @@ void servers_t::from(const json_t *servers)
json_t *val = json_array_get(servers, i);
assert(json_is_string(val));
(*this)[i].url = json_string_value(val);
(*this)[i].ping = 0;
(*this)[i].new_session();
}
}

Expand Down
25 changes: 20 additions & 5 deletions thcrap_update/src/update.h
Expand Up @@ -68,16 +68,28 @@ struct server_t {
// compiler.
const char *url = NULL;

// Last 5 ping times of this server.
// The raw counter value is enough for our purposes, no need to lose
// precision by dividing through the frequency.
LONGLONG ping = 0;
LONGLONG ping[5];

bool active() const { return ping >= 0; }
bool unused() const { return ping == 0; }
bool visited() const { return ping > 0; }
LONGLONG ping_average() const;
void ping_push(LONGLONG newval);

bool active() const { return this->ping_average() >= 0; }
bool unused() const { return this->ping_average() == 0; }
bool visited() const { return this->ping_average() > 0; }

void disable() {
this->ping = -1;
for(auto& i : this->ping) {
i = -1;
}
}

void new_session() {
for(auto& i : this->ping) {
i = 0;
}
}

// Single-server part of servers_t::download().
Expand All @@ -89,6 +101,9 @@ struct server_t {
}

server_t(const char *_url) : url(_url) {
// TODO: For consistency, ping should be initialized with {0},
// but Visual Studio 2013 doesn't implement this.
new_session();
}
};

Expand Down

0 comments on commit fcb8a32

Please sign in to comment.