forked from cory/tildefriends
An experiment in controlling memory usage when syncing. uv_read_stop when we have too active message/blob writes to the database and uv_read_start when we're back under control. #64
This commit is contained in:
59
src/ssb.c
59
src/ssb.c
@ -342,6 +342,8 @@ typedef struct _tf_ssb_connection_t
|
||||
|
||||
tf_ssb_debug_message_t* debug_messages[k_debug_close_message_count];
|
||||
int ref_count;
|
||||
|
||||
int read_back_pressure;
|
||||
} tf_ssb_connection_t;
|
||||
|
||||
static JSClassID _connection_class_id;
|
||||
@ -2062,6 +2064,30 @@ static void _tf_ssb_connection_client_send_hello(tf_ssb_connection_t* connection
|
||||
connection->state = k_tf_ssb_state_sent_hello;
|
||||
}
|
||||
|
||||
static bool _tf_ssb_connection_read_start(tf_ssb_connection_t* connection)
|
||||
{
|
||||
int result = uv_read_start((uv_stream_t*)&connection->tcp, _tf_ssb_connection_on_tcp_alloc, _tf_ssb_connection_on_tcp_recv);
|
||||
if (result && result != UV_EALREADY)
|
||||
{
|
||||
tf_printf("uv_read_start => %s\n", uv_strerror(result));
|
||||
_tf_ssb_connection_close(connection, "uv_read_start failed");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _tf_ssb_connection_read_stop(tf_ssb_connection_t* connection)
|
||||
{
|
||||
int result = uv_read_stop((uv_stream_t*)&connection->tcp);
|
||||
if (result && result != UV_EALREADY)
|
||||
{
|
||||
tf_printf("uv_read_stop => %s\n", uv_strerror(result));
|
||||
_tf_ssb_connection_close(connection, "uv_read_stop failed");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void _tf_ssb_connection_on_connect(uv_connect_t* connect, int status)
|
||||
{
|
||||
tf_ssb_connection_t* connection = connect->data;
|
||||
@ -2069,13 +2095,7 @@ static void _tf_ssb_connection_on_connect(uv_connect_t* connect, int status)
|
||||
if (status == 0)
|
||||
{
|
||||
connection->state = k_tf_ssb_state_connected;
|
||||
int result = uv_read_start(connect->handle, _tf_ssb_connection_on_tcp_alloc, _tf_ssb_connection_on_tcp_recv);
|
||||
if (result)
|
||||
{
|
||||
tf_printf("uv_read_start => %s\n", uv_strerror(status));
|
||||
_tf_ssb_connection_close(connection, "uv_read_start failed");
|
||||
}
|
||||
else
|
||||
if (_tf_ssb_connection_read_start(connection))
|
||||
{
|
||||
_tf_ssb_connection_client_send_hello(connection);
|
||||
}
|
||||
@ -2826,7 +2846,7 @@ static void _tf_ssb_on_connection(uv_stream_t* stream, int status)
|
||||
_tf_ssb_notify_connections_changed(ssb, k_tf_ssb_change_create, connection);
|
||||
|
||||
connection->state = k_tf_ssb_state_server_wait_hello;
|
||||
uv_read_start((uv_stream_t*)&connection->tcp, _tf_ssb_connection_on_tcp_alloc, _tf_ssb_connection_on_tcp_recv);
|
||||
_tf_ssb_connection_read_start(connection);
|
||||
}
|
||||
|
||||
static void _tf_ssb_send_broadcast(tf_ssb_t* ssb, struct sockaddr_in* address, struct sockaddr_in* netmask)
|
||||
@ -4065,3 +4085,26 @@ JSValue tf_ssb_connection_requests_to_object(tf_ssb_connection_t* connection)
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
void tf_ssb_connection_adjust_read_backpressure(tf_ssb_connection_t* connection, int delta)
|
||||
{
|
||||
const int k_threshold = 256;
|
||||
int old_pressure = connection->read_back_pressure;
|
||||
connection->read_back_pressure += delta;
|
||||
if (!connection->closing)
|
||||
{
|
||||
if (old_pressure < k_threshold && connection->read_back_pressure >= k_threshold)
|
||||
{
|
||||
_tf_ssb_connection_read_stop(connection);
|
||||
}
|
||||
else if (old_pressure >= k_threshold && connection->read_back_pressure < k_threshold)
|
||||
{
|
||||
_tf_ssb_connection_read_start(connection);
|
||||
}
|
||||
}
|
||||
connection->ref_count += delta;
|
||||
if (connection->ref_count == 0 && connection->closing)
|
||||
{
|
||||
_tf_ssb_connection_destroy(connection, "backpressure released");
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user