1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

for bug #217, use isolate thread to improve 17% performance.

This commit is contained in:
winlin 2014-11-22 15:53:05 +08:00
parent d3c770d252
commit 622218c4dd
7 changed files with 286 additions and 62 deletions

View file

@ -415,6 +415,7 @@ SrsProtocol::SrsProtocol(ISrsProtocolReaderWriter* io)
srs_assert(nb_out_iovs >= 2);
warned_c0c3_cache_dry = false;
auto_response_when_recv = true;
}
SrsProtocol::~SrsProtocol()
@ -430,6 +431,15 @@ SrsProtocol::~SrsProtocol()
chunk_streams.clear();
}
if (true) {
std::vector<SrsPacket*>::iterator it;
for (it = manual_response_queue.begin(); it != manual_response_queue.end(); ++it) {
SrsPacket* pkt = *it;
srs_freep(pkt);
}
manual_response_queue.clear();
}
srs_freep(in_buffer);
// alloc by malloc, use free directly.
@ -439,6 +449,35 @@ SrsProtocol::~SrsProtocol()
}
}
void SrsProtocol::set_auto_response(bool v)
{
auto_response_when_recv = v;
}
int SrsProtocol::manual_response_flush()
{
int ret = ERROR_SUCCESS;
if (manual_response_queue.empty()) {
return ret;
}
std::vector<SrsPacket*>::iterator it;
for (it = manual_response_queue.begin(); it != manual_response_queue.end();) {
SrsPacket* pkt = *it;
// erase this packet, the send api always free it.
it = manual_response_queue.erase(it);
// use underlayer api to send, donot flush again.
if ((ret = do_send_and_free_packet(pkt, 0)) != ERROR_SUCCESS) {
return ret;
}
}
return ret;
}
void SrsProtocol::set_recv_timeout(int64_t timeout_us)
{
return skt->set_recv_timeout(timeout_us);
@ -638,7 +677,9 @@ int SrsProtocol::do_send_messages(SrsMessage** msgs, int nb_msgs)
// when c0c3 cache dry,
// sendout all messages and reset the cache, then send again.
if ((ret = skt->writev(out_iovs, iov_index, NULL)) != ERROR_SUCCESS) {
srs_error("send with writev failed. ret=%d", ret);
if (!srs_is_client_gracefully_close(ret)) {
srs_error("send with writev failed. ret=%d", ret);
}
return ret;
}
@ -663,13 +704,57 @@ int SrsProtocol::do_send_messages(SrsMessage** msgs, int nb_msgs)
// sendout header and payload by writev.
// decrease the sys invoke count to get higher performance.
if ((ret = skt->writev(out_iovs, iov_index, NULL)) != ERROR_SUCCESS) {
srs_error("send with writev failed. ret=%d", ret);
if (!srs_is_client_gracefully_close(ret)) {
srs_error("send with writev failed. ret=%d", ret);
}
return ret;
}
return ret;
}
int SrsProtocol::do_send_and_free_packet(SrsPacket* packet, int stream_id)
{
int ret = ERROR_SUCCESS;
srs_assert(packet);
SrsAutoFree(SrsPacket, packet);
int size = 0;
char* payload = NULL;
if ((ret = packet->encode(size, payload)) != ERROR_SUCCESS) {
srs_error("encode RTMP packet to bytes oriented RTMP message failed. ret=%d", ret);
return ret;
}
// encode packet to payload and size.
if (size <= 0 || payload == NULL) {
srs_warn("packet is empty, ignore empty message.");
return ret;
}
// to message
SrsMessage* msg = new SrsCommonMessage();
msg->payload = payload;
msg->size = size;
msg->header.payload_length = size;
msg->header.message_type = packet->get_message_type();
msg->header.stream_id = stream_id;
msg->header.perfer_cid = packet->get_prefer_cid();
// donot use the auto free to free the msg,
// for performance issue.
ret = do_send_messages(&msg, 1);
if (ret == ERROR_SUCCESS) {
ret = on_send_packet(msg, packet);
}
srs_freep(msg);
return ret;
}
void SrsProtocol::generate_chunk_header(char* cache, SrsMessageHeader* mh, bool c0, int* pnbh, char** ph)
{
// to directly set the field.
@ -948,6 +1033,16 @@ int SrsProtocol::send_and_free_messages(SrsMessage** msgs, int nb_msgs, int stre
srs_freep(msg);
}
// donot flush when send failed
if (ret != ERROR_SUCCESS) {
return ret;
}
// flush messages in manual queue
if ((ret = manual_response_flush()) != ERROR_SUCCESS) {
return ret;
}
return ret;
}
@ -955,41 +1050,15 @@ int SrsProtocol::send_and_free_packet(SrsPacket* packet, int stream_id)
{
int ret = ERROR_SUCCESS;
srs_assert(packet);
SrsAutoFree(SrsPacket, packet);
int size = 0;
char* payload = NULL;
if ((ret = packet->encode(size, payload)) != ERROR_SUCCESS) {
srs_error("encode RTMP packet to bytes oriented RTMP message failed. ret=%d", ret);
if ((ret = do_send_and_free_packet(packet, stream_id)) != ERROR_SUCCESS) {
return ret;
}
// encode packet to payload and size.
if (size <= 0 || payload == NULL) {
srs_warn("packet is empty, ignore empty message.");
// flush messages in manual queue
if ((ret = manual_response_flush()) != ERROR_SUCCESS) {
return ret;
}
// to message
SrsMessage* msg = new SrsCommonMessage();
msg->payload = payload;
msg->size = size;
msg->header.payload_length = size;
msg->header.message_type = packet->get_message_type();
msg->header.stream_id = stream_id;
msg->header.perfer_cid = packet->get_prefer_cid();
// donot use the auto free to free the msg,
// for performance issue.
ret = do_send_messages(&msg, 1);
if (ret == ERROR_SUCCESS) {
ret = on_send_packet(msg, packet);
}
srs_freep(msg);
return ret;
}
@ -1698,7 +1767,15 @@ int SrsProtocol::response_acknowledgement_message()
SrsAcknowledgementPacket* pkt = new SrsAcknowledgementPacket();
in_ack_size.acked_size = skt->get_recv_bytes();
pkt->sequence_number = (int32_t)in_ack_size.acked_size;
if ((ret = send_and_free_packet(pkt, 0)) != ERROR_SUCCESS) {
// cache the message and use flush to send.
if (!auto_response_when_recv) {
manual_response_queue.push_back(pkt);
return ret;
}
// use underlayer api to send, donot flush again.
if ((ret = do_send_and_free_packet(pkt, 0)) != ERROR_SUCCESS) {
srs_error("send acknowledgement failed. ret=%d", ret);
return ret;
}
@ -1718,7 +1795,14 @@ int SrsProtocol::response_ping_message(int32_t timestamp)
pkt->event_type = SrcPCUCPingResponse;
pkt->event_data = timestamp;
if ((ret = send_and_free_packet(pkt, 0)) != ERROR_SUCCESS) {
// cache the message and use flush to send.
if (!auto_response_when_recv) {
manual_response_queue.push_back(pkt);
return ret;
}
// use underlayer api to send, donot flush again.
if ((ret = do_send_and_free_packet(pkt, 0)) != ERROR_SUCCESS) {
srs_error("send ping response failed. ret=%d", ret);
return ret;
}