Skip to content

Commit

Permalink
Optimize zend_fci_cache code; Remove swoole_add_function/swoole_get_f…
Browse files Browse the repository at this point in the history
…unction; Enforce single-threading when using package_length_func and dispatch_func.
  • Loading branch information
matyhtf committed Sep 25, 2024
1 parent a64640a commit ea8495a
Show file tree
Hide file tree
Showing 16 changed files with 110 additions and 275 deletions.
11 changes: 0 additions & 11 deletions core-tests/src/core/base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,17 +223,6 @@ static std::string test_func(std::string test_data_2) {
return test_data + test_data_2;
}

TEST(base, add_function) {
typedef std::string (*_func_t)(std::string);
swoole_add_function("test_func", (void *) test_func);
ASSERT_EQ(swoole_add_function("test_func", (void *) test_func), SW_ERR);
_func_t _func = (_func_t) swoole_get_function(SW_STRL("test_func"));
std::string b = ", swoole is best";
auto rs = _func(", swoole is best");
ASSERT_EQ(rs, test_data + b);
ASSERT_EQ(swoole_get_function(SW_STRL("test_func31")), nullptr);
}

TEST(base, hook) {
int count = 0;
swoole_add_hook(
Expand Down
14 changes: 14 additions & 0 deletions ext-src/php_swoole_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -978,6 +978,20 @@ static sw_inline void sw_zend_fci_cache_free(void *fci_cache) {
efree((zend_fcall_info_cache *) fci_cache);
}

static zend_fcall_info_cache *sw_zend_fci_cache_create(zval *zfn) {
char *func_name = nullptr;
zend_fcall_info_cache *fci_cache = (zend_fcall_info_cache *) emalloc(sizeof(zend_fcall_info_cache));
if (!sw_zend_is_callable_ex(zfn, nullptr, 0, &func_name, nullptr, fci_cache, nullptr)) {
php_swoole_fatal_error(E_ERROR, "function '%s' is not callable", func_name);
efree(fci_cache);
efree(func_name);
return nullptr;
}
efree(func_name);
sw_zend_fci_cache_persist(fci_cache);
return fci_cache;
}

#if PHP_VERSION_ID >= 80100
#define sw_php_spl_object_hash(o) php_spl_object_hash(Z_OBJ_P(o))
#else
Expand Down
36 changes: 9 additions & 27 deletions ext-src/swoole_client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -352,32 +352,15 @@ bool php_swoole_client_check_setting(Client *cli, zval *zset) {
}
// length function
if (php_swoole_array_get_value(vht, "package_length_func", ztmp)) {
while (1) {
if (Z_TYPE_P(ztmp) == IS_STRING) {
Protocol::LengthFunc func = Protocol::get_function(std::string(Z_STRVAL_P(ztmp), Z_STRLEN_P(ztmp)));
if (func != nullptr) {
cli->protocol.get_package_length = func;
break;
}
}

char *func_name;
zend_fcall_info_cache *fci_cache = (zend_fcall_info_cache *) ecalloc(1, sizeof(zend_fcall_info_cache));
if (!sw_zend_is_callable_ex(ztmp, nullptr, 0, &func_name, nullptr, fci_cache, nullptr)) {
php_swoole_fatal_error(E_ERROR, "function '%s' is not callable", func_name);
return false;
}
efree(func_name);
cli->protocol.get_package_length = php_swoole_length_func;
if (cli->protocol.private_data) {
sw_zend_fci_cache_discard((zend_fcall_info_cache *) cli->protocol.private_data);
efree(cli->protocol.private_data);
}
sw_zend_fci_cache_persist(fci_cache);
cli->protocol.private_data = fci_cache;
break;
auto fci_cache = sw_zend_fci_cache_create(ztmp);
if (!fci_cache) {
return false;
}

cli->protocol.get_package_length = php_swoole_length_func;
if (cli->protocol.private_data) {
sw_zend_fci_cache_free((zend_fcall_info_cache *) cli->protocol.private_data);
}
cli->protocol.private_data = fci_cache;
cli->protocol.package_length_size = 0;
cli->protocol.package_length_type = '\0';
cli->protocol.package_length_offset = SW_IPC_BUFFER_SIZE;
Expand Down Expand Up @@ -527,8 +510,7 @@ static void php_swoole_client_free(zval *zobject, Client *cli) {
cli->timer = nullptr;
}
if (cli->protocol.private_data) {
sw_zend_fci_cache_discard((zend_fcall_info_cache *) cli->protocol.private_data);
efree(cli->protocol.private_data);
sw_zend_fci_cache_free((zend_fcall_info_cache *) cli->protocol.private_data);
cli->protocol.private_data = nullptr;
}
// long tcp connection, delete from php_sw_long_connections
Expand Down
3 changes: 1 addition & 2 deletions ext-src/swoole_client_coro.cc
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,7 @@ static zend_object *client_coro_create_object(zend_class_entry *ce) {

static void client_coro_socket_dtor(ClientCoroObject *client) {
if (client->socket->protocol.private_data) {
sw_zend_fci_cache_discard((zend_fcall_info_cache *) client->socket->protocol.private_data);
efree(client->socket->protocol.private_data);
sw_zend_fci_cache_free((zend_fcall_info_cache *) client->socket->protocol.private_data);
client->socket->protocol.private_data = nullptr;
}
client->socket = nullptr;
Expand Down
47 changes: 17 additions & 30 deletions ext-src/swoole_coroutine_scheduler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -106,16 +106,15 @@ void php_swoole_coroutine_scheduler_minit(int module_number) {
swoole_coroutine_scheduler_ce->ce_flags |= ZEND_ACC_FINAL;
}

static zend_fcall_info_cache exit_condition_fci_cache;
static bool exit_condition_cleaner;
static zend_fcall_info_cache *exit_condition_fci_cache = nullptr;

static bool php_swoole_coroutine_reactor_can_exit(Reactor *reactor, size_t &event_num) {
zval retval;
int success;

SW_ASSERT(exit_condition_fci_cache.function_handler);
SW_ASSERT(exit_condition_fci_cache);
ZVAL_NULL(&retval);
success = sw_zend_call_function_ex(nullptr, &exit_condition_fci_cache, 0, nullptr, &retval);
success = sw_zend_call_function_ex(nullptr, exit_condition_fci_cache, 0, nullptr, &retval);
if (UNEXPECTED(success != SUCCESS)) {
php_swoole_fatal_error(E_ERROR, "Coroutine can_exit callback handler error");
}
Expand All @@ -135,6 +134,11 @@ void php_swoole_coroutine_scheduler_rshutdown() {
return SW_TRAVERSE_KEEP;
}
});

if (exit_condition_fci_cache) {
exit_condition_fci_cache = nullptr;
sw_zend_fci_cache_free(exit_condition_fci_cache);
}
}

void php_swoole_set_coroutine_option(zend_array *vht) {
Expand Down Expand Up @@ -194,33 +198,16 @@ PHP_METHOD(swoole_coroutine_scheduler, set) {
}
/* Reactor can exit */
if ((ztmp = zend_hash_str_find(vht, ZEND_STRL("exit_condition")))) {
char *func_name;
if (exit_condition_fci_cache.function_handler) {
sw_zend_fci_cache_discard(&exit_condition_fci_cache);
exit_condition_fci_cache.function_handler = nullptr;
if (exit_condition_fci_cache) {
sw_zend_fci_cache_free(&exit_condition_fci_cache);
}
if (!ZVAL_IS_NULL(ztmp)) {
if (!sw_zend_is_callable_ex(ztmp, nullptr, 0, &func_name, nullptr, &exit_condition_fci_cache, nullptr)) {
php_swoole_fatal_error(E_ERROR, "exit_condition '%s' is not callable", func_name);
} else {
efree(func_name);
sw_zend_fci_cache_persist(&exit_condition_fci_cache);
if (!exit_condition_cleaner) {
php_swoole_register_rshutdown_callback(
[](void *data) {
if (exit_condition_fci_cache.function_handler) {
sw_zend_fci_cache_discard(&exit_condition_fci_cache);
exit_condition_fci_cache.function_handler = nullptr;
}
},
nullptr);
exit_condition_cleaner = true;
}
SwooleG.user_exit_condition = php_swoole_coroutine_reactor_can_exit;
if (sw_reactor()) {
sw_reactor()->set_exit_condition(Reactor::EXIT_CONDITION_USER_AFTER_DEFAULT,
SwooleG.user_exit_condition);
}

exit_condition_fci_cache = sw_zend_fci_cache_create(ztmp);
if (exit_condition_fci_cache) {
SwooleG.user_exit_condition = php_swoole_coroutine_reactor_can_exit;
if (sw_reactor()) {
sw_reactor()->set_exit_condition(Reactor::EXIT_CONDITION_USER_AFTER_DEFAULT,
SwooleG.user_exit_condition);
}
} else {
if (sw_reactor()) {
Expand Down
22 changes: 7 additions & 15 deletions ext-src/swoole_process.cc
Original file line number Diff line number Diff line change
Expand Up @@ -493,16 +493,10 @@ static PHP_METHOD(swoole_process, signal) {
} else if (Z_TYPE_P(zcallback) == IS_LONG && Z_LVAL_P(zcallback) == (zend_long) SIG_IGN) {
handler = nullptr;
} else {
char *func_name;
fci_cache = (zend_fcall_info_cache *) ecalloc(1, sizeof(zend_fcall_info_cache));
if (!sw_zend_is_callable_ex(zcallback, nullptr, 0, &func_name, 0, fci_cache, nullptr)) {
php_swoole_error(E_WARNING, "function '%s' is not callable", func_name);
efree(func_name);
efree(fci_cache);
fci_cache = sw_zend_fci_cache_create(zcallback);
if (!fci_cache) {
RETURN_FALSE;
}
efree(func_name);
sw_zend_fci_cache_persist(fci_cache);
handler = php_swoole_onSignal;
}

Expand Down Expand Up @@ -619,8 +613,7 @@ void php_swoole_process_clean() {
for (int i = 0; i < SW_SIGNO_MAX; i++) {
zend_fcall_info_cache *fci_cache = signal_fci_caches[i];
if (fci_cache) {
sw_zend_fci_cache_discard(fci_cache);
efree(fci_cache);
sw_zend_fci_cache_free(fci_cache);
signal_fci_caches[i] = nullptr;
}
}
Expand All @@ -637,10 +630,8 @@ void php_swoole_process_rshutdown() {

int php_swoole_process_start(Worker *process, zval *zobject) {
zval *zcallback = sw_zend_read_property_ex(swoole_process_ce, zobject, SW_ZSTR_KNOWN(SW_ZEND_STR_CALLBACK), 0);
zend_fcall_info_cache fci_cache;

if (!sw_zend_is_callable_ex(zcallback, nullptr, 0, nullptr, 0, &fci_cache, nullptr)) {
php_swoole_fatal_error(E_ERROR, "Illegal callback function of %s", SW_Z_OBJCE_NAME_VAL_P(zobject));
auto fci_cache = sw_zend_fci_cache_create(zcallback);
if (!fci_cache) {
return SW_ERR;
}

Expand Down Expand Up @@ -681,13 +672,14 @@ int php_swoole_process_start(Worker *process, zval *zobject) {
return SW_ERR;
}
// main function
if (UNEXPECTED(!zend::function::call(&fci_cache, 1, zobject, nullptr, proc->enable_coroutine))) {
if (UNEXPECTED(!zend::function::call(fci_cache, 1, zobject, nullptr, proc->enable_coroutine))) {
php_swoole_error(E_WARNING, "%s->onStart handler error", SW_Z_OBJCE_NAME_VAL_P(zobject));
}
// eventloop start
if (proc->enable_coroutine) {
php_swoole_event_wait();
}
sw_zend_fci_cache_free(fci_cache);
// equivalent to exit
zend_bailout();

Expand Down
24 changes: 8 additions & 16 deletions ext-src/swoole_process_pool.cc
Original file line number Diff line number Diff line change
Expand Up @@ -75,20 +75,16 @@ static void process_pool_free_object(zend_object *object) {
}

if (pp->onWorkerStart) {
sw_zend_fci_cache_discard(pp->onWorkerStart);
efree(pp->onWorkerStart);
sw_zend_fci_cache_free(pp->onWorkerStart);
}
if (pp->onMessage) {
sw_zend_fci_cache_discard(pp->onMessage);
efree(pp->onMessage);
sw_zend_fci_cache_free(pp->onMessage);
}
if (pp->onWorkerStop) {
sw_zend_fci_cache_discard(pp->onWorkerStop);
efree(pp->onWorkerStop);
sw_zend_fci_cache_free(pp->onWorkerStop);
}
if (pp->onStart) {
sw_zend_fci_cache_discard(pp->onStart);
efree(pp->onStart);
sw_zend_fci_cache_free(pp->onStart);
}

zend_object_std_dtor(object);
Expand Down Expand Up @@ -344,8 +340,7 @@ static PHP_METHOD(swoole_process_pool, on) {

if (SW_STRCASEEQ(name, l_name, "WorkerStart")) {
if (pp->onWorkerStart) {
sw_zend_fci_cache_discard(pp->onWorkerStart);
efree(pp->onWorkerStart);
sw_zend_fci_cache_free(pp->onWorkerStart);
} else {
pp->onWorkerStart = (zend_fcall_info_cache *) emalloc(sizeof(zend_fcall_info_cache));
}
Expand All @@ -358,8 +353,7 @@ static PHP_METHOD(swoole_process_pool, on) {
RETURN_FALSE;
}
if (pp->onMessage) {
sw_zend_fci_cache_discard(pp->onMessage);
efree(pp->onMessage);
sw_zend_fci_cache_free(pp->onMessage);
} else {
pp->onMessage = (zend_fcall_info_cache *) emalloc(sizeof(zend_fcall_info_cache));
}
Expand All @@ -368,8 +362,7 @@ static PHP_METHOD(swoole_process_pool, on) {
RETURN_TRUE;
} else if (SW_STRCASEEQ(name, l_name, "WorkerStop")) {
if (pp->onWorkerStop) {
sw_zend_fci_cache_discard(pp->onWorkerStop);
efree(pp->onWorkerStop);
sw_zend_fci_cache_free(pp->onWorkerStop);
} else {
pp->onWorkerStop = (zend_fcall_info_cache *) emalloc(sizeof(zend_fcall_info_cache));
}
Expand All @@ -378,8 +371,7 @@ static PHP_METHOD(swoole_process_pool, on) {
RETURN_TRUE;
} else if (SW_STRCASEEQ(name, l_name, "Start")) {
if (pp->onStart) {
sw_zend_fci_cache_discard(pp->onStart);
efree(pp->onStart);
sw_zend_fci_cache_free(pp->onStart);
} else {
pp->onStart = (zend_fcall_info_cache *) emalloc(sizeof(zend_fcall_info_cache));
}
Expand Down
18 changes: 7 additions & 11 deletions ext-src/swoole_redis_server.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ namespace Redis = swoole::redis;
zend_class_entry *swoole_redis_server_ce;
zend_object_handlers swoole_redis_server_handlers;

static SW_THREAD_LOCAL std::unordered_map<std::string, zend_fcall_info_cache> redis_handlers;
static SW_THREAD_LOCAL std::unordered_map<std::string, zend_fcall_info_cache *> redis_handlers;

SW_EXTERN_C_BEGIN
static PHP_METHOD(swoole_redis_server, setHandler);
Expand Down Expand Up @@ -71,7 +71,7 @@ void php_swoole_redis_server_minit(int module_number) {

void php_swoole_redis_server_rshutdown() {
for (auto i = redis_handlers.begin(); i != redis_handlers.end(); i++) {
sw_zend_fci_cache_discard(&i->second);
sw_zend_fci_cache_free(i->second);
}
redis_handlers.clear();
}
Expand Down Expand Up @@ -169,7 +169,7 @@ int php_swoole_redis_server_onReceive(Server *serv, RecvData *req) {
return serv->send(fd, err_msg, length) ? SW_OK : SW_ERR;
}

zend_fcall_info_cache *fci_cache = &i->second;
zend_fcall_info_cache *fci_cache = i->second;
zval args[2];
zval retval;

Expand Down Expand Up @@ -209,13 +209,10 @@ static PHP_METHOD(swoole_redis_server, setHandler) {
RETURN_FALSE;
}

char *func_name;
zend_fcall_info_cache *fci_cache = (zend_fcall_info_cache *) emalloc(sizeof(zend_fcall_info_cache));
if (!sw_zend_is_callable_ex(zcallback, nullptr, 0, &func_name, nullptr, fci_cache, nullptr)) {
php_swoole_fatal_error(E_ERROR, "function '%s' is not callable", func_name);
auto fci_cache = sw_zend_fci_cache_create(zcallback);
if (!fci_cache) {
return;
}
efree(func_name);

char _command[SW_REDIS_MAX_COMMAND_SIZE];
size_t _command_len = sw_snprintf(_command, sizeof(_command), "_handler_%s", command);
Expand All @@ -230,11 +227,10 @@ static PHP_METHOD(swoole_redis_server, setHandler) {
std::string key(_command, _command_len);
auto i = redis_handlers.find(key);
if (i != redis_handlers.end()) {
sw_zend_fci_cache_discard(&i->second);
sw_zend_fci_cache_free(i->second);
}

sw_zend_fci_cache_persist(fci_cache);
redis_handlers[key] = *fci_cache;
redis_handlers[key] = fci_cache;

RETURN_TRUE;
}
Expand Down
12 changes: 4 additions & 8 deletions ext-src/swoole_runtime.cc
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ void php_swoole_runtime_rshutdown() {
*/
if (rf->fci_cache) {
zval_dtor(&rf->name);
efree(rf->fci_cache);
sw_zend_fci_cache_free(rf->fci_cache);
}
rf->function->internal_function.handler = rf->ori_handler;
rf->function->internal_function.arg_info = rf->ori_arg_info;
Expand Down Expand Up @@ -2000,15 +2000,11 @@ static void hook_func(const char *name, size_t l_name, zif_handler handler, zend
memcpy(func + 7, fn_str->val, fn_str->len);

ZVAL_STRINGL(&rf->name, func, fn_str->len + 7);

char *func_name;
zend_fcall_info_cache *func_cache = (zend_fcall_info_cache *) emalloc(sizeof(zend_fcall_info_cache));
if (!sw_zend_is_callable_ex(&rf->name, nullptr, 0, &func_name, nullptr, func_cache, nullptr)) {
php_swoole_fatal_error(E_ERROR, "function '%s' is not callable", func_name);
auto fci_cache = sw_zend_fci_cache_create(&rf->name);
if (!fci_cache) {
return;
}
efree(func_name);
rf->fci_cache = func_cache;
rf->fci_cache = fci_cache;
}

zend_hash_add_ptr(tmp_function_table, fn_str, rf);
Expand Down
Loading

0 comments on commit ea8495a

Please sign in to comment.