rfc:internal_serialize_api
no way to compare when less than two revisions
Differences
This shows you the differences between two versions of the page.
Previous revisionNext revision | |||
— | rfc:internal_serialize_api [2013/09/15 18:52] – New version with patch bukka | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====== PHP RFC: Internal Serialize API ====== | ||
+ | * Version: 1.0 | ||
+ | * Date: 2013-07-27 | ||
+ | * Author: Jakub Zelenka, bukka@php.net | ||
+ | * Status: Under Discussion | ||
+ | ===== Introduction ===== | ||
+ | |||
+ | This RFC proposes a new API for internal object serialization and unserialization. | ||
+ | |||
+ | The current methods of serializing/ | ||
+ | * Internal class has to to define object properties or use get_properties handler. The properties are then used for serialization. The object state can be restored using '' | ||
+ | * Using Serializable interface or serialize / unserialize '' | ||
+ | |||
+ | The first method has one side effect. After unserializing of object, the properties are saved to the object properties HashTable. This requires more allocated memory for the object than it's usualy necassary. The usual purpose of unserializing the internal object is to get the object to the state when it was before serialization. These data are mostly saved in the object bucket and there is no point to save them to properties table as well. There also is an performance issue with serialization. In addition the serialization is quite slow because HashTable must be created and populated with zvals. This is much slower than simply transforming the state of the object to the string (see benchmarks). | ||
+ | |||
+ | The second method requires generating and parsing serialized string which can require quite a lot of coding in C. Also the resulted string is never compatible with the string generate by the first method. It means that existing classes cannot be changed from the first method to the custom serialization without breaking BC. | ||
+ | |||
+ | The proposed API resolves all mentioned problems and also simplify the way how internal objects are serialized/ | ||
+ | |||
+ | | ||
+ | ===== Proposal ===== | ||
+ | |||
+ | The purpose of the proposed API is simplified custom object serialization and unserialization for extension writers and also improve performance. | ||
+ | |||
+ | The proposed changes does not have any influence on user space serialization/ | ||
+ | |||
+ | |||
+ | ==== Serialization ==== | ||
+ | |||
+ | The first part of the proposal is API for generating serialized data for internal classes. | ||
+ | |||
+ | === Serialize hook changes === | ||
+ | |||
+ | Currently '' | ||
+ | |||
+ | < | ||
+ | #define PHP_SERIALIZE_FAILURE (FAILURE) | ||
+ | #define PHP_SERIALIZE_CUSTOM | ||
+ | #define PHP_SERIALIZE_OBJECT | ||
+ | </ | ||
+ | |||
+ | If the return value is '' | ||
+ | |||
+ | If the return value is '' | ||
+ | |||
+ | === Functions === | ||
+ | |||
+ | The RFC defines new PHPAPI exported helper functions that should be used for object serialization. | ||
+ | |||
+ | < | ||
+ | /* add object serialization string prefix */ | ||
+ | PHPAPI void php_var_serialize_object_start(smart_str *buf, zval *object, zend_uint nprops TSRMLS_DC); | ||
+ | |||
+ | /* append string that ends the object definition */ | ||
+ | PHPAPI void php_var_serialize_object_end(smart_str *buf); | ||
+ | |||
+ | /* append null property */ | ||
+ | PHPAPI void php_var_serialize_property_null(smart_str *buf, const char *key); | ||
+ | |||
+ | /* append boolean property */ | ||
+ | PHPAPI void php_var_serialize_property_bool(smart_str *buf, const char *key, int value); | ||
+ | |||
+ | /* append long property */ | ||
+ | PHPAPI void php_var_serialize_property_long(smart_str *buf, const char *key, long value); | ||
+ | |||
+ | /* append double property */ | ||
+ | PHPAPI void php_var_serialize_property_double(smart_str *buf, const char *key, double value TSRMLS_DC); | ||
+ | |||
+ | /* append string property */ | ||
+ | PHPAPI void php_var_serialize_property_string(smart_str *buf, const char *key, const char *value); | ||
+ | |||
+ | /* append string property */ | ||
+ | PHPAPI void php_var_serialize_property_stringl(smart_str *buf, const char *key, const char *value, int value_len); | ||
+ | |||
+ | /* append string property zval */ | ||
+ | PHPAPI void php_var_serialize_property_zval(smart_str *buf, const char *key, zval *value, zend_serialize_data *data TSRMLS_DC); | ||
+ | |||
+ | /* append properties taken from HashTable */ | ||
+ | PHPAPI void php_var_serialize_properties(smart_str *buf, HashTable *properties, | ||
+ | </ | ||
+ | |||
+ | The functionality for all functions should be clear from the comments. | ||
+ | |||
+ | === Example ==== | ||
+ | |||
+ | This example shows how the new API could be used in extension. | ||
+ | |||
+ | < | ||
+ | static int test_object_serialize(zval *object, unsigned char **buffer, zend_uint *buf_len, zend_serialize_data *data TSRMLS_DC) | ||
+ | { | ||
+ | smart_str buf = {0}; | ||
+ | |||
+ | php_var_serialize_object_start(& | ||
+ | php_var_serialize_property_bool(& | ||
+ | php_var_serialize_property_long(& | ||
+ | php_var_serialize_property_double(& | ||
+ | php_var_serialize_property_string(& | ||
+ | php_var_serialize_object_end(& | ||
+ | | ||
+ | return PHP_SERIALIZE_OBJECT; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | ==== Unserialization ==== | ||
+ | |||
+ | The second part of the proposal is API for parsing serialized string for internal classes. | ||
+ | |||
+ | === Unserialize hook changes === | ||
+ | |||
+ | Currently '' | ||
+ | |||
+ | The RFC proposes calling unserialize callback for custom classes as well as for normal internal classes (prefixed O:) that have '' | ||
+ | |||
+ | The return value is number of characters left in the buffer after processing serialized string. In case of error, the return value should be negative number (usually -1). This behavior is backward compatible. | ||
+ | |||
+ | === Functions === | ||
+ | |||
+ | The RFC defines new PHPAPI exported helper functions that should be used for object unserialization. | ||
+ | |||
+ | < | ||
+ | /* unserialize one property (key and value) of the serialized object */ | ||
+ | PHPAPI int php_var_unserialize_property(zval *key, zval *value, const unsigned char **buf, zend_uint *buf_len, zend_unserialize_data *data TSRMLS_DC); | ||
+ | |||
+ | /* unserialize all properties of the serialized object and save them to ht */ | ||
+ | PHPAPI int php_var_unserialize_properties(HashTable *ht, const unsigned char **buf, zend_uint *buf_len, zend_uint elements, zend_unserialize_data *data TSRMLS_DC); | ||
+ | </ | ||
+ | |||
+ | The functionality for all functions should be clear from the comments. | ||
+ | |||
+ | === Example ==== | ||
+ | |||
+ | This example shows how the new API could be used in extension. | ||
+ | |||
+ | < | ||
+ | static int test_object_unserialize(zval **object, zend_class_entry *ce, const unsigned char *buf, zend_uint buf_len, zend_unserialize_data *data TSRMLS_DC) | ||
+ | { | ||
+ | zval key, value; | ||
+ | |||
+ | if (!php_var_unserialize_property(& | ||
+ | return -1; | ||
+ | } | ||
+ | /* process first key and value... */ | ||
+ | |||
+ | if (!php_var_unserialize_property(& | ||
+ | return -1; | ||
+ | } | ||
+ | /* process second key and value... */ | ||
+ | |||
+ | if (!php_var_unserialize_property(& | ||
+ | return -1; | ||
+ | } | ||
+ | /* process third key and value... */ | ||
+ | |||
+ | if (!php_var_unserialize_property(& | ||
+ | return -1; | ||
+ | } | ||
+ | /* process fourth key and value... */ | ||
+ | |||
+ | return (int) buf_len; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ===== Benchmark and more examples ===== | ||
+ | |||
+ | The extension with tests and benchmarks is available at https:// | ||
+ | |||
+ | ===== Patches and Tests ===== | ||
+ | |||
+ | Pull request is at https:// |
rfc/internal_serialize_api.txt · Last modified: 2018/06/18 10:15 by cmb