Skip to content

Commit de836b5

Browse files
matyhtfhuanghantao
andauthored
Optimize send to worker from master (#3910)
* Optimize the process of sending data from master to worker * Fix * Update * Fix * Optimize test * Fix reactor buffer append * optimeize code * fix tests * fix tests [2] * optimize code * fix tests * fix tests[4] * fix tests[5] * fix tests[6] * add const * fix tests * fix tests [7] Co-authored-by: codinghuang <[email protected]>
1 parent d70d45a commit de836b5

File tree

19 files changed

+307
-74
lines changed

19 files changed

+307
-74
lines changed

core-tests/src/memory/buffer.cpp

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
+----------------------------------------------------------------------+
3+
| Swoole |
4+
+----------------------------------------------------------------------+
5+
| This source file is subject to version 2.0 of the Apache license, |
6+
| that is bundled with this package in the file LICENSE, and is |
7+
| available through the world-wide-web at the following url: |
8+
| http://www.apache.org/licenses/LICENSE-2.0.html |
9+
| If you did not receive a copy of the Apache2.0 license and are unable|
10+
| to obtain it through the world-wide-web, please send a note to |
11+
| [email protected] so we can mail you a copy immediately. |
12+
+----------------------------------------------------------------------+
13+
| @link https://www.swoole.com/ |
14+
| @contact [email protected] |
15+
| @license https://github.com/swoole/swoole-src/blob/master/LICENSE |
16+
| @author Tianfeng Han <[email protected]> |
17+
+----------------------------------------------------------------------+
18+
*/
19+
20+
#include "test_core.h"
21+
#include "swoole_memory.h"
22+
#include "swoole_buffer.h"
23+
24+
using namespace std;
25+
using namespace swoole;
26+
27+
TEST(buffer, append_iov) {
28+
Buffer buf(1024);
29+
30+
int iovcnt = 4;
31+
iovec v[iovcnt];
32+
33+
v[0].iov_len = swoole_rand(99, 4095);
34+
v[1].iov_len = swoole_rand(99, 4095);
35+
v[2].iov_len = swoole_rand(99, 4095);
36+
v[3].iov_len = swoole_rand(99, 4095);
37+
38+
unique_ptr<char> s1(new char[v[0].iov_len]);
39+
unique_ptr<char> s2(new char[v[1].iov_len]);
40+
unique_ptr<char> s3(new char[v[2].iov_len]);
41+
unique_ptr<char> s4(new char[v[3].iov_len]);
42+
43+
v[0].iov_base = s1.get();
44+
v[1].iov_base = s2.get();
45+
v[2].iov_base = s3.get();
46+
v[3].iov_base = s4.get();
47+
48+
memset(v[0].iov_base, 'A', v[0].iov_len);
49+
memset(v[1].iov_base, 'B', v[1].iov_len);
50+
memset(v[2].iov_base, 'C', v[2].iov_len);
51+
memset(v[3].iov_base, 'D', v[3].iov_len);
52+
53+
buf.append(v, iovcnt, 0);
54+
55+
ASSERT_EQ(buf.length(), v[0].iov_len + v[1].iov_len + v[2].iov_len+ v[3].iov_len);
56+
57+
String str(buf.length());
58+
59+
while(!buf.empty()) {
60+
auto chunk = buf.front();
61+
str.append(chunk->value.ptr, chunk->length);
62+
buf.pop();
63+
}
64+
65+
size_t offset = 0;
66+
67+
SW_LOOP_N (iovcnt) {
68+
ASSERT_EQ(memcmp(str.str + offset, v[i].iov_base, v[i].iov_len), 0);
69+
offset += v[i].iov_len;
70+
}
71+
}

ext-src/swoole_http2_client_coro.cc

+2-2
Original file line numberDiff line numberDiff line change
@@ -919,7 +919,7 @@ int Client::parse_header(Stream *stream, int flags, char *in, size_t inlen) {
919919
inlen -= (size_t) rv;
920920

921921
swTraceLog(SW_TRACE_HTTP2,
922-
"[" SW_ECHO_GREEN "] %.*s[%d]: %.*s[%d]",
922+
"[" SW_ECHO_GREEN "] %.*s[%lu]: %.*s[%lu]",
923923
"HEADER",
924924
(int) nv.namelen,
925925
nv.name,
@@ -1297,7 +1297,7 @@ bool Client::send_goaway_frame(zend_long error_code, const char *debug_data, siz
12971297
memcpy(frame + SW_HTTP2_FRAME_HEADER_SIZE + SW_HTTP2_GOAWAY_SIZE, debug_data, debug_data_len);
12981298
}
12991299
swTraceLog(SW_TRACE_HTTP2,
1300-
"[" SW_ECHO_GREEN "] Send: last-sid=%d, error-code=%d",
1300+
"[" SW_ECHO_GREEN "] Send: last-sid=%u, error-code=%ld",
13011301
swHttp2_get_type(SW_HTTP2_TYPE_GOAWAY),
13021302
last_stream_id,
13031303
error_code);

ext-src/swoole_http_server.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ int php_swoole_http_onReceive(Server *serv, RecvData *req) {
7070
php_swoole_get_recv_data(serv, zdata, req);
7171

7272
swTraceLog(SW_TRACE_SERVER,
73-
"http request from %d with %d bytes: <<EOF\n%.*s\nEOF",
73+
"http request from %ld with %d bytes: <<EOF\n%.*s\nEOF",
7474
session_id,
7575
(int) Z_STRLEN_P(zdata),
7676
(int) Z_STRLEN_P(zdata),

include/swoole_api.h

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ SW_API int swoole_event_set(swoole::network::Socket *socket, int events);
4343
SW_API int swoole_event_del(swoole::network::Socket *socket);
4444
SW_API void swoole_event_defer(swoole::Callback cb, void *private_data);
4545
SW_API ssize_t swoole_event_write(swoole::network::Socket *socket, const void *data, size_t len);
46+
SW_API ssize_t swoole_event_writev(swoole::network::Socket *socket, const iovec *iov, size_t iovcnt);
4647
SW_API int swoole_event_wait();
4748
SW_API int swoole_event_free();
4849
SW_API bool swoole_event_set_handler(int fdtype, swoole::ReactorHandler handler);

include/swoole_buffer.h

+6
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#pragma once
1818

1919
#include <queue>
20+
#include <sys/uio.h>
2021

2122
namespace swoole {
2223

@@ -61,6 +62,7 @@ class Buffer {
6162

6263
void pop();
6364
void append(const void *data, uint32_t size);
65+
void append(const struct iovec *iov, size_t iovcnt, off_t offset);
6466

6567
uint32_t length() {
6668
return total_length;
@@ -70,6 +72,10 @@ class Buffer {
7072
return queue_.size();
7173
}
7274

75+
bool empty() {
76+
return queue_.empty();
77+
}
78+
7379
static bool empty(Buffer *buffer) {
7480
return buffer == nullptr || buffer->queue_.empty();
7581
}

include/swoole_reactor.h

+2
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ class Reactor {
167167
std::function<void(Reactor *)> onBegin;
168168

169169
int (*write)(Reactor *reactor, network::Socket *socket, const void *buf, size_t n) = nullptr;
170+
int (*writev)(Reactor *reactor, network::Socket *socket, const iovec *iov, size_t iovcnt) = nullptr;
170171
int (*close)(Reactor *reactor, network::Socket *socket) = nullptr;
171172

172173
private:
@@ -324,6 +325,7 @@ class Reactor {
324325
}
325326

326327
static int _write(Reactor *reactor, network::Socket *socket, const void *buf, size_t n);
328+
static int _writev(Reactor *reactor, network::Socket *socket, const iovec *iov, size_t iovcnt);
327329
static int _close(Reactor *reactor, network::Socket *socket);
328330
static int _writable_callback(Reactor *reactor, Event *ev);
329331

include/swoole_server.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -1180,9 +1180,10 @@ class Server {
11801180
static int dispatch_task(Protocol *proto, network::Socket *_socket, const char *data, uint32_t length);
11811181

11821182
int send_to_connection(SendData *);
1183-
ssize_t send_to_worker_from_master(Worker *worker, const void *data, size_t len);
1183+
ssize_t send_to_worker_from_master(Worker *worker, const iovec *iov, size_t iovcnt);
11841184
ssize_t send_to_worker_from_worker(Worker *dst_worker, const void *buf, size_t len, int flags);
1185-
ssize_t send_to_reactor_thread(EventData *ev_data, size_t sendn, SessionId session_id);
1185+
ssize_t send_to_reactor_thread(const EventData *ev_data, size_t sendn, SessionId session_id);
1186+
ssize_t send_to_reactor_thread(const DataHead *head, const iovec *iov, size_t iovcnt, SessionId session_id);
11861187
int reply_task_result(const char *data, size_t data_len, int flags, EventData *current_task);
11871188

11881189
bool send(SessionId session_id, const void *data, uint32_t length);

include/swoole_socket.h

+6
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ struct IOVector {
117117
~IOVector();
118118

119119
void update_iterator(ssize_t __n);
120+
120121
inline struct iovec *get_iterator() {
121122
return iov_iterator;
122123
}
@@ -306,6 +307,10 @@ struct Socket {
306307
ssize_t readv(IOVector *io_vector);
307308
ssize_t writev(IOVector *io_vector);
308309

310+
ssize_t writev(const struct iovec *iov, size_t iovcnt) {
311+
return ::writev(fd, iov, iovcnt);
312+
}
313+
309314
int bind(const Address &sa) {
310315
return ::bind(fd, &sa.addr.ss, sizeof(sa.addr.ss));
311316
}
@@ -319,6 +324,7 @@ struct Socket {
319324
ssize_t send_async(const void *__data, size_t __len);
320325
ssize_t recv_blocking(void *__data, size_t __len, int flags);
321326
int sendfile_blocking(const char *filename, off_t offset, size_t length, double timeout);
327+
ssize_t writev_blocking(const struct iovec *iov, size_t iovcnt);
322328

323329
inline int connect(const Address &sa) {
324330
return ::connect(fd, &sa.addr.ss, sa.len);

include/swoole_string.h

+9
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,15 @@ class String {
159159
}
160160
}
161161

162+
String *substr(size_t offset, size_t len) {
163+
if (offset + len > length) {
164+
return nullptr;
165+
}
166+
auto _substr = new String(len);
167+
_substr->append(str + offset, len);
168+
return _substr;
169+
}
170+
162171
bool empty() {
163172
return str == nullptr || length == 0;
164173
}

include/swoole_version.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@
2222
#define SWOOLE_MINOR_VERSION 6
2323
#define SWOOLE_RELEASE_VERSION 0
2424
#define SWOOLE_EXTRA_VERSION "alpha"
25-
#define SWOOLE_VERSION "4.5.6"
25+
#define SWOOLE_VERSION "4.6.0-alpha"
2626
#define SWOOLE_VERSION_ID 40600
27-
#define SWOOLE_API_VERSION_ID 0x202011b
27+
#define SWOOLE_API_VERSION_ID 0x202012a
2828

2929
#define SWOOLE_BUG_REPORT \
3030
"A bug occurred in Swoole-v" SWOOLE_VERSION ", please report it.\n" \

src/memory/buffer.cc

+59-1
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,69 @@ void Buffer::append(const void *data, uint32_t size) {
7272
memcpy(chunk->value.ptr, _pos, _n);
7373
chunk->length = _n;
7474

75-
swTraceLog(SW_TRACE_BUFFER, "chunk_n=%d|size=%d|chunk_len=%d|chunk=%p", count(), _n, chunk->length, chunk);
75+
swTraceLog(SW_TRACE_BUFFER, "chunk_n=%lu|size=%u|chunk_len=%u|chunk=%p", count(), _n, chunk->length, chunk);
7676

7777
_pos += _n;
7878
_length -= _n;
7979
}
8080
}
8181

82+
void Buffer::append(const struct iovec *iov, size_t iovcnt, off_t offset) {
83+
size_t _length = 0;
84+
85+
SW_LOOP_N(iovcnt) {
86+
_length += iov[i].iov_len;
87+
}
88+
89+
char *pos = (char *) iov[0].iov_base;
90+
BufferChunk *chunk = nullptr;
91+
size_t iov_remain_len = iov[0].iov_len, chunk_remain_len;
92+
size_t i = 0;
93+
94+
while (true) {
95+
if (chunk) {
96+
if (chunk->size == chunk->length) {
97+
chunk = nullptr;
98+
continue;
99+
} else {
100+
chunk_remain_len = chunk->size - chunk->length;
101+
}
102+
} else {
103+
if (offset > 0) {
104+
if (offset >= (off_t) iov[i].iov_len) {
105+
offset -= iov[i].iov_len;
106+
i++;
107+
continue;
108+
} else {
109+
offset = 0;
110+
pos += offset;
111+
iov_remain_len -= offset;
112+
}
113+
}
114+
chunk_remain_len = _length >= chunk_size ? chunk_size : _length;
115+
chunk = alloc(BufferChunk::TYPE_DATA, chunk_remain_len);
116+
}
117+
118+
size_t _n = std::min(iov_remain_len, chunk_remain_len);
119+
memcpy(chunk->value.ptr + chunk->length, pos, _n);
120+
total_length += _n;
121+
_length -= _n;
122+
123+
swTraceLog(SW_TRACE_BUFFER, "chunk_n=%lu|size=%lu|chunk_len=%u|chunk=%p", count(), _n, chunk->length, chunk);
124+
125+
chunk->length += _n;
126+
iov_remain_len -= _n;
127+
128+
if (iov_remain_len == 0) {
129+
i++;
130+
if (i == iovcnt) {
131+
break;
132+
}
133+
iov_remain_len = iov[i].iov_len;
134+
pos = (char *) iov[i].iov_base;
135+
} else {
136+
pos += _n;
137+
}
138+
}
139+
}
82140
} // namespace swoole

src/network/socket.cc

+23-2
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,26 @@ int Socket::sendfile_blocking(const char *filename, off_t offset, size_t length,
122122
return SW_OK;
123123
}
124124

125+
ssize_t Socket::writev_blocking(const struct iovec *iov, size_t iovcnt) {
126+
while (1) {
127+
ssize_t n = writev(iov, iovcnt);
128+
if (n < 0) {
129+
if (errno == EINTR) {
130+
continue;
131+
} else if (catch_error(errno) == SW_WAIT &&
132+
wait_event((int) (send_timeout_ * 1000), SW_EVENT_WRITE) == SW_OK) {
133+
continue;
134+
} else {
135+
swSysWarn("send %lu bytes failed", iov[1].iov_len);
136+
return SW_ERR;
137+
}
138+
} else {
139+
return n;
140+
}
141+
}
142+
return -1;
143+
}
144+
125145
/**
126146
* clear socket buffer.
127147
*/
@@ -532,7 +552,7 @@ int Socket::handle_sendfile() {
532552
ret = ::swoole_sendfile(fd, task->file.get_fd(), &task->offset, sendn);
533553
}
534554

535-
swTrace("ret=%d|task->offset=%ld|sendn=%d|filesize=%ld", ret, (long) task->offset, sendn, task->length);
555+
swTrace("ret=%d|task->offset=%ld|sendn=%lu|filesize=%lu", ret, (long) task->offset, sendn, task->length);
536556

537557
if (ret <= 0) {
538558
switch (catch_error(errno)) {
@@ -751,6 +771,7 @@ ssize_t Socket::readv(IOVector *io_vector) {
751771

752772
return retval;
753773
}
774+
754775
ssize_t Socket::writev(IOVector *io_vector) {
755776
ssize_t retval;
756777

@@ -1118,7 +1139,7 @@ int Socket::ssl_sendfile(const File &fp, off_t *_offset, size_t _size) {
11181139
} else {
11191140
*_offset += ret;
11201141
}
1121-
swTraceLog(SW_TRACE_REACTOR, "fd=%d, readn=%d, n=%d, ret=%d", fd, readn, n, ret);
1142+
swTraceLog(SW_TRACE_REACTOR, "fd=%d, readn=%ld, n=%ld, ret=%ld", fd, readn, n, ret);
11221143
return ret;
11231144
} else {
11241145
swSysWarn("pread() failed");

0 commit comments

Comments
 (0)