正在显示
8 个修改的文件
包含
457 行增加
和
2 行删除
| @@ -634,6 +634,10 @@ SrsSource::SrsSource(SrsRequest* req) | @@ -634,6 +634,10 @@ SrsSource::SrsSource(SrsRequest* req) | ||
| 634 | 634 | ||
| 635 | _srs_config->subscribe(this); | 635 | _srs_config->subscribe(this); |
| 636 | atc = _srs_config->get_atc(_req->vhost); | 636 | atc = _srs_config->get_atc(_req->vhost); |
| 637 | + | ||
| 638 | +#ifdef SRS_PERF_MW_MSG_IOVS_CACHE | ||
| 639 | + chunk_size = 0; | ||
| 640 | +#endif | ||
| 637 | } | 641 | } |
| 638 | 642 | ||
| 639 | SrsSource::~SrsSource() | 643 | SrsSource::~SrsSource() |
| @@ -860,6 +864,26 @@ int SrsSource::on_reload_vhost_dvr(string vhost) | @@ -860,6 +864,26 @@ int SrsSource::on_reload_vhost_dvr(string vhost) | ||
| 860 | return ret; | 864 | return ret; |
| 861 | } | 865 | } |
| 862 | 866 | ||
| 867 | +int SrsSource::on_reload_vhost_chunk_size(string vhost) | ||
| 868 | +{ | ||
| 869 | + int ret = ERROR_SUCCESS; | ||
| 870 | + | ||
| 871 | + if (_req->vhost != vhost) { | ||
| 872 | + return ret; | ||
| 873 | + } | ||
| 874 | + | ||
| 875 | +#ifdef SRS_PERF_MW_MSG_IOVS_CACHE | ||
| 876 | + int size = _srs_config->get_chunk_size(_req->vhost); | ||
| 877 | + if (chunk_size != size) { | ||
| 878 | + srs_warn("connected clients will error for mic chunk_size changed %d=>%d", | ||
| 879 | + chunk_size, size); | ||
| 880 | + } | ||
| 881 | + chunk_size = size; | ||
| 882 | +#endif | ||
| 883 | + | ||
| 884 | + return ret; | ||
| 885 | +} | ||
| 886 | + | ||
| 863 | int SrsSource::on_reload_vhost_transcode(string vhost) | 887 | int SrsSource::on_reload_vhost_transcode(string vhost) |
| 864 | { | 888 | { |
| 865 | int ret = ERROR_SUCCESS; | 889 | int ret = ERROR_SUCCESS; |
| @@ -1089,6 +1113,14 @@ int SrsSource::on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata | @@ -1089,6 +1113,14 @@ int SrsSource::on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata | ||
| 1089 | } | 1113 | } |
| 1090 | srs_verbose("initialize shared ptr metadata success."); | 1114 | srs_verbose("initialize shared ptr metadata success."); |
| 1091 | 1115 | ||
| 1116 | +#ifdef SRS_PERF_MW_MSG_IOVS_CACHE | ||
| 1117 | + if ((ret = cache_metadata->mic_evaluate(chunk_size)) != ERROR_SUCCESS) { | ||
| 1118 | + srs_error("mic metadata iovs failed, chunk_size=%d. ret=%d", chunk_size, ret); | ||
| 1119 | + return ret; | ||
| 1120 | + } | ||
| 1121 | + srs_info("mic metadata iovs ok, chunk_size=%d", chunk_size); | ||
| 1122 | +#endif | ||
| 1123 | + | ||
| 1092 | // copy to all consumer | 1124 | // copy to all consumer |
| 1093 | if (true) { | 1125 | if (true) { |
| 1094 | std::vector<SrsConsumer*>::iterator it; | 1126 | std::vector<SrsConsumer*>::iterator it; |
| @@ -1130,6 +1162,14 @@ int SrsSource::on_audio(SrsCommonMessage* __audio) | @@ -1130,6 +1162,14 @@ int SrsSource::on_audio(SrsCommonMessage* __audio) | ||
| 1130 | } | 1162 | } |
| 1131 | srs_verbose("initialize shared ptr audio success."); | 1163 | srs_verbose("initialize shared ptr audio success."); |
| 1132 | 1164 | ||
| 1165 | +#ifdef SRS_PERF_MW_MSG_IOVS_CACHE | ||
| 1166 | + if ((ret = msg.mic_evaluate(chunk_size)) != ERROR_SUCCESS) { | ||
| 1167 | + srs_error("mic audio iovs failed, chunk_size=%d. ret=%d", chunk_size, ret); | ||
| 1168 | + return ret; | ||
| 1169 | + } | ||
| 1170 | + srs_info("mic audio iovs ok, chunk_size=%d", chunk_size); | ||
| 1171 | +#endif | ||
| 1172 | + | ||
| 1133 | #ifdef SRS_AUTO_HLS | 1173 | #ifdef SRS_AUTO_HLS |
| 1134 | if ((ret = hls->on_audio(&msg)) != ERROR_SUCCESS) { | 1174 | if ((ret = hls->on_audio(&msg)) != ERROR_SUCCESS) { |
| 1135 | srs_warn("hls process audio message failed, ignore and disable hls. ret=%d", ret); | 1175 | srs_warn("hls process audio message failed, ignore and disable hls. ret=%d", ret); |
| @@ -1240,6 +1280,14 @@ int SrsSource::on_video(SrsCommonMessage* __video) | @@ -1240,6 +1280,14 @@ int SrsSource::on_video(SrsCommonMessage* __video) | ||
| 1240 | } | 1280 | } |
| 1241 | srs_verbose("initialize shared ptr video success."); | 1281 | srs_verbose("initialize shared ptr video success."); |
| 1242 | 1282 | ||
| 1283 | +#ifdef SRS_PERF_MW_MSG_IOVS_CACHE | ||
| 1284 | + if ((ret = msg.mic_evaluate(chunk_size)) != ERROR_SUCCESS) { | ||
| 1285 | + srs_error("mic video iovs failed, chunk_size=%d. ret=%d", chunk_size, ret); | ||
| 1286 | + return ret; | ||
| 1287 | + } | ||
| 1288 | + srs_info("mic video iovs ok, chunk_size=%d", chunk_size); | ||
| 1289 | +#endif | ||
| 1290 | + | ||
| 1243 | #ifdef SRS_AUTO_HLS | 1291 | #ifdef SRS_AUTO_HLS |
| 1244 | if ((ret = hls->on_video(&msg)) != ERROR_SUCCESS) { | 1292 | if ((ret = hls->on_video(&msg)) != ERROR_SUCCESS) { |
| 1245 | srs_warn("hls process video message failed, ignore and disable hls. ret=%d", ret); | 1293 | srs_warn("hls process video message failed, ignore and disable hls. ret=%d", ret); |
| @@ -1491,6 +1539,11 @@ int SrsSource::on_publish() | @@ -1491,6 +1539,11 @@ int SrsSource::on_publish() | ||
| 1491 | return ret; | 1539 | return ret; |
| 1492 | } | 1540 | } |
| 1493 | #endif | 1541 | #endif |
| 1542 | + | ||
| 1543 | +#ifdef SRS_PERF_MW_MSG_IOVS_CACHE | ||
| 1544 | + chunk_size = _srs_config->get_chunk_size(_req->vhost); | ||
| 1545 | + srs_trace("mic use chunk_size=%d to send msgs", chunk_size); | ||
| 1546 | +#endif | ||
| 1494 | 1547 | ||
| 1495 | return ret; | 1548 | return ret; |
| 1496 | } | 1549 | } |
| @@ -352,6 +352,11 @@ private: | @@ -352,6 +352,11 @@ private: | ||
| 352 | std::vector<SrsForwarder*> forwarders; | 352 | std::vector<SrsForwarder*> forwarders; |
| 353 | // for aggregate message | 353 | // for aggregate message |
| 354 | SrsStream* aggregate_stream; | 354 | SrsStream* aggregate_stream; |
| 355 | +#ifdef SRS_PERF_MW_MSG_IOVS_CACHE | ||
| 356 | + // the chunk size for mic, | ||
| 357 | + // update when publish stream. | ||
| 358 | + int chunk_size; | ||
| 359 | +#endif | ||
| 355 | private: | 360 | private: |
| 356 | /** | 361 | /** |
| 357 | * the sample rate of audio in metadata. | 362 | * the sample rate of audio in metadata. |
| @@ -396,6 +401,7 @@ public: | @@ -396,6 +401,7 @@ public: | ||
| 396 | virtual int on_reload_vhost_forward(std::string vhost); | 401 | virtual int on_reload_vhost_forward(std::string vhost); |
| 397 | virtual int on_reload_vhost_hls(std::string vhost); | 402 | virtual int on_reload_vhost_hls(std::string vhost); |
| 398 | virtual int on_reload_vhost_dvr(std::string vhost); | 403 | virtual int on_reload_vhost_dvr(std::string vhost); |
| 404 | + virtual int on_reload_vhost_chunk_size(std::string vhost); | ||
| 399 | virtual int on_reload_vhost_transcode(std::string vhost); | 405 | virtual int on_reload_vhost_transcode(std::string vhost); |
| 400 | // for the tools callback | 406 | // for the tools callback |
| 401 | public: | 407 | public: |
| @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 31 | // current release version | 31 | // current release version |
| 32 | #define VERSION_MAJOR 2 | 32 | #define VERSION_MAJOR 2 |
| 33 | #define VERSION_MINOR 0 | 33 | #define VERSION_MINOR 0 |
| 34 | -#define VERSION_REVISION 60 | 34 | +#define VERSION_REVISION 61 |
| 35 | // server info. | 35 | // server info. |
| 36 | #define RTMP_SIG_SRS_KEY "SRS" | 36 | #define RTMP_SIG_SRS_KEY "SRS" |
| 37 | #define RTMP_SIG_SRS_ROLE "origin/edge server" | 37 | #define RTMP_SIG_SRS_ROLE "origin/edge server" |
| @@ -104,6 +104,15 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -104,6 +104,15 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 104 | */ | 104 | */ |
| 105 | #define SRS_PERF_MW_MSGS 128 | 105 | #define SRS_PERF_MW_MSGS 128 |
| 106 | /** | 106 | /** |
| 107 | +* use iovs cache in each msg, | ||
| 108 | +* for the shared ptr message, we calc once and used for every copy. | ||
| 109 | +* @see https://github.com/winlinvip/simple-rtmp-server/issues/251 | ||
| 110 | +* @remark if enable this, donot use protocol iovs cache. | ||
| 111 | +* @remark when reload change the chunk size, previous clients error. | ||
| 112 | +*/ | ||
| 113 | +#undef SRS_PERF_MW_MSG_IOVS_CACHE | ||
| 114 | + | ||
| 115 | +/** | ||
| 107 | * whether set the socket send buffer size. | 116 | * whether set the socket send buffer size. |
| 108 | * @see https://github.com/winlinvip/simple-rtmp-server/issues/251 | 117 | * @see https://github.com/winlinvip/simple-rtmp-server/issues/251 |
| 109 | */ | 118 | */ |
| @@ -134,6 +134,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -134,6 +134,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 134 | #define ERROR_OpenSslSha256DigestSize 2037 | 134 | #define ERROR_OpenSslSha256DigestSize 2037 |
| 135 | #define ERROR_OpenSslGetPeerPublicKey 2038 | 135 | #define ERROR_OpenSslGetPeerPublicKey 2038 |
| 136 | #define ERROR_OpenSslComputeSharedKey 2039 | 136 | #define ERROR_OpenSslComputeSharedKey 2039 |
| 137 | +#define ERROR_RTMP_MIC_CHUNKSIZE_CHANGED 2040 | ||
| 137 | // | 138 | // |
| 138 | // system control message, | 139 | // system control message, |
| 139 | // not an error, but special control logic. | 140 | // not an error, but special control logic. |
| @@ -149,6 +149,11 @@ void show_macro_features() | @@ -149,6 +149,11 @@ void show_macro_features() | ||
| 149 | #endif | 149 | #endif |
| 150 | srs_trace("system default latency in ms: mw(0-%d) + mr(0-%d) + play-queue(0-%d)", | 150 | srs_trace("system default latency in ms: mw(0-%d) + mr(0-%d) + play-queue(0-%d)", |
| 151 | SRS_PERF_MW_SLEEP, possible_mr_latency, SRS_PERF_PLAY_QUEUE*1000); | 151 | SRS_PERF_MW_SLEEP, possible_mr_latency, SRS_PERF_PLAY_QUEUE*1000); |
| 152 | + | ||
| 153 | +#ifndef SRS_PERF_MW_MSG_IOVS_CACHE | ||
| 154 | + srs_warn("MIC(message iovs cache) enabled, the connected clients will be" | ||
| 155 | + "disconneted when reload changed the chunk_size."); | ||
| 156 | +#endif | ||
| 152 | } | 157 | } |
| 153 | 158 | ||
| 154 | void check_macro_features() | 159 | void check_macro_features() |
| @@ -387,16 +387,110 @@ SrsSharedPtrMessage::__SrsSharedPtr::__SrsSharedPtr() | @@ -387,16 +387,110 @@ SrsSharedPtrMessage::__SrsSharedPtr::__SrsSharedPtr() | ||
| 387 | payload = NULL; | 387 | payload = NULL; |
| 388 | size = 0; | 388 | size = 0; |
| 389 | shared_count = 0; | 389 | shared_count = 0; |
| 390 | + | ||
| 391 | +#ifdef SRS_PERF_MW_MSG_IOVS_CACHE | ||
| 392 | + nb_iovs = 0; | ||
| 393 | + iovs = NULL; | ||
| 394 | + chunk_size = 0; | ||
| 395 | +#endif | ||
| 390 | } | 396 | } |
| 391 | 397 | ||
| 392 | SrsSharedPtrMessage::__SrsSharedPtr::~__SrsSharedPtr() | 398 | SrsSharedPtrMessage::__SrsSharedPtr::~__SrsSharedPtr() |
| 393 | { | 399 | { |
| 394 | srs_freep(payload); | 400 | srs_freep(payload); |
| 401 | + | ||
| 402 | +#ifdef SRS_PERF_MW_MSG_IOVS_CACHE | ||
| 403 | + srs_freep(iovs); | ||
| 404 | +#endif | ||
| 395 | } | 405 | } |
| 396 | 406 | ||
| 407 | +#ifdef SRS_PERF_MW_MSG_IOVS_CACHE | ||
| 408 | +int SrsSharedPtrMessage::__SrsSharedPtr::mic_evaluate( | ||
| 409 | + SrsMessageHeader* mh, int chunk_size | ||
| 410 | +) { | ||
| 411 | + int ret = ERROR_SUCCESS; | ||
| 412 | + | ||
| 413 | + // use the chunk size, shuold not be changed. | ||
| 414 | + this->chunk_size = chunk_size; | ||
| 415 | + | ||
| 416 | + // ignore size | ||
| 417 | + srs_chunk_header(mic_c0, mh, true); | ||
| 418 | + mic_c3 = 0xC0 | (mh->perfer_cid & 0x3F); | ||
| 419 | + | ||
| 420 | + // calc number of iovs | ||
| 421 | + nb_chunks = mh->payload_length / chunk_size; | ||
| 422 | + if (mh->payload_length % chunk_size) { | ||
| 423 | + nb_chunks++; | ||
| 424 | + } | ||
| 425 | + nb_iovs = 1/*cid*/ + 1/*size*/ + 1 /*type*/+ 1/*chunk*/; | ||
| 426 | + // left chunks, always cid+chunk. | ||
| 427 | + if (nb_chunks > 0) { | ||
| 428 | + nb_iovs += (nb_chunks - 1) * 2; | ||
| 429 | + } | ||
| 430 | + | ||
| 431 | + // create iovs | ||
| 432 | + srs_freep(iovs); | ||
| 433 | + iovs = new iovec[nb_iovs]; | ||
| 434 | + | ||
| 435 | + // for payload chunks. | ||
| 436 | + char* p = payload; | ||
| 437 | + char* end = p + size; | ||
| 438 | + iovec* iov = iovs + 0; | ||
| 439 | + while (p < end) { | ||
| 440 | + // size of payload. | ||
| 441 | + int payload_size = srs_min(chunk_size, end - p); | ||
| 442 | + | ||
| 443 | + // header, c0 or c3 | ||
| 444 | + if (p == payload) { | ||
| 445 | + // c0, cid+size+type | ||
| 446 | + // cid, 1B | ||
| 447 | + iov[0].iov_base = mic_c0; | ||
| 448 | + iov[0].iov_len = 1; | ||
| 449 | + | ||
| 450 | + // size(payload length), 3B | ||
| 451 | + iov[1].iov_base = mic_c0 + 4; | ||
| 452 | + iov[1].iov_len = 3; | ||
| 453 | + | ||
| 454 | + // type(message type) | ||
| 455 | + iov[2].iov_base = mic_c0 + 7; | ||
| 456 | + iov[2].iov_len = 1; | ||
| 457 | + | ||
| 458 | + // chunk | ||
| 459 | + iov[3].iov_base = p; | ||
| 460 | + iov[3].iov_len = payload_size; | ||
| 461 | + | ||
| 462 | + // move to next iovs. | ||
| 463 | + iov += 4; | ||
| 464 | + } else { | ||
| 465 | + // c3 | ||
| 466 | + iov[0].iov_base = &mic_c3; | ||
| 467 | + iov[0].iov_len = 1; | ||
| 468 | + | ||
| 469 | + // chunk | ||
| 470 | + iov[1].iov_base = p; | ||
| 471 | + iov[1].iov_len = payload_size; | ||
| 472 | + | ||
| 473 | + // move to next iovs. | ||
| 474 | + iov += 2; | ||
| 475 | + } | ||
| 476 | + | ||
| 477 | + // to next chunk | ||
| 478 | + p += payload_size; | ||
| 479 | + } | ||
| 480 | + | ||
| 481 | + return ret; | ||
| 482 | +} | ||
| 483 | +#endif | ||
| 484 | + | ||
| 397 | SrsSharedPtrMessage::SrsSharedPtrMessage() | 485 | SrsSharedPtrMessage::SrsSharedPtrMessage() |
| 398 | { | 486 | { |
| 399 | ptr = NULL; | 487 | ptr = NULL; |
| 488 | + | ||
| 489 | +#ifdef SRS_PERF_MW_MSG_IOVS_CACHE | ||
| 490 | + mic_etime_present = false; | ||
| 491 | + iovs = NULL; | ||
| 492 | + nb_iovs = 0; | ||
| 493 | +#endif | ||
| 400 | } | 494 | } |
| 401 | 495 | ||
| 402 | SrsSharedPtrMessage::~SrsSharedPtrMessage() | 496 | SrsSharedPtrMessage::~SrsSharedPtrMessage() |
| @@ -408,6 +502,10 @@ SrsSharedPtrMessage::~SrsSharedPtrMessage() | @@ -408,6 +502,10 @@ SrsSharedPtrMessage::~SrsSharedPtrMessage() | ||
| 408 | ptr->shared_count--; | 502 | ptr->shared_count--; |
| 409 | } | 503 | } |
| 410 | } | 504 | } |
| 505 | + | ||
| 506 | +#ifdef SRS_PERF_MW_MSG_IOVS_CACHE | ||
| 507 | + srs_freep(iovs); | ||
| 508 | +#endif | ||
| 411 | } | 509 | } |
| 412 | 510 | ||
| 413 | int SrsSharedPtrMessage::create(SrsCommonMessage* msg) | 511 | int SrsSharedPtrMessage::create(SrsCommonMessage* msg) |
| @@ -479,6 +577,153 @@ SrsSharedPtrMessage* SrsSharedPtrMessage::copy() | @@ -479,6 +577,153 @@ SrsSharedPtrMessage* SrsSharedPtrMessage::copy() | ||
| 479 | return copy; | 577 | return copy; |
| 480 | } | 578 | } |
| 481 | 579 | ||
| 580 | +#ifdef SRS_PERF_MW_MSG_IOVS_CACHE | ||
| 581 | +int SrsSharedPtrMessage::mic_evaluate(int chunk_size) | ||
| 582 | +{ | ||
| 583 | + int ret = ERROR_SUCCESS; | ||
| 584 | + | ||
| 585 | + // when chunk size changed, error to disconnect the client.. | ||
| 586 | + if (ptr->chunk_size > 0 && chunk_size != ptr->chunk_size) { | ||
| 587 | + ret = ERROR_RTMP_MIC_CHUNKSIZE_CHANGED; | ||
| 588 | + srs_warn("mic chunk size changed %d=>%d, ret=%d", | ||
| 589 | + ptr->chunk_size, chunk_size, ret); | ||
| 590 | + return ret; | ||
| 591 | + } | ||
| 592 | + | ||
| 593 | + // calc the shared ptr iovs at the first time. | ||
| 594 | + if (ptr->chunk_size <= 0) { | ||
| 595 | + if ((ret = ptr->mic_evaluate(&header, chunk_size)) != ERROR_SUCCESS) { | ||
| 596 | + srs_warn("mic evaluate source iovs failed. ret=%d", ret); | ||
| 597 | + return ret; | ||
| 598 | + } | ||
| 599 | + } | ||
| 600 | + | ||
| 601 | + // calc the private iovs | ||
| 602 | + char* pp = NULL; | ||
| 603 | + | ||
| 604 | + // timestamp for c0/c3 | ||
| 605 | + u_int32_t timestamp = (u_int32_t)header.timestamp; | ||
| 606 | + mic_etime_present = timestamp >= RTMP_EXTENDED_TIMESTAMP; | ||
| 607 | + | ||
| 608 | + // chunk message header, 11 bytes | ||
| 609 | + // timestamp, 3bytes, big-endian | ||
| 610 | + char* p = mic_c0_time; | ||
| 611 | + if (!mic_etime_present) { | ||
| 612 | + pp = (char*)×tamp; | ||
| 613 | + *p++ = pp[2]; | ||
| 614 | + *p++ = pp[1]; | ||
| 615 | + *p++ = pp[0]; | ||
| 616 | + } else { | ||
| 617 | + *p++ = 0xFF; | ||
| 618 | + *p++ = 0xFF; | ||
| 619 | + *p++ = 0xFF; | ||
| 620 | + } | ||
| 621 | + | ||
| 622 | + // stream_id, 4bytes, little-endian | ||
| 623 | + p = mic_c0_sid; | ||
| 624 | + pp = (char*)&header.stream_id; | ||
| 625 | + *p++ = pp[0]; | ||
| 626 | + *p++ = pp[1]; | ||
| 627 | + *p++ = pp[2]; | ||
| 628 | + *p++ = pp[3]; | ||
| 629 | + | ||
| 630 | + // for c0 | ||
| 631 | + // chunk extended timestamp header, 0 or 4 bytes, big-endian | ||
| 632 | + // | ||
| 633 | + // for c3: | ||
| 634 | + // chunk extended timestamp header, 0 or 4 bytes, big-endian | ||
| 635 | + // 6.1.3. Extended Timestamp | ||
| 636 | + // This field is transmitted only when the normal time stamp in the | ||
| 637 | + // chunk message header is set to 0x00ffffff. If normal time stamp is | ||
| 638 | + // set to any value less than 0x00ffffff, this field MUST NOT be | ||
| 639 | + // present. This field MUST NOT be present if the timestamp field is not | ||
| 640 | + // present. Type 3 chunks MUST NOT have this field. | ||
| 641 | + // adobe changed for Type3 chunk: | ||
| 642 | + // FMLE always sendout the extended-timestamp, | ||
| 643 | + // must send the extended-timestamp to FMS, | ||
| 644 | + // must send the extended-timestamp to flash-player. | ||
| 645 | + // @see: ngx_rtmp_prepare_message | ||
| 646 | + // @see: http://blog.csdn.net/win_lin/article/details/13363699 | ||
| 647 | + // TODO: FIXME: extract to outer. | ||
| 648 | + p = mic_etime; | ||
| 649 | + if (mic_etime_present) { | ||
| 650 | + pp = (char*)×tamp; | ||
| 651 | + *p++ = pp[3]; | ||
| 652 | + *p++ = pp[2]; | ||
| 653 | + *p++ = pp[1]; | ||
| 654 | + *p++ = pp[0]; | ||
| 655 | + } | ||
| 656 | + | ||
| 657 | + // calc number of iovs. | ||
| 658 | + nb_iovs = 1/*time*/ + 1/*sid*/; | ||
| 659 | + // insert etime before all chunks. | ||
| 660 | + if (mic_etime_present) { | ||
| 661 | + nb_iovs += ptr->nb_chunks; | ||
| 662 | + } | ||
| 663 | + | ||
| 664 | + // create iovs | ||
| 665 | + srs_freep(iovs); | ||
| 666 | + iovs = new iovec[nb_iovs]; | ||
| 667 | + | ||
| 668 | + // time, 3B | ||
| 669 | + iovs[0].iov_base = mic_c0_time; | ||
| 670 | + iovs[0].iov_len = 3; | ||
| 671 | + | ||
| 672 | + // sid, 4B | ||
| 673 | + iovs[1].iov_base = mic_c0_sid; | ||
| 674 | + iovs[1].iov_len = 4; | ||
| 675 | + | ||
| 676 | + // etime, 4B for each chunks. | ||
| 677 | + for (int i = 2; i < nb_iovs; i++) { | ||
| 678 | + iovs[i].iov_base = mic_etime; | ||
| 679 | + iovs[i].iov_len = 4; | ||
| 680 | + } | ||
| 681 | + | ||
| 682 | + return ret; | ||
| 683 | +} | ||
| 684 | + | ||
| 685 | +int SrsSharedPtrMessage::mic_iovs_count() | ||
| 686 | +{ | ||
| 687 | + return nb_iovs + ptr->nb_iovs; | ||
| 688 | +} | ||
| 689 | + | ||
| 690 | +int SrsSharedPtrMessage::mic_iovs_dump(iovec* _iovs, int _nb_iovs) | ||
| 691 | +{ | ||
| 692 | + int shared_index = 0; | ||
| 693 | + int private_index = 0; | ||
| 694 | + int index = 0; | ||
| 695 | + | ||
| 696 | + // dumps all. | ||
| 697 | + srs_assert(nb_iovs + ptr->nb_iovs <= _nb_iovs); | ||
| 698 | + | ||
| 699 | + // dump the c0 chunk | ||
| 700 | + _iovs[index++] = ptr->iovs[shared_index++]; // cid | ||
| 701 | + _iovs[index++] = iovs[private_index++]; // time | ||
| 702 | + _iovs[index++] = ptr->iovs[shared_index++]; // size | ||
| 703 | + _iovs[index++] = ptr->iovs[shared_index++]; // type | ||
| 704 | + _iovs[index++] = iovs[private_index++]; // sid | ||
| 705 | + if (mic_etime_present) { | ||
| 706 | + _iovs[index++] = iovs[private_index++]; // etime | ||
| 707 | + } | ||
| 708 | + _iovs[index++] = ptr->iovs[shared_index++]; // chunk | ||
| 709 | + | ||
| 710 | + // dump left c3 chunks | ||
| 711 | + for (int i = 1; i < ptr->nb_chunks; i++) { | ||
| 712 | + _iovs[index++] = ptr->iovs[shared_index++]; // cid | ||
| 713 | + if (mic_etime_present) { | ||
| 714 | + _iovs[index++] = iovs[private_index++]; // etime | ||
| 715 | + } | ||
| 716 | + _iovs[index++] = ptr->iovs[shared_index++]; // chunk | ||
| 717 | + } | ||
| 718 | + | ||
| 719 | + srs_assert(index == private_index + shared_index); | ||
| 720 | + srs_assert(index == nb_iovs + ptr->nb_iovs); | ||
| 721 | + srs_assert(index <= _nb_iovs); | ||
| 722 | + | ||
| 723 | + return nb_iovs + ptr->nb_iovs; | ||
| 724 | +} | ||
| 725 | +#endif | ||
| 726 | + | ||
| 482 | SrsProtocol::AckWindowSize::AckWindowSize() | 727 | SrsProtocol::AckWindowSize::AckWindowSize() |
| 483 | { | 728 | { |
| 484 | ack_window_size = 0; | 729 | ack_window_size = 0; |
| @@ -498,8 +743,10 @@ SrsProtocol::SrsProtocol(ISrsProtocolReaderWriter* io) | @@ -498,8 +743,10 @@ SrsProtocol::SrsProtocol(ISrsProtocolReaderWriter* io) | ||
| 498 | // each chunk consumers atleast 2 iovs | 743 | // each chunk consumers atleast 2 iovs |
| 499 | srs_assert(nb_out_iovs >= 2); | 744 | srs_assert(nb_out_iovs >= 2); |
| 500 | 745 | ||
| 746 | +#ifndef SRS_PERF_MW_MSG_IOVS_CACHE | ||
| 501 | warned_c0c3_cache_dry = false; | 747 | warned_c0c3_cache_dry = false; |
| 502 | auto_response_when_recv = true; | 748 | auto_response_when_recv = true; |
| 749 | +#endif | ||
| 503 | 750 | ||
| 504 | cs_cache = NULL; | 751 | cs_cache = NULL; |
| 505 | if (SRS_PERF_CHUNK_STREAM_CACHE > 0) { | 752 | if (SRS_PERF_CHUNK_STREAM_CACHE > 0) { |
| @@ -707,6 +954,7 @@ int SrsProtocol::do_send_messages(SrsSharedPtrMessage** msgs, int nb_msgs) | @@ -707,6 +954,7 @@ int SrsProtocol::do_send_messages(SrsSharedPtrMessage** msgs, int nb_msgs) | ||
| 707 | { | 954 | { |
| 708 | int ret = ERROR_SUCCESS; | 955 | int ret = ERROR_SUCCESS; |
| 709 | 956 | ||
| 957 | +#ifndef SRS_PERF_MW_MSG_IOVS_CACHE | ||
| 710 | // TODO: FIXME: use cache system instead. | 958 | // TODO: FIXME: use cache system instead. |
| 711 | int iov_index = 0; | 959 | int iov_index = 0; |
| 712 | iovec* iov = out_iovs + iov_index; | 960 | iovec* iov = out_iovs + iov_index; |
| @@ -811,6 +1059,40 @@ int SrsProtocol::do_send_messages(SrsSharedPtrMessage** msgs, int nb_msgs) | @@ -811,6 +1059,40 @@ int SrsProtocol::do_send_messages(SrsSharedPtrMessage** msgs, int nb_msgs) | ||
| 811 | } | 1059 | } |
| 812 | } | 1060 | } |
| 813 | } | 1061 | } |
| 1062 | +#else | ||
| 1063 | + // send all iovs for all msgs. | ||
| 1064 | + int total_iovs = 0; | ||
| 1065 | + for (int i = 0; i < nb_msgs; i++) { | ||
| 1066 | + SrsSharedPtrMessage* msg = msgs[i]; | ||
| 1067 | + if ((ret = msg->mic_evaluate(out_chunk_size)) != ERROR_SUCCESS) { | ||
| 1068 | + srs_error("mic evaluate failed, chunk=%d. ret=%d", out_chunk_size, ret); | ||
| 1069 | + return ret; | ||
| 1070 | + } | ||
| 1071 | + total_iovs += msg->mic_iovs_count(); | ||
| 1072 | + } | ||
| 1073 | + srs_verbose("mic nb_iovs=%d, max=%d", total_iovs, nb_out_iovs); | ||
| 1074 | + | ||
| 1075 | + // realloc the iovs if exceed, | ||
| 1076 | + // for we donot know how many messges maybe to send entirely, | ||
| 1077 | + // we just alloc the iovs, it's ok. | ||
| 1078 | + if (total_iovs > nb_out_iovs) { | ||
| 1079 | + srs_warn("resize iovs %d => %d, msgs=%d, max_msgs=%d", | ||
| 1080 | + nb_out_iovs, total_iovs, nb_msgs, SRS_PERF_MW_MSGS); | ||
| 1081 | + | ||
| 1082 | + nb_out_iovs = total_iovs; | ||
| 1083 | + int realloc_size = sizeof(iovec) * nb_out_iovs; | ||
| 1084 | + out_iovs = (iovec*)realloc(out_iovs, realloc_size); | ||
| 1085 | + } | ||
| 1086 | + | ||
| 1087 | + // dumps iovs | ||
| 1088 | + int iov_index = 0; | ||
| 1089 | + for (int i = 0; i < nb_msgs; i++) { | ||
| 1090 | + SrsSharedPtrMessage* msg = msgs[i]; | ||
| 1091 | + iov_index += msg->mic_iovs_dump( | ||
| 1092 | + out_iovs + iov_index, nb_out_iovs - iov_index | ||
| 1093 | + ); | ||
| 1094 | + } | ||
| 1095 | +#endif | ||
| 814 | 1096 | ||
| 815 | // maybe the iovs already sendout when c0c3 cache dry, | 1097 | // maybe the iovs already sendout when c0c3 cache dry, |
| 816 | // so just ignore when no iovs to send. | 1098 | // so just ignore when no iovs to send. |
| @@ -824,11 +1106,21 @@ int SrsProtocol::do_send_messages(SrsSharedPtrMessage** msgs, int nb_msgs) | @@ -824,11 +1106,21 @@ int SrsProtocol::do_send_messages(SrsSharedPtrMessage** msgs, int nb_msgs) | ||
| 824 | iovec* iov = out_iovs + i; | 1106 | iovec* iov = out_iovs + i; |
| 825 | nb_bytes += iov->iov_len; | 1107 | nb_bytes += iov->iov_len; |
| 826 | } | 1108 | } |
| 1109 | + #ifndef SRS_PERF_MW_MSG_IOVS_CACHE | ||
| 827 | srs_info("mw %d msgs %dB in %d iovs, max_msgs=%d, nb_out_iovs=%d", | 1110 | srs_info("mw %d msgs %dB in %d iovs, max_msgs=%d, nb_out_iovs=%d", |
| 828 | nb_msgs, nb_bytes, iov_index, SRS_PERF_MW_MSGS, nb_out_iovs); | 1111 | nb_msgs, nb_bytes, iov_index, SRS_PERF_MW_MSGS, nb_out_iovs); |
| 1112 | + #else | ||
| 1113 | + srs_info("mic nb_iovs=%d, max=%d, msgs=%d %dB", | ||
| 1114 | + total_iovs, nb_out_iovs, nb_msgs, nb_bytes); | ||
| 1115 | + #endif | ||
| 829 | #else | 1116 | #else |
| 1117 | + #ifndef SRS_PERF_MW_MSG_IOVS_CACHE | ||
| 830 | srs_info("mw %d msgs in %d iovs, max_msgs=%d, nb_out_iovs=%d", | 1118 | srs_info("mw %d msgs in %d iovs, max_msgs=%d, nb_out_iovs=%d", |
| 831 | nb_msgs, iov_index, SRS_PERF_MW_MSGS, nb_out_iovs); | 1119 | nb_msgs, iov_index, SRS_PERF_MW_MSGS, nb_out_iovs); |
| 1120 | + #else | ||
| 1121 | + srs_info("mic nb_iovs=%d, max=%d, msgs=%d", | ||
| 1122 | + total_iovs, nb_out_iovs, nb_msgs); | ||
| 1123 | + #endif | ||
| 832 | #endif | 1124 | #endif |
| 833 | 1125 | ||
| 834 | // the limits of writev iovs. | 1126 | // the limits of writev iovs. |
| @@ -214,14 +214,82 @@ private: | @@ -214,14 +214,82 @@ private: | ||
| 214 | class __SrsSharedPtr | 214 | class __SrsSharedPtr |
| 215 | { | 215 | { |
| 216 | public: | 216 | public: |
| 217 | + // actual shared payload. | ||
| 217 | char* payload; | 218 | char* payload; |
| 219 | + // size of payload. | ||
| 218 | int size; | 220 | int size; |
| 221 | + // the reference count | ||
| 219 | int shared_count; | 222 | int shared_count; |
| 220 | - | 223 | + public: |
| 224 | + // the iovs cache in shared ptr message. | ||
| 225 | + // @see https://github.com/winlinvip/simple-rtmp-server/issues/251 | ||
| 226 | + #ifdef SRS_PERF_MW_MSG_IOVS_CACHE | ||
| 227 | + /** | ||
| 228 | + * the mic(msg iovs cache). | ||
| 229 | + * why share the cache in msg? | ||
| 230 | + * all msgs of a source are same for: | ||
| 231 | + * 1. cid, all use the same cid, copy from src msg. | ||
| 232 | + * 2. size, all msg size never changed. | ||
| 233 | + * 3. type, type never changed. | ||
| 234 | + * 4. chunk size, all connections in a vhost use the same chunk size. | ||
| 235 | + * the different: | ||
| 236 | + * 1. time and etime, almost different. | ||
| 237 | + * 2. stream id, maybe different, but almost the same. | ||
| 238 | + * @remark, when reload change the chunk size, clients will be disconnected. | ||
| 239 | + */ | ||
| 240 | + // the c0 shared section for all msgs | ||
| 241 | + // 1. cid, 1B, same. | ||
| 242 | + // 2. [*]time, 3B, not same. | ||
| 243 | + // 3. size, 3B, same. | ||
| 244 | + // 4. type, 1B, same. | ||
| 245 | + // 5. [*]stream id, 4B, not same, little-endian. | ||
| 246 | + // 6. [*]etime, 4B, not same. | ||
| 247 | + // the stared field must be calced in each msg. | ||
| 248 | + char mic_c0[16]; | ||
| 249 | + // the c3 headers. | ||
| 250 | + char mic_c3; | ||
| 251 | + // the calced iovs for all msg, | ||
| 252 | + // we assumpt that the chunk size is not changed for a vhost, | ||
| 253 | + // if do changed, the client will got an error msg and disconnect. | ||
| 254 | + iovec* iovs; | ||
| 255 | + int nb_iovs; | ||
| 256 | + // the msgs source chunk size, | ||
| 257 | + // which is evaluated the iovs first time, | ||
| 258 | + // this cannot be changed. | ||
| 259 | + int chunk_size; | ||
| 260 | + // the number of chunks. | ||
| 261 | + int nb_chunks; | ||
| 262 | + #endif | ||
| 263 | + public: | ||
| 221 | __SrsSharedPtr(); | 264 | __SrsSharedPtr(); |
| 222 | virtual ~__SrsSharedPtr(); | 265 | virtual ~__SrsSharedPtr(); |
| 266 | + public: | ||
| 267 | + #ifdef SRS_PERF_MW_MSG_IOVS_CACHE | ||
| 268 | + /** | ||
| 269 | + * for iovs msg cache, calc the iovs. | ||
| 270 | + * @param chunk_size use the specified chunk size to evaluate the iovs. | ||
| 271 | + */ | ||
| 272 | + virtual int mic_evaluate(SrsMessageHeader* mh, int chunk_size); | ||
| 273 | + #endif | ||
| 223 | }; | 274 | }; |
| 224 | __SrsSharedPtr* ptr; | 275 | __SrsSharedPtr* ptr; |
| 276 | +private: | ||
| 277 | + // msgs level cache. | ||
| 278 | +#ifdef SRS_PERF_MW_MSG_IOVS_CACHE | ||
| 279 | + // the c0 private section for this | ||
| 280 | + // 1. time, 3B, not same, not used. | ||
| 281 | + // 2. stream id, 4B, almost the same, little-endian. | ||
| 282 | + // 3. etime, 4B, optional, always same for all chunk when present. | ||
| 283 | + // the stared field must be calced in each msg. | ||
| 284 | + char mic_c0_time[3]; | ||
| 285 | + char mic_c0_sid[4]; | ||
| 286 | + char mic_etime[4]; | ||
| 287 | + // whether etime present. | ||
| 288 | + bool mic_etime_present; | ||
| 289 | + // the calced private iovs for this msg | ||
| 290 | + iovec* iovs; | ||
| 291 | + int nb_iovs; | ||
| 292 | +#endif | ||
| 225 | public: | 293 | public: |
| 226 | SrsSharedPtrMessage(); | 294 | SrsSharedPtrMessage(); |
| 227 | virtual ~SrsSharedPtrMessage(); | 295 | virtual ~SrsSharedPtrMessage(); |
| @@ -253,6 +321,23 @@ public: | @@ -253,6 +321,23 @@ public: | ||
| 253 | * @remark, assert object is created. | 321 | * @remark, assert object is created. |
| 254 | */ | 322 | */ |
| 255 | virtual SrsSharedPtrMessage* copy(); | 323 | virtual SrsSharedPtrMessage* copy(); |
| 324 | +public: | ||
| 325 | +#ifdef SRS_PERF_MW_MSG_IOVS_CACHE | ||
| 326 | + /** | ||
| 327 | + * for iovs msg cache, calc the iovs. | ||
| 328 | + * @param chunk_size use the specified chunk size to evaluate the iovs. | ||
| 329 | + */ | ||
| 330 | + virtual int mic_evaluate(int chunk_size); | ||
| 331 | + /** | ||
| 332 | + * count the total iovs needed. | ||
| 333 | + */ | ||
| 334 | + virtual int mic_iovs_count(); | ||
| 335 | + /** | ||
| 336 | + * dump all iovs, the _nb_iovs must equals to mic_iovs_count(). | ||
| 337 | + * @return the dumped count. | ||
| 338 | + */ | ||
| 339 | + virtual int mic_iovs_dump(iovec* _iovs, int _nb_iovs); | ||
| 340 | +#endif | ||
| 256 | }; | 341 | }; |
| 257 | 342 | ||
| 258 | /** | 343 | /** |
| @@ -326,6 +411,9 @@ private: | @@ -326,6 +411,9 @@ private: | ||
| 326 | */ | 411 | */ |
| 327 | iovec* out_iovs; | 412 | iovec* out_iovs; |
| 328 | int nb_out_iovs; | 413 | int nb_out_iovs; |
| 414 | + // if use iovs cache in each msg, | ||
| 415 | + // donot use protocol level c0c3 cache. | ||
| 416 | +#ifndef SRS_PERF_MW_MSG_IOVS_CACHE | ||
| 329 | /** | 417 | /** |
| 330 | * output header cache. | 418 | * output header cache. |
| 331 | * used for type0, 11bytes(or 15bytes with extended timestamp) header. | 419 | * used for type0, 11bytes(or 15bytes with extended timestamp) header. |
| @@ -337,6 +425,7 @@ private: | @@ -337,6 +425,7 @@ private: | ||
| 337 | char out_c0c3_caches[SRS_CONSTS_C0C3_HEADERS_MAX]; | 425 | char out_c0c3_caches[SRS_CONSTS_C0C3_HEADERS_MAX]; |
| 338 | // whether warned user to increase the c0c3 header cache. | 426 | // whether warned user to increase the c0c3 header cache. |
| 339 | bool warned_c0c3_cache_dry; | 427 | bool warned_c0c3_cache_dry; |
| 428 | +#endif | ||
| 340 | /** | 429 | /** |
| 341 | * output chunk size, default to 128, set by config. | 430 | * output chunk size, default to 128, set by config. |
| 342 | */ | 431 | */ |
-
请 注册 或 登录 后发表评论