继续操作前请注册或者登录。
winlin

for #405, improve the HTT FLV to 3k. 2.0.169

@@ -716,7 +716,8 @@ The play HTTP FLV benchmark by [SB](https://github.com/simple-rtmp-server/srs-be @@ -716,7 +716,8 @@ The play HTTP FLV benchmark by [SB](https://github.com/simple-rtmp-server/srs-be
716 | Update | SRS | Clients | Type | CPU | Memory | Commit | 716 | Update | SRS | Clients | Type | CPU | Memory | Commit |
717 | ------------- | --------- | ------------- | ------------- | --------- | -------- | ------------ | 717 | ------------- | --------- | ------------- | ------------- | --------- | -------- | ------------ |
718 | 2014-05-24 | 2.0.167 | 1.0k(1000) | players | 82% | 86MB | - | 718 | 2014-05-24 | 2.0.167 | 1.0k(1000) | players | 82% | 86MB | - |
719 -| 2014-05-24 | 2.0.168 | 2.3k(2300) | players | 92% | 276MB | - | 719 +| 2014-05-24 | 2.0.168 | 2.3k(2300) | players | 92% | 276MB | [code][p17] |
  720 +| 2014-05-24 | 2.0.169 | 3.0k(3000) | players | 94% | 188MB | [code][p18] |
720 721
721 ### Latency benchmark 722 ### Latency benchmark
722 723
@@ -832,6 +833,7 @@ Winlin @@ -832,6 +833,7 @@ Winlin
832 [p14]: https://github.com/simple-rtmp-server/srs/commit/10297fab519811845b549a8af40a6bcbd23411e8 833 [p14]: https://github.com/simple-rtmp-server/srs/commit/10297fab519811845b549a8af40a6bcbd23411e8
833 [p15]: https://github.com/simple-rtmp-server/srs/commit/0d6b91039d408328caab31a1077d56a809b6bebc 834 [p15]: https://github.com/simple-rtmp-server/srs/commit/0d6b91039d408328caab31a1077d56a809b6bebc
834 [p16]: https://github.com/simple-rtmp-server/srs/commit/0d6b91039d408328caab31a1077d56a809b6bebc 835 [p16]: https://github.com/simple-rtmp-server/srs/commit/0d6b91039d408328caab31a1077d56a809b6bebc
  836 +[p17]: https://github.com/simple-rtmp-server/srs/commit/fc995473eb02c7cf64b5b212b456e11f34aa7984
835 837
836 [authors]: https://github.com/simple-rtmp-server/srs/blob/develop/AUTHORS.txt 838 [authors]: https://github.com/simple-rtmp-server/srs/blob/develop/AUTHORS.txt
837 [bigthanks]: https://github.com/simple-rtmp-server/srs/wiki/v1_CN_Product#bigthanks 839 [bigthanks]: https://github.com/simple-rtmp-server/srs/wiki/v1_CN_Product#bigthanks
@@ -98,8 +98,14 @@ int SrsHttpResponseWriter::write(char* data, int size) @@ -98,8 +98,14 @@ int SrsHttpResponseWriter::write(char* data, int size)
98 98
99 if (!header_wrote) { 99 if (!header_wrote) {
100 write_header(SRS_CONSTS_HTTP_OK); 100 write_header(SRS_CONSTS_HTTP_OK);
  101 +
  102 + if ((ret = send_header(data, size)) != ERROR_SUCCESS) {
  103 + srs_error("http: send header failed. ret=%d", ret);
  104 + return ret;
  105 + }
101 } 106 }
102 107
  108 + // check the bytes send and content length.
103 written += size; 109 written += size;
104 if (content_length != -1 && written > content_length) { 110 if (content_length != -1 && written > content_length) {
105 ret = ERROR_HTTP_CONTENT_LENGTH; 111 ret = ERROR_HTTP_CONTENT_LENGTH;
@@ -107,11 +113,6 @@ int SrsHttpResponseWriter::write(char* data, int size) @@ -107,11 +113,6 @@ int SrsHttpResponseWriter::write(char* data, int size)
107 return ret; 113 return ret;
108 } 114 }
109 115
110 - if ((ret = send_header(data, size)) != ERROR_SUCCESS) {  
111 - srs_error("http: send header failed. ret=%d", ret);  
112 - return ret;  
113 - }  
114 -  
115 // ignore NULL content. 116 // ignore NULL content.
116 if (!data) { 117 if (!data) {
117 return ret; 118 return ret;
@@ -143,6 +144,71 @@ int SrsHttpResponseWriter::write(char* data, int size) @@ -143,6 +144,71 @@ int SrsHttpResponseWriter::write(char* data, int size)
143 return ret; 144 return ret;
144 } 145 }
145 146
  147 +int SrsHttpResponseWriter::writev(iovec* iov, int iovcnt, ssize_t* pnwrite)
  148 +{
  149 + int ret = ERROR_SUCCESS;
  150 +
  151 + // when header not ready, or not chunked, send one by one.
  152 + if (!header_wrote || content_length != -1) {
  153 + ssize_t nwrite = 0;
  154 + for (int i = 0; i < iovcnt; i++) {
  155 + iovec* piovc = iov + i;
  156 + nwrite += piovc->iov_len;
  157 + if ((ret = write((char*)piovc->iov_base, (int)piovc->iov_len)) != ERROR_SUCCESS) {
  158 + return ret;
  159 + }
  160 + }
  161 +
  162 + if (pnwrite) {
  163 + *pnwrite = nwrite;
  164 + }
  165 +
  166 + return ret;
  167 + }
  168 +
  169 + // ignore NULL content.
  170 + if (iovcnt <= 0) {
  171 + return ret;
  172 + }
  173 +
  174 + // send in chunked encoding.
  175 + int nb_iovss = iovcnt * 4;
  176 + iovec* iovss = new iovec[nb_iovss];
  177 + SrsAutoFree(iovec, iovss);
  178 +
  179 + char* pheader_cache = header_cache;
  180 + for (int i = 0; i < iovcnt; i++) {
  181 + int left = SRS_HTTP_HEADER_CACHE_SIZE - (int)(pheader_cache - header_cache);
  182 + srs_assert(left > 0);
  183 +
  184 + iovec* data_iov = iov + i;
  185 + int nb_size = snprintf(pheader_cache, left, "%x", (int)data_iov->iov_len);
  186 +
  187 + iovec* iovs = iovss + (i * 4);
  188 + iovs[0].iov_base = (char*)pheader_cache;
  189 + iovs[0].iov_len = (int)nb_size;
  190 + iovs[1].iov_base = (char*)SRS_HTTP_CRLF;
  191 + iovs[1].iov_len = 2;
  192 + iovs[2].iov_base = (char*)data_iov->iov_base;
  193 + iovs[2].iov_len = (int)data_iov->iov_len;
  194 + iovs[3].iov_base = (char*)SRS_HTTP_CRLF;
  195 + iovs[3].iov_len = 2;
  196 +
  197 + pheader_cache += nb_size;
  198 + }
  199 +
  200 + ssize_t nwrite;
  201 + if ((ret = skt->writev(iovss, nb_iovss, &nwrite)) != ERROR_SUCCESS) {
  202 + return ret;
  203 + }
  204 +
  205 + if (pnwrite) {
  206 + *pnwrite = nwrite;
  207 + }
  208 +
  209 + return ret;
  210 +}
  211 +
146 void SrsHttpResponseWriter::write_header(int code) 212 void SrsHttpResponseWriter::write_header(int code)
147 { 213 {
148 if (header_wrote) { 214 if (header_wrote) {
@@ -1513,6 +1579,11 @@ int SrsStreamWriter::write(void* buf, size_t count, ssize_t* pnwrite) @@ -1513,6 +1579,11 @@ int SrsStreamWriter::write(void* buf, size_t count, ssize_t* pnwrite)
1513 return writer->write((char*)buf, (int)count); 1579 return writer->write((char*)buf, (int)count);
1514 } 1580 }
1515 1581
  1582 +int SrsStreamWriter::writev(iovec* iov, int iovcnt, ssize_t* pnwrite)
  1583 +{
  1584 + return writer->writev(iov, iovcnt, pnwrite);
  1585 +}
  1586 +
1516 SrsLiveStream::SrsLiveStream(SrsSource* s, SrsRequest* r, SrsStreamCache* c) 1587 SrsLiveStream::SrsLiveStream(SrsSource* s, SrsRequest* r, SrsStreamCache* c)
1517 { 1588 {
1518 source = s; 1589 source = s;
@@ -71,7 +71,11 @@ class SrsHttpMessage; @@ -71,7 +71,11 @@ class SrsHttpMessage;
71 71
72 #ifdef SRS_AUTO_HTTP_PARSER 72 #ifdef SRS_AUTO_HTTP_PARSER
73 73
74 -#define SRS_HTTP_HEADER_CACHE_SIZE 16 74 +// for HTTP FLV, each video/audio packet is send by 3 iovs,
  75 +// while each iov is send by 4 sub iovs, that is needs 3 chunk header,
  76 +// suppose each header is 16 length, 3*16=48 is ok.
  77 +// that is, 512 can used for 16 iovs to send.
  78 +#define SRS_HTTP_HEADER_CACHE_SIZE 512
75 79
76 /** 80 /**
77 * response writer use st socket 81 * response writer use st socket
@@ -105,6 +109,7 @@ public: @@ -105,6 +109,7 @@ public:
105 virtual int final_request(); 109 virtual int final_request();
106 virtual SrsHttpHeader* header(); 110 virtual SrsHttpHeader* header();
107 virtual int write(char* data, int size); 111 virtual int write(char* data, int size);
  112 + virtual int writev(iovec* iov, int iovcnt, ssize_t* pnwrite);
108 virtual void write_header(int code); 113 virtual void write_header(int code);
109 virtual int send_header(char* data, int size); 114 virtual int send_header(char* data, int size);
110 }; 115 };
@@ -541,6 +546,7 @@ public: @@ -541,6 +546,7 @@ public:
541 virtual int64_t tellg(); 546 virtual int64_t tellg();
542 public: 547 public:
543 virtual int write(void* buf, size_t count, ssize_t* pnwrite); 548 virtual int write(void* buf, size_t count, ssize_t* pnwrite);
  549 + virtual int writev(iovec* iov, int iovcnt, ssize_t* pnwrite);
544 }; 550 };
545 551
546 /** 552 /**
@@ -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 168 34 +#define VERSION_REVISION 169
35 35
36 // server info. 36 // server info.
37 #define RTMP_SIG_SRS_KEY "SRS" 37 #define RTMP_SIG_SRS_KEY "SRS"
@@ -30,6 +30,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -30,6 +30,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 30
31 #include <fcntl.h> 31 #include <fcntl.h>
32 #include <sstream> 32 #include <sstream>
  33 +#include <sys/uio.h>
33 using namespace std; 34 using namespace std;
34 35
35 #include <srs_kernel_log.hpp> 36 #include <srs_kernel_log.hpp>
@@ -145,6 +146,27 @@ int SrsFileWriter::write(void* buf, size_t count, ssize_t* pnwrite) @@ -145,6 +146,27 @@ int SrsFileWriter::write(void* buf, size_t count, ssize_t* pnwrite)
145 return ret; 146 return ret;
146 } 147 }
147 148
  149 +int SrsFileWriter::writev(iovec* iov, int iovcnt, ssize_t* pnwrite)
  150 +{
  151 + int ret = ERROR_SUCCESS;
  152 +
  153 + ssize_t nwrite = 0;
  154 + for (int i = 0; i < iovcnt; i++) {
  155 + iovec* piov = iov + i;
  156 + ssize_t this_nwrite = 0;
  157 + if ((ret = write(piov->iov_base, piov->iov_len, &this_nwrite)) != ERROR_SUCCESS) {
  158 + return ret;
  159 + }
  160 + nwrite += this_nwrite;
  161 + }
  162 +
  163 + if (pnwrite) {
  164 + *pnwrite = nwrite;
  165 + }
  166 +
  167 + return ret;
  168 +}
  169 +
148 SrsFileReader::SrsFileReader() 170 SrsFileReader::SrsFileReader()
149 { 171 {
150 fd = -1; 172 fd = -1;
@@ -31,6 +31,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -31,6 +31,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 31
32 #include <string> 32 #include <string>
33 33
  34 +// for srs-librtmp, @see https://github.com/simple-rtmp-server/srs/issues/213
  35 +#ifndef _WIN32
  36 +#include <sys/uio.h>
  37 +#endif
  38 +
34 /** 39 /**
35 * file writer, to write to file. 40 * file writer, to write to file.
36 */ 41 */
@@ -62,6 +67,11 @@ public: @@ -62,6 +67,11 @@ public:
62 * @param pnwrite the output nb_write, NULL to ignore. 67 * @param pnwrite the output nb_write, NULL to ignore.
63 */ 68 */
64 virtual int write(void* buf, size_t count, ssize_t* pnwrite); 69 virtual int write(void* buf, size_t count, ssize_t* pnwrite);
  70 + /**
  71 + * for the HTTP FLV, to writev to improve performance.
  72 + * @see https://github.com/simple-rtmp-server/srs/issues/405
  73 + */
  74 + virtual int writev(iovec* iov, int iovcnt, ssize_t* pnwrite);
65 }; 75 };
66 76
67 /** 77 /**
@@ -223,31 +223,24 @@ int SrsFlvEncoder::write_tag(char* header, int header_size, char* tag, int tag_s @@ -223,31 +223,24 @@ int SrsFlvEncoder::write_tag(char* header, int header_size, char* tag, int tag_s
223 { 223 {
224 int ret = ERROR_SUCCESS; 224 int ret = ERROR_SUCCESS;
225 225
226 - // write tag header.  
227 - if ((ret = _fs->write(header, header_size, NULL)) != ERROR_SUCCESS) {  
228 - if (!srs_is_client_gracefully_close(ret)) {  
229 - srs_error("write flv tag header failed. ret=%d", ret);  
230 - }  
231 - return ret;  
232 - }  
233 -  
234 - // write tag data.  
235 - if ((ret = _fs->write(tag, tag_size, NULL)) != ERROR_SUCCESS) {  
236 - if (!srs_is_client_gracefully_close(ret)) {  
237 - srs_error("write flv tag failed. ret=%d", ret);  
238 - }  
239 - return ret;  
240 - }  
241 -  
242 // PreviousTagSizeN UI32 Size of last tag, including its header, in bytes. 226 // PreviousTagSizeN UI32 Size of last tag, including its header, in bytes.
243 char pre_size[SRS_FLV_PREVIOUS_TAG_SIZE]; 227 char pre_size[SRS_FLV_PREVIOUS_TAG_SIZE];
244 if ((ret = tag_stream->initialize(pre_size, SRS_FLV_PREVIOUS_TAG_SIZE)) != ERROR_SUCCESS) { 228 if ((ret = tag_stream->initialize(pre_size, SRS_FLV_PREVIOUS_TAG_SIZE)) != ERROR_SUCCESS) {
245 return ret; 229 return ret;
246 } 230 }
247 tag_stream->write_4bytes(tag_size + header_size); 231 tag_stream->write_4bytes(tag_size + header_size);
248 - if ((ret = _fs->write(pre_size, sizeof(pre_size), NULL)) != ERROR_SUCCESS) { 232 +
  233 + iovec iovs[3];
  234 + iovs[0].iov_base = header;
  235 + iovs[0].iov_len = header_size;
  236 + iovs[1].iov_base = tag;
  237 + iovs[1].iov_len = tag_size;
  238 + iovs[2].iov_base = pre_size;
  239 + iovs[2].iov_len = sizeof(SRS_FLV_PREVIOUS_TAG_SIZE);
  240 +
  241 + if ((ret = _fs->writev(iovs, 3, NULL)) != ERROR_SUCCESS) {
249 if (!srs_is_client_gracefully_close(ret)) { 242 if (!srs_is_client_gracefully_close(ret)) {
250 - srs_error("write flv previous tag size failed. ret=%d", ret); 243 + srs_error("write flv tag failed. ret=%d", ret);
251 } 244 }
252 return ret; 245 return ret;
253 } 246 }
@@ -33,6 +33,11 @@ @@ -33,6 +33,11 @@
33 #include <string> 33 #include <string>
34 #include <vector> 34 #include <vector>
35 35
  36 +// for srs-librtmp, @see https://github.com/simple-rtmp-server/srs/issues/213
  37 +#ifndef _WIN32
  38 +#include <sys/uio.h>
  39 +#endif
  40 +
36 class SrsFileReader; 41 class SrsFileReader;
37 class SrsHttpHeader; 42 class SrsHttpHeader;
38 class ISrsHttpMessage; 43 class ISrsHttpMessage;
@@ -188,6 +193,11 @@ public: @@ -188,6 +193,11 @@ public:
188 // the initial 512 bytes of written data to DetectContentType. 193 // the initial 512 bytes of written data to DetectContentType.
189 // @param data, the data to send. NULL to flush header only. 194 // @param data, the data to send. NULL to flush header only.
190 virtual int write(char* data, int size) = 0; 195 virtual int write(char* data, int size) = 0;
  196 + /**
  197 + * for the HTTP FLV, to writev to improve performance.
  198 + * @see https://github.com/simple-rtmp-server/srs/issues/405
  199 + */
  200 + virtual int writev(iovec* iov, int iovcnt, ssize_t* pnwrite) = 0;
191 201
192 // WriteHeader sends an HTTP response header with status code. 202 // WriteHeader sends an HTTP response header with status code.
193 // If WriteHeader is not called explicitly, the first call to Write 203 // If WriteHeader is not called explicitly, the first call to Write