Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP]Optimize memory usage #5264

Closed
wants to merge 21 commits into from
2 changes: 1 addition & 1 deletion ext-src/php_swoole.cc
Original file line number Diff line number Diff line change
Expand Up @@ -695,7 +695,7 @@ PHP_MINIT_FUNCTION(swoole) {
// init bug report message
bug_report_message_init();
if (strcmp("cli", sapi_module.name) == 0 || strcmp("phpdbg", sapi_module.name) == 0 ||
strcmp("embed", sapi_module.name) == 0) {
strcmp("embed", sapi_module.name) == 0 || strcmp("micro", sapi_module.name) == 0) {
SWOOLE_G(cli) = 1;
}

Expand Down
122 changes: 121 additions & 1 deletion ext-src/php_swoole_http.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,126 @@ class Session;

namespace http {

struct ByteBuffer {
const char *version = "HTTP/1.1 ";
size_t version_length = 9;
const char *status = nullptr;
size_t status_length = 0;
const char *reason = nullptr;
size_t reason_length = 0;

size_t position = 0;
size_t http_status_length = 0;
size_t http_headers_length = 0;

int index = 0;
size_t *lengths;
const char **headers;

int free_num = 0;
zend_string **free_list;

ByteBuffer(size_t *_lengths, const char **_headers, zend_string **_free_list) {
lengths = _lengths;
headers = _headers;
free_list = _free_list;
}

~ByteBuffer() {
int i = 0;
while (i < free_num) {
zend_string_release(free_list[i++]);
}
}

inline void add_status(const char *_status, const char *_reason) {
status = _status;
status_length = strlen(status);
reason = _reason;
reason_length = reason ? strlen(reason) : 0;

// calculate http status line length
http_status_length = version_length + status_length + SW_CRLF_LEN;
if (reason) {
http_status_length += reason_length + 1;
}
}

inline void add_header(zend_string *key, zend_string *value) {
zend_string_addref(key);
zend_string_addref(value);
free_list[free_num++] = key;
free_list[free_num++] = value;
add_header(ZSTR_VAL(key), ZSTR_LEN(key), ZSTR_VAL(value), ZSTR_LEN(value));
}

inline void add_header(const char *key, size_t key_length, const char *value, size_t value_length) {
headers[index] = key;
lengths[index] = key_length;
index++;

headers[index] = value;
lengths[index] = value_length;
index++;

if (value) {
http_headers_length += key_length + value_length + SW_CRLF_LEN + 2;
} else {
// When the value is a nullptr, it means that this response header has a fixed value.
http_headers_length += key_length;
}
}

inline size_t get_protocol_length(size_t length = 0) {
// calculate http protocol length
return http_status_length + http_headers_length + length + SW_CRLF_LEN;
}

inline void append(char *protocol, const char *data, size_t length) {
memcpy(protocol + position, data, length);
position += length;
}

void write_protocol(char *protocol, const char *data, size_t length) {
append(protocol, version, version_length);
append(protocol, status, status_length);
if (reason) {
append(protocol, " ", 1);
append(protocol, reason, reason_length);
}

append(protocol, SW_CRLF, SW_CRLF_LEN);

size_t key_length = 0;
size_t value_length = 0;
const char *key = nullptr;
const char *value = nullptr;
int i = 0;

while (i < index) {
key_length = lengths[i];
value_length = lengths[i + 1];
key = headers[i++];
value = headers[i++];

if (value == nullptr) {
append(protocol, key, key_length);
continue;
}

append(protocol, key, key_length);
append(protocol, ": ", 2);
append(protocol, value, value_length);
append(protocol, SW_CRLF, SW_CRLF_LEN);
}

append(protocol, SW_CRLF, SW_CRLF_LEN);
if (data) {
append(protocol, data, length);
}
}
};

struct Request {
int version;
char *path;
Expand Down Expand Up @@ -193,7 +313,7 @@ struct Context {
bool send_file(const char *file, uint32_t l_file, off_t offset, size_t length);
void send_trailer(zval *return_value);
String *get_write_buffer();
void build_header(String *http_buffer, const char *body, size_t length);
bool start_send(const char *body, size_t length);
ssize_t build_trailer(String *http_buffer);

size_t get_content_length() {
Expand Down
9 changes: 5 additions & 4 deletions ext-src/php_swoole_library.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
+----------------------------------------------------------------------+
*/

/* $Id: d0ac03753a22ce34a521c7eb75b2e19f0d6ec961 */
/* $Id: 286fa34095664574dbb1c9c00cfe3ca052e04a59 */

#ifndef SWOOLE_LIBRARY_H
#define SWOOLE_LIBRARY_H
Expand Down Expand Up @@ -1939,7 +1939,7 @@ static const char* swoole_library_source_core_coroutine_http_client_proxy =
"\n"
"class ClientProxy\n"
"{\n"
" public function __construct(private string $body, private int $statusCode, private array $headers, private array $cookies)\n"
" public function __construct(private string $body, private int $statusCode, private ?array $headers, private ?array $cookies)\n"
" {\n"
" }\n"
"\n"
Expand Down Expand Up @@ -6609,6 +6609,7 @@ static const char* swoole_library_source_core_coroutine_fast_cgi_client =
"\n"
"namespace Swoole\\Coroutine\\FastCGI;\n"
"\n"
"use Swoole\\Constant;\n"
"use Swoole\\Coroutine\\FastCGI\\Client\\Exception;\n"
"use Swoole\\Coroutine\\Socket;\n"
"use Swoole\\FastCGI\\FrameParser;\n"
Expand Down Expand Up @@ -6655,8 +6656,8 @@ static const char* swoole_library_source_core_coroutine_fast_cgi_client =
" if (!isset($this->socket)) {\n"
" $this->socket = $socket = new Socket($this->af, SOCK_STREAM, IPPROTO_IP);\n"
" $socket->setProtocol([\n"
" 'open_ssl' => $this->ssl,\n"
" 'open_fastcgi_protocol' => true,\n"
" Constant::OPTION_OPEN_SSL => $this->ssl,\n"
" Constant::OPTION_OPEN_FASTCGI_PROTOCOL => true,\n"
" ]);\n"
" if (!$socket->connect($this->host, $this->port, $timeout)) {\n"
" $this->ioException();\n"
Expand Down
16 changes: 7 additions & 9 deletions ext-src/php_swoole_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -709,11 +709,12 @@ static sw_inline void sw_zend_update_property_null_ex(zend_class_entry *scope, z
zend_update_property_ex(scope, SW_Z8_OBJ_P(object), s, &tmp);
}

static sw_inline zval *sw_zend_read_property_ex(zend_class_entry *ce, zval *obj, zend_string *s, int silent) {
zval rv, *property = zend_read_property_ex(ce, SW_Z8_OBJ_P(obj), s, silent, &rv);
static sw_inline zval *sw_zend_read_property_ex(zend_class_entry *ce, zval *zobject, zend_string *name, int silent) {
zval *zv = zend_hash_find(&ce->properties_info, name);
zend_property_info *property_info = (zend_property_info *) Z_PTR_P(zv);
zval *property = OBJ_PROP(SW_Z8_OBJ_P(zobject), property_info->offset);
if (UNEXPECTED(property == &EG(uninitialized_zval))) {
sw_zend_update_property_null_ex(ce, obj, s);
return zend_read_property_ex(ce, SW_Z8_OBJ_P(obj), s, silent, &rv);
ZVAL_NULL(property);
}
return property;
}
Expand Down Expand Up @@ -946,11 +947,8 @@ static sw_inline int php_swoole_check_reactor() {
}
}

static sw_inline char *php_swoole_format_date(char *format, size_t format_len, time_t ts, int localtime) {
zend_string *time = php_format_date(format, format_len, ts, localtime);
char *return_str = estrndup(ZSTR_VAL(time), ZSTR_LEN(time));
zend_string_release(time);
return return_str;
static sw_inline zend_string *php_swoole_format_date(char *format, size_t format_len, time_t ts, int localtime) {
return php_format_date(format, format_len, ts, localtime);
}

static sw_inline char *php_swoole_url_encode(const char *value, size_t value_len, size_t *exten) {
Expand Down
8 changes: 4 additions & 4 deletions ext-src/swoole_http2_server.cc
Original file line number Diff line number Diff line change
Expand Up @@ -306,11 +306,11 @@ static void http2_server_set_date_header(Http2::HeaderSet *headers) {

time_t now = time(nullptr);
if (now != cache.time) {
char *date_str = php_swoole_format_date((char *) ZEND_STRL(SW_HTTP_DATE_FORMAT), now, 0);
cache.len = strlen(date_str);
memcpy(cache.buf, date_str, cache.len);
zend_string *date = php_swoole_format_date((char *) ZEND_STRL(SW_HTTP_DATE_FORMAT), now, 0);
memcpy(cache.buf, ZSTR_VAL(date), ZSTR_LEN(date));
cache.len = ZSTR_LEN(date);
cache.time = now;
efree(date_str);
zend_string_release(date);
}
headers->add(ZEND_STRL("date"), cache.buf, cache.len);
}
Expand Down
Loading
Loading