Skip to content

Commit 25eb21e

Browse files
bluestnwinlinvip
andauthored
Improve file writer performance by fwrite with cache. v5.0.133 (#3308)
* SrsFileWriter leverages libc buffer to boost dvr write speed. * Refactor SrsFileWriter to use libc file functions mockable * Add utest and refine code. Co-authored-by: winlin <[email protected]>
1 parent fb17902 commit 25eb21e

File tree

9 files changed

+358
-62
lines changed

9 files changed

+358
-62
lines changed

trunk/doc/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ The changelog for SRS.
88

99
## SRS 5.0 Changelog
1010

11+
* v5.0, 2023-01-08, Merge [#3308](https://github.com/ossrs/srs/pull/3308): DVR: Improve file write performance by fwrite with cache. v5.0.133
1112
* v5.0, 2023-01-06, DVR: Support blackbox test based on hooks. v5.0.132
1213
* v5.0, 2023-01-06, FFmpeg: Support build with FFmpeg native opus. v5.0.131 (#3140)
1314
* v5.0, 2023-01-05, CORS: Refine HTTP CORS headers. v5.0.130

trunk/src/app/srs_app_dvr.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ using namespace std;
2626
#include <srs_kernel_mp4.hpp>
2727
#include <srs_app_fragment.hpp>
2828

29+
#define SRS_FWRITE_CACHE_SIZE 65536
30+
2931
SrsDvrSegmenter::SrsDvrSegmenter()
3032
{
3133
req = NULL;
@@ -95,6 +97,11 @@ srs_error_t SrsDvrSegmenter::open()
9597
return srs_error_wrap(err, "open file %s", path.c_str());
9698
}
9799

100+
// Set libc file write cache buffer size
101+
if ((err = fs->set_iobuf_size(SRS_FWRITE_CACHE_SIZE)) != srs_success) {
102+
return srs_error_wrap(err, "set iobuf size for file %s", path.c_str());
103+
}
104+
98105
// initialize the encoder.
99106
if ((err = open_encoder()) != srs_success) {
100107
return srs_error_wrap(err, "open encoder");

trunk/src/core/srs_core_version5.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@
99

1010
#define VERSION_MAJOR 5
1111
#define VERSION_MINOR 0
12-
#define VERSION_REVISION 132
12+
#define VERSION_REVISION 133
1313

1414
#endif

trunk/src/kernel/srs_kernel_error.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@
105105
XX(ERROR_BACKTRACE_PARSE_NOT_SUPPORT , 1092, "BacktraceParseNotSupport", "Backtrace parse not supported") \
106106
XX(ERROR_BACKTRACE_PARSE_OFFSET , 1093, "BacktraceParseOffset", "Parse backtrace offset failed") \
107107
XX(ERROR_BACKTRACE_ADDR2LINE , 1094, "BacktraceAddr2Line", "Backtrace addr2line failed") \
108+
XX(ERROR_SYSTEM_FILE_NOT_OPEN , 1095, "FileNotOpen", "File is not opened") \
109+
XX(ERROR_SYSTEM_FILE_SETVBUF , 1096, "FileSetVBuf", "Failed to set file vbuf") \
108110

109111
/**************************************************/
110112
/* RTMP protocol error. */

trunk/src/kernel/srs_kernel_file.cpp

Lines changed: 66 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -26,32 +26,57 @@ srs_read_t _srs_read_fn = ::read;
2626
srs_lseek_t _srs_lseek_fn = ::lseek;
2727
srs_close_t _srs_close_fn = ::close;
2828

29+
srs_fopen_t _srs_fopen_fn = ::fopen;
30+
srs_fwrite_t _srs_fwrite_fn = ::fwrite;
31+
srs_fread_t _srs_fread_fn = ::fread;
32+
srs_fseek_t _srs_fseek_fn = ::fseek;
33+
srs_fclose_t _srs_fclose_fn = ::fclose;
34+
srs_ftell_t _srs_ftell_fn = ::ftell;
35+
srs_setvbuf_t _srs_setvbuf_fn = ::setvbuf;
36+
2937
SrsFileWriter::SrsFileWriter()
3038
{
31-
fd = -1;
39+
fp_ = NULL;
40+
buf_ = NULL;
3241
}
3342

3443
SrsFileWriter::~SrsFileWriter()
3544
{
3645
close();
46+
srs_freepa(buf_);
47+
}
48+
49+
srs_error_t SrsFileWriter::set_iobuf_size(int size)
50+
{
51+
srs_error_t err = srs_success;
52+
53+
if (fp_ == NULL) {
54+
return srs_error_new(ERROR_SYSTEM_FILE_NOT_OPEN, "file %s is not opened", path_.c_str());
55+
}
56+
57+
srs_freepa(buf_);
58+
buf_ = size > 0 ? new char[size] : NULL;
59+
int r0 = _srs_setvbuf_fn(fp_, buf_, _IOFBF, size);
60+
if (r0) {
61+
return srs_error_new(ERROR_SYSTEM_FILE_SETVBUF, "setvbuf err, file=%s, r0=%d", path_.c_str(), r0);
62+
}
63+
64+
return err;
3765
}
3866

3967
srs_error_t SrsFileWriter::open(string p)
4068
{
4169
srs_error_t err = srs_success;
4270

43-
if (fd > 0) {
71+
if (fp_ != NULL) {
4472
return srs_error_new(ERROR_SYSTEM_FILE_ALREADY_OPENED, "file %s already opened", p.c_str());
4573
}
4674

47-
int flags = O_CREAT|O_WRONLY|O_TRUNC;
48-
mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH;
49-
50-
if ((fd = _srs_open_fn(p.c_str(), flags, mode)) < 0) {
75+
if ((fp_ = _srs_fopen_fn(p.c_str(), "wb")) == NULL) {
5176
return srs_error_new(ERROR_SYSTEM_FILE_OPENE, "open file %s failed", p.c_str());
5277
}
5378

54-
path = p;
79+
path_ = p;
5580

5681
return err;
5782
}
@@ -60,70 +85,70 @@ srs_error_t SrsFileWriter::open_append(string p)
6085
{
6186
srs_error_t err = srs_success;
6287

63-
if (fd > 0) {
64-
return srs_error_new(ERROR_SYSTEM_FILE_ALREADY_OPENED, "file %s already opened", path.c_str());
88+
if (fp_ != NULL) {
89+
return srs_error_new(ERROR_SYSTEM_FILE_ALREADY_OPENED, "file %s already opened", p.c_str());
6590
}
6691

67-
int flags = O_CREAT|O_APPEND|O_WRONLY;
68-
mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH;
69-
70-
if ((fd = _srs_open_fn(p.c_str(), flags, mode)) < 0) {
92+
if ((fp_ = _srs_fopen_fn(p.c_str(), "ab")) == NULL) {
7193
return srs_error_new(ERROR_SYSTEM_FILE_OPENE, "open file %s failed", p.c_str());
7294
}
7395

74-
path = p;
96+
path_ = p;
7597

7698
return err;
7799
}
78100

79101
void SrsFileWriter::close()
80102
{
81-
if (fd < 0) {
103+
if (fp_ == NULL) {
82104
return;
83105
}
84106

85-
if (_srs_close_fn(fd) < 0) {
86-
srs_warn("close file %s failed", path.c_str());
107+
if (_srs_fclose_fn(fp_) < 0) {
108+
srs_warn("close file %s failed", path_.c_str());
87109
}
88-
fd = -1;
110+
fp_ = NULL;
89111

90112
return;
91113
}
92114

93115
bool SrsFileWriter::is_open()
94116
{
95-
return fd > 0;
117+
return fp_ != NULL;
96118
}
97119

98120
void SrsFileWriter::seek2(int64_t offset)
99121
{
100-
off_t r0 = _srs_lseek_fn(fd, (off_t)offset, SEEK_SET);
122+
srs_assert(is_open());
123+
124+
int r0 = _srs_fseek_fn(fp_, (long)offset, SEEK_SET);
101125
srs_assert(r0 != -1);
102126
}
103127

104128
int64_t SrsFileWriter::tellg()
105129
{
106-
return (int64_t)_srs_lseek_fn(fd, 0, SEEK_CUR);
130+
srs_assert(is_open());
131+
132+
return _srs_ftell_fn(fp_);
107133
}
108134

109135
srs_error_t SrsFileWriter::write(void* buf, size_t count, ssize_t* pnwrite)
110136
{
111137
srs_error_t err = srs_success;
112-
113-
ssize_t nwrite;
114-
// TODO: FIXME: use st_write.
115-
#ifdef _WIN32
116-
if ((nwrite = ::_write(fd, buf, (unsigned int)count)) < 0) {
117-
#else
118-
if ((nwrite = _srs_write_fn(fd, buf, count)) < 0) {
119-
#endif
120-
return srs_error_new(ERROR_SYSTEM_FILE_WRITE, "write to file %s failed", path.c_str());
138+
139+
if (fp_ == NULL) {
140+
return srs_error_new(ERROR_SYSTEM_FILE_NOT_OPEN, "file %s is not opened", path_.c_str());
121141
}
122142

143+
size_t n = _srs_fwrite_fn(buf, 1, count, fp_);
144+
if (n != count) {
145+
return srs_error_new(ERROR_SYSTEM_FILE_WRITE, "write to file %s failed", path_.c_str());
146+
}
147+
123148
if (pnwrite != NULL) {
124-
*pnwrite = nwrite;
149+
*pnwrite = (ssize_t)n;
125150
}
126-
151+
127152
return err;
128153
}
129154

@@ -136,29 +161,30 @@ srs_error_t SrsFileWriter::writev(const iovec* iov, int iovcnt, ssize_t* pnwrite
136161
const iovec* piov = iov + i;
137162
ssize_t this_nwrite = 0;
138163
if ((err = write(piov->iov_base, piov->iov_len, &this_nwrite)) != srs_success) {
139-
return srs_error_wrap(err, "write file");
164+
return srs_error_wrap(err, "writev");
140165
}
141166
nwrite += this_nwrite;
142167
}
143-
168+
144169
if (pnwrite) {
145170
*pnwrite = nwrite;
146171
}
147-
172+
148173
return err;
149174
}
150175

151176
srs_error_t SrsFileWriter::lseek(off_t offset, int whence, off_t* seeked)
152177
{
153-
off_t sk = _srs_lseek_fn(fd, offset, whence);
154-
if (sk < 0) {
178+
srs_assert(is_open());
179+
180+
if (_srs_fseek_fn(fp_, (long)offset, whence) == -1) {
155181
return srs_error_new(ERROR_SYSTEM_FILE_SEEK, "seek file");
156182
}
157-
183+
158184
if (seeked) {
159-
*seeked = sk;
185+
*seeked = _srs_ftell_fn(fp_);
160186
}
161-
187+
162188
return srs_success;
163189
}
164190

trunk/src/kernel/srs_kernel_file.hpp

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,18 @@ class SrsFileReader;
2626
class SrsFileWriter : public ISrsWriteSeeker
2727
{
2828
private:
29-
std::string path;
30-
int fd;
29+
std::string path_;
30+
FILE *fp_;
31+
char *buf_;
3132
public:
3233
SrsFileWriter();
3334
virtual ~SrsFileWriter();
3435
public:
36+
/**
37+
* set io buf size
38+
*/
39+
virtual srs_error_t set_iobuf_size(int size);
40+
3541
/**
3642
* open file writer, in truncate mode.
3743
* @param p a string indicates the path of file to open.
@@ -110,5 +116,16 @@ typedef ssize_t (*srs_read_t)(int fildes, void* buf, size_t nbyte);
110116
typedef off_t (*srs_lseek_t)(int fildes, off_t offset, int whence);
111117
typedef int (*srs_close_t)(int fildes);
112118

119+
120+
typedef FILE* (*srs_fopen_t)(const char* path, const char* mode);
121+
typedef size_t (*srs_fwrite_t)(const void* ptr, size_t size, size_t nitems,
122+
FILE* stream);
123+
typedef size_t (*srs_fread_t)(void* ptr, size_t size, size_t nitems,
124+
FILE* stream);
125+
typedef int (*srs_fseek_t)(FILE* stream, long offset, int whence);
126+
typedef int (*srs_fclose_t)(FILE* stream);
127+
typedef long (*srs_ftell_t)(FILE* stream);
128+
typedef int (*srs_setvbuf_t)(FILE* stream, char* buf, int type, size_t size);
129+
113130
#endif
114131

0 commit comments

Comments
 (0)