Commit edda0c92 authored by Paul Yang's avatar Paul Yang Committed by Rafi Kamal

Persistent Descriptor Pool (#6899)

* Make reserve names map persistent

* Add DescriptorInternal to map

* Use get_msgdef_desc in encode_decode.c

* Add persistent map for ce=>def and enum=>def

* Replace get_ce_obj

* Remove get_proto_obj

* Remove obsolete fields from Descriptor and EnumDescriptor

* Add cache for descriptor php values

* Add cache for descriptors

* Fix bug

* Avoid add generated file again if it has been added

* Fix the bug upb depends on null-ended str for look up.

* Initialize generated pool impl

* Turn down old generated pool

* Add init entry flag protobuf.keep_descriptor_pool_after_request

By default, it's off. Add protobuf.keep_descriptor_pool_after_request=1 to php.ini to enable it

* Fix zts build
parent cd7b27be
This diff is collapsed.
This diff is collapsed.
......@@ -255,7 +255,7 @@ void* message_data(MessageHeader* msg) {
void custom_data_init(const zend_class_entry* ce,
MessageHeader* intern PHP_PROTO_TSRMLS_DC) {
Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, get_ce_obj(ce));
DescriptorInternal* desc = get_ce_desc(ce);
intern->data = ALLOC_N(uint8_t, desc->layout->size);
// We wrap first so that everything in the message object is GC-rooted in
// case a collection happens during object creation in layout_init().
......@@ -279,15 +279,15 @@ void build_class_from_descriptor(
Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, php_descriptor);
// Map entries don't have existing php class.
if (upb_msgdef_mapentry(desc->msgdef)) {
if (upb_msgdef_mapentry(desc->intern->msgdef)) {
return;
}
zend_class_entry* registered_ce = desc->klass;
zend_class_entry* registered_ce = desc->intern->klass;
if (desc->layout == NULL) {
MessageLayout* layout = create_layout(desc->msgdef);
desc->layout = layout;
if (desc->intern->layout == NULL) {
MessageLayout* layout = create_layout(desc->intern->msgdef);
desc->intern->layout = layout;
}
registered_ce->create_object = message_create;
......@@ -395,8 +395,7 @@ void Message_construct(zval* msg, zval* array_wrapper) {
is_wrapper = is_wrapper_msg(submsgdef);
if (is_wrapper) {
PHP_PROTO_HASHTABLE_VALUE subdesc_php = get_def_obj(submsgdef);
Descriptor* subdesc = UNBOX_HASHTABLE_VALUE(Descriptor, subdesc_php);
DescriptorInternal* subdesc = get_msgdef_desc(submsgdef);
subklass = subdesc->klass;
}
}
......@@ -435,8 +434,7 @@ void Message_construct(zval* msg, zval* array_wrapper) {
is_wrapper = is_wrapper_msg(submsgdef);
if (is_wrapper) {
PHP_PROTO_HASHTABLE_VALUE subdesc_php = get_def_obj(submsgdef);
Descriptor* subdesc = UNBOX_HASHTABLE_VALUE(Descriptor, subdesc_php);
DescriptorInternal* subdesc = get_msgdef_desc(submsgdef);
subklass = subdesc->klass;
}
}
......@@ -459,8 +457,7 @@ void Message_construct(zval* msg, zval* array_wrapper) {
}
} else if (upb_fielddef_issubmsg(field)) {
const upb_msgdef* submsgdef = upb_fielddef_msgsubdef(field);
PHP_PROTO_HASHTABLE_VALUE desc_php = get_def_obj(submsgdef);
Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, desc_php);
DescriptorInternal* desc = get_msgdef_desc(submsgdef);
CACHED_VALUE* cached = NULL;
if (upb_fielddef_containingoneof(field)) {
......@@ -530,7 +527,7 @@ PHP_METHOD(Message, __construct) {
PHP_METHOD(Message, clear) {
MessageHeader* msg = UNBOX(MessageHeader, getThis());
Descriptor* desc = msg->descriptor;
DescriptorInternal* desc = msg->descriptor;
zend_class_entry* ce = desc->klass;
zend_object_std_dtor(&msg->std TSRMLS_CC);
......@@ -1536,14 +1533,13 @@ PHP_METHOD(Any, unpack) {
}
const char* fully_qualified_name = type_url + url_prefix_len;
PHP_PROTO_HASHTABLE_VALUE desc_php = get_proto_obj(fully_qualified_name);
if (desc_php == NULL) {
DescriptorInternal* desc = get_proto_desc(fully_qualified_name);
if (desc == NULL) {
zend_throw_exception(
NULL, "Specified message in any hasn't been added to descriptor pool",
0 TSRMLS_CC);
return;
}
Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, desc_php);
zend_class_entry* klass = desc->klass;
ZVAL_OBJ(return_value, klass->create_object(klass TSRMLS_CC));
MessageHeader* msg = UNBOX(MessageHeader, return_value);
......@@ -1589,8 +1585,7 @@ PHP_METHOD(Any, pack) {
PHP_PROTO_FAKE_SCOPE_END;
// Set type url.
Descriptor* desc =
UNBOX_HASHTABLE_VALUE(Descriptor, get_ce_obj(Z_OBJCE_P(val)));
DescriptorInternal* desc = get_ce_desc(Z_OBJCE_P(val));
const char* fully_qualified_name = upb_msgdef_fullname(desc->msgdef);
size_t type_url_len =
strlen(TYPE_URL_PREFIX) + strlen(fully_qualified_name) + 1;
......@@ -1617,14 +1612,12 @@ PHP_METHOD(Any, is) {
return;
}
PHP_PROTO_HASHTABLE_VALUE desc_php = get_ce_obj(klass);
if (desc_php == NULL) {
DescriptorInternal* desc = get_ce_desc(klass);
if (desc == NULL) {
RETURN_BOOL(false);
}
// Create corresponded type url.
Descriptor* desc =
UNBOX_HASHTABLE_VALUE(Descriptor, get_ce_obj(klass));
const char* fully_qualified_name = upb_msgdef_fullname(desc->msgdef);
size_t type_url_len =
strlen(TYPE_URL_PREFIX) + strlen(fully_qualified_name) + 1;
......
This diff is collapsed.
......@@ -171,7 +171,7 @@
LOWWERNAME##_methods); \
LOWWERNAME##_type = zend_register_internal_class(&class_type TSRMLS_CC); \
LOWWERNAME##_type->create_object = LOWWERNAME##_create; \
LOWWERNAME##_handlers = PEMALLOC(zend_object_handlers); \
LOWWERNAME##_handlers = PEMALLOC(zend_object_handlers, 1); \
memcpy(LOWWERNAME##_handlers, zend_get_std_object_handlers(), \
sizeof(zend_object_handlers));
#define PHP_PROTO_INIT_CLASS_END \
......@@ -440,7 +440,7 @@ static inline int php_proto_zend_hash_get_current_data_ex(HashTable* ht,
LOWWERNAME##_methods); \
LOWWERNAME##_type = zend_register_internal_class(&class_type TSRMLS_CC); \
LOWWERNAME##_type->create_object = LOWWERNAME##_create; \
LOWWERNAME##_handlers = PEMALLOC(zend_object_handlers); \
LOWWERNAME##_handlers = PEMALLOC(zend_object_handlers, 1); \
memcpy(LOWWERNAME##_handlers, zend_get_std_object_handlers(), \
sizeof(zend_object_handlers)); \
LOWWERNAME##_handlers->free_obj = LOWWERNAME##_free; \
......@@ -590,11 +590,13 @@ struct Api;
struct BoolValue;
struct BytesValue;
struct Descriptor;
struct DescriptorInternal;
struct DescriptorPool;
struct DoubleValue;
struct Duration;
struct Enum;
struct EnumDescriptor;
struct EnumDescriptorInternal;
struct EnumValue;
struct EnumValueDescriptor;
struct Field;
......@@ -607,6 +609,7 @@ struct GPBEmpty;
struct Int32Value;
struct Int64Value;
struct InternalDescriptorPool;
struct InternalDescriptorPoolImpl;
struct ListValue;
struct Map;
struct MapIter;
......@@ -635,10 +638,12 @@ typedef struct Api Api;
typedef struct BoolValue BoolValue;
typedef struct BytesValue BytesValue;
typedef struct Descriptor Descriptor;
typedef struct DescriptorInternal DescriptorInternal;
typedef struct DescriptorPool DescriptorPool;
typedef struct DoubleValue DoubleValue;
typedef struct Duration Duration;
typedef struct EnumDescriptor EnumDescriptor;
typedef struct EnumDescriptorInternal EnumDescriptorInternal;
typedef struct Enum Enum;
typedef struct EnumValueDescriptor EnumValueDescriptor;
typedef struct EnumValue EnumValue;
......@@ -652,6 +657,7 @@ typedef struct GPBEmpty GPBEmpty;
typedef struct Int32Value Int32Value;
typedef struct Int64Value Int64Value;
typedef struct InternalDescriptorPool InternalDescriptorPool;
typedef struct InternalDescriptorPoolImpl InternalDescriptorPoolImpl;
typedef struct ListValue ListValue;
typedef struct MapIter MapIter;
typedef struct Map Map;
......@@ -680,8 +686,17 @@ typedef struct Value Value;
// -----------------------------------------------------------------------------
ZEND_BEGIN_MODULE_GLOBALS(protobuf)
zend_bool keep_descriptor_pool_after_request;
ZEND_END_MODULE_GLOBALS(protobuf)
ZEND_DECLARE_MODULE_GLOBALS(protobuf)
#ifdef ZTS
#define PROTOBUF_G(v) TSRMG(protobuf_globals_id, zend_protobuf_globals *, v)
#else
#define PROTOBUF_G(v) (protobuf_globals.v)
#endif
// Init module and PHP classes.
void any_init(TSRMLS_D);
void api_init(TSRMLS_D);
......@@ -743,17 +758,27 @@ void gpb_metadata_wrappers_init(TSRMLS_D);
// instances.
void add_def_obj(const void* def, PHP_PROTO_HASHTABLE_VALUE value);
PHP_PROTO_HASHTABLE_VALUE get_def_obj(const void* def);
void add_msgdef_desc(const upb_msgdef* m, DescriptorInternal* desc);
DescriptorInternal* get_msgdef_desc(const upb_msgdef* m);
void add_enumdef_enumdesc(const upb_enumdef* e, EnumDescriptorInternal* desc);
EnumDescriptorInternal* get_enumdef_enumdesc(const upb_enumdef* e);
// Global map from PHP class entries to wrapper Descriptor/EnumDescriptor
// instances.
void add_ce_obj(const void* ce, PHP_PROTO_HASHTABLE_VALUE value);
PHP_PROTO_HASHTABLE_VALUE get_ce_obj(const void* ce);
bool class_added(const void* ce);
void add_ce_desc(const zend_class_entry* ce, DescriptorInternal* desc);
DescriptorInternal* get_ce_desc(const zend_class_entry* ce);
void add_ce_enumdesc(const zend_class_entry* ce, EnumDescriptorInternal* desc);
EnumDescriptorInternal* get_ce_enumdesc(const zend_class_entry* ce);
// Global map from message/enum's proto fully-qualified name to corresponding
// wrapper Descriptor/EnumDescriptor instances.
void add_proto_obj(const char* proto, PHP_PROTO_HASHTABLE_VALUE value);
PHP_PROTO_HASHTABLE_VALUE get_proto_obj(const char* proto);
void add_proto_desc(const char* proto, DescriptorInternal* desc);
DescriptorInternal* get_proto_desc(const char* proto);
void add_proto_enumdesc(const char* proto, EnumDescriptorInternal* desc);
EnumDescriptorInternal* get_proto_enumdesc(const char* proto);
extern zend_class_entry* map_field_type;
extern zend_class_entry* repeated_field_type;
......@@ -763,14 +788,14 @@ extern zend_class_entry* repeated_field_type;
// -----------------------------------------------------------------------------
PHP_PROTO_WRAP_OBJECT_START(DescriptorPool)
InternalDescriptorPool* intern;
InternalDescriptorPoolImpl* intern;
PHP_PROTO_WRAP_OBJECT_END
PHP_METHOD(DescriptorPool, getGeneratedPool);
PHP_METHOD(DescriptorPool, getDescriptorByClassName);
PHP_METHOD(DescriptorPool, getEnumDescriptorByClassName);
PHP_PROTO_WRAP_OBJECT_START(InternalDescriptorPool)
struct InternalDescriptorPoolImpl {
upb_symtab* symtab;
upb_handlercache* fill_handler_cache;
upb_handlercache* pb_serialize_handler_cache;
......@@ -778,13 +803,17 @@ PHP_PROTO_WRAP_OBJECT_START(InternalDescriptorPool)
upb_handlercache* json_serialize_handler_preserve_cache;
upb_pbcodecache* fill_method_cache;
upb_json_codecache* json_fill_method_cache;
};
PHP_PROTO_WRAP_OBJECT_START(InternalDescriptorPool)
InternalDescriptorPoolImpl* intern;
PHP_PROTO_WRAP_OBJECT_END
PHP_METHOD(InternalDescriptorPool, getGeneratedPool);
PHP_METHOD(InternalDescriptorPool, internalAddGeneratedFile);
void internal_add_generated_file(const char* data, PHP_PROTO_SIZE data_len,
InternalDescriptorPool* pool,
InternalDescriptorPoolImpl* pool,
bool use_nested_submsg TSRMLS_DC);
void init_generated_pool_once(TSRMLS_D);
void add_handlers_for_message(const void* closure, upb_handlers* h);
......@@ -801,13 +830,24 @@ extern zend_object *internal_generated_pool_php;
void descriptor_pool_free(zend_object* object);
void internal_descriptor_pool_free(zend_object* object);
#endif
extern InternalDescriptorPool* generated_pool; // The actual generated pool
extern InternalDescriptorPoolImpl* generated_pool;
// The actual generated pool
extern InternalDescriptorPoolImpl generated_pool_impl;
PHP_PROTO_WRAP_OBJECT_START(Descriptor)
InternalDescriptorPool* pool;
void internal_descriptor_pool_impl_init(
InternalDescriptorPoolImpl *pool TSRMLS_DC);
void internal_descriptor_pool_impl_destroy(
InternalDescriptorPoolImpl *pool TSRMLS_DC);
struct DescriptorInternal {
InternalDescriptorPoolImpl* pool;
const upb_msgdef* msgdef;
MessageLayout* layout;
zend_class_entry* klass; // begins as NULL
};
PHP_PROTO_WRAP_OBJECT_START(Descriptor)
DescriptorInternal* intern;
PHP_PROTO_WRAP_OBJECT_END
PHP_METHOD(Descriptor, getClass);
......@@ -835,9 +875,13 @@ PHP_METHOD(FieldDescriptor, getMessageType);
extern zend_class_entry* field_descriptor_type;
PHP_PROTO_WRAP_OBJECT_START(EnumDescriptor)
struct EnumDescriptorInternal {
const upb_enumdef* enumdef;
zend_class_entry* klass; // begins as NULL
};
PHP_PROTO_WRAP_OBJECT_START(EnumDescriptor)
EnumDescriptorInternal* intern;
PHP_PROTO_WRAP_OBJECT_END
PHP_METHOD(EnumDescriptor, getValue);
......@@ -943,7 +987,8 @@ struct MessageLayout {
PHP_PROTO_WRAP_OBJECT_START(MessageHeader)
void* data; // Point to the real message data.
// Place needs to be consistent with map_parse_frame_data_t.
Descriptor* descriptor; // Kept alive by self.class.descriptor reference.
DescriptorInternal* descriptor; // Kept alive by self.class.descriptor
// reference.
PHP_PROTO_WRAP_OBJECT_END
MessageLayout* create_layout(const upb_msgdef* msgdef);
......@@ -985,7 +1030,7 @@ PHP_METHOD(Message, __construct);
const upb_pbdecodermethod *new_fillmsg_decodermethod(Descriptor *desc,
const void *owner);
void serialize_to_string(zval* val, zval* return_value TSRMLS_DC);
void merge_from_string(const char* data, int data_len, Descriptor* desc,
void merge_from_string(const char* data, int data_len, DescriptorInternal* desc,
MessageHeader* msg);
PHP_METHOD(Message, serializeToString);
......@@ -1491,8 +1536,11 @@ size_t stringsink_string(void *_sink, const void *hd, const char *ptr,
// -----------------------------------------------------------------------------
// Memory management
#define SYS_MALLOC(class_name) (class_name*) malloc(sizeof(class_name))
#define SYS_MALLOC_N(class_name, n) (class_name*) malloc(sizeof(class_name) * n)
#define SYS_FREE(ptr) free(ptr)
#define ALLOC(class_name) (class_name*) emalloc(sizeof(class_name))
#define PEMALLOC(class_name) (class_name*) pemalloc(sizeof(class_name), 1)
#define PEMALLOC(class_name, persistent) (class_name*) pemalloc(sizeof(class_name), persistent)
#define ALLOC_N(class_name, n) (class_name*) emalloc(sizeof(class_name) * n)
#define FREE(object) efree(object)
#define PEFREE(object) pefree(object, 1)
......
......@@ -550,12 +550,11 @@ const upb_fielddef* map_entry_value(const upb_msgdef* msgdef) {
const zend_class_entry* field_type_class(
const upb_fielddef* field PHP_PROTO_TSRMLS_DC) {
if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
Descriptor* desc = UNBOX_HASHTABLE_VALUE(
Descriptor, get_def_obj(upb_fielddef_msgsubdef(field)));
DescriptorInternal* desc = get_msgdef_desc(upb_fielddef_msgsubdef(field));
return desc->klass;
} else if (upb_fielddef_type(field) == UPB_TYPE_ENUM) {
EnumDescriptor* desc = UNBOX_HASHTABLE_VALUE(
EnumDescriptor, get_def_obj(upb_fielddef_enumsubdef(field)));
EnumDescriptorInternal* desc =
get_enumdef_enumdesc(upb_fielddef_enumsubdef(field));
return desc->klass;
}
return NULL;
......@@ -587,7 +586,7 @@ void* slot_memory(MessageLayout* layout, const void* storage,
}
MessageLayout* create_layout(const upb_msgdef* msgdef) {
MessageLayout* layout = ALLOC(MessageLayout);
MessageLayout* layout = SYS_MALLOC(MessageLayout);
int nfields = upb_msgdef_numfields(msgdef);
upb_msg_field_iter it;
upb_msg_oneof_iter oit;
......@@ -600,8 +599,8 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) {
layout->empty_template = NULL;
TSRMLS_FETCH();
Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj(msgdef));
layout->fields = ALLOC_N(MessageField, nfields);
DescriptorInternal* desc = get_msgdef_desc(msgdef);
layout->fields = SYS_MALLOC_N(MessageField, nfields);
for (upb_msg_field_begin(&it, msgdef); !upb_msg_field_done(&it);
upb_msg_field_next(&it)) {
......@@ -745,16 +744,16 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) {
layout->msgdef = msgdef;
// Create the empty message template.
layout->empty_template = ALLOC_N(char, layout->size);
layout->empty_template = SYS_MALLOC_N(char, layout->size);
memset(layout->empty_template, 0, layout->size);
return layout;
}
void free_layout(MessageLayout* layout) {
FREE(layout->empty_template);
FREE(layout->fields);
FREE(layout);
SYS_FREE(layout->empty_template);
SYS_FREE(layout->fields);
SYS_FREE(layout);
}
void layout_init(MessageLayout* layout, void* storage,
......@@ -822,9 +821,7 @@ zval* layout_get(MessageLayout* layout, MessageHeader* header,
const upb_msgdef* submsgdef = upb_fielddef_msgsubdef(field);
const upb_fielddef* value_field = upb_msgdef_itof(submsgdef, 1);
MessageHeader* submsg;
Descriptor* subdesc =
UNBOX_HASHTABLE_VALUE(
Descriptor, get_def_obj((void*)submsgdef));
DescriptorInternal* subdesc = get_msgdef_desc(submsgdef);
zend_class_entry* subklass = subdesc->klass;
#if PHP_MAJOR_VERSION < 7
zval* val = NULL;
......@@ -879,8 +876,7 @@ void layout_set(MessageLayout* layout, MessageHeader* header,
if (upb_fielddef_descriptortype(valuefield) ==
UPB_DESCRIPTOR_TYPE_MESSAGE) {
const upb_msgdef* submsg = upb_fielddef_msgsubdef(valuefield);
Descriptor* subdesc =
UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj(submsg));
DescriptorInternal* subdesc = get_msgdef_desc(submsg);
subce = subdesc->klass;
}
check_map_field(subce, upb_fielddef_descriptortype(keyfield),
......@@ -889,8 +885,7 @@ void layout_set(MessageLayout* layout, MessageHeader* header,
} else {
if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
const upb_msgdef* submsg = upb_fielddef_msgsubdef(field);
Descriptor* subdesc =
UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj(submsg));
DescriptorInternal* subdesc = get_msgdef_desc(submsg);
subce = subdesc->klass;
}
......@@ -912,7 +907,7 @@ void layout_set(MessageLayout* layout, MessageHeader* header,
zend_class_entry *ce = NULL;
if (type == UPB_TYPE_MESSAGE) {
const upb_msgdef* msg = upb_fielddef_msgsubdef(field);
Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj(msg));
DescriptorInternal* desc = get_msgdef_desc(msg);
ce = desc->klass;
}
CACHED_VALUE* cache = find_zval_property(header, field);
......@@ -950,7 +945,7 @@ static void native_slot_merge(
break;
case UPB_TYPE_MESSAGE: {
const upb_msgdef* msg = upb_fielddef_msgsubdef(field);
Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj(msg));
DescriptorInternal* desc = get_msgdef_desc(msg);
ce = desc->klass;
if (native_slot_is_default(type, to_memory)) {
#if PHP_MAJOR_VERSION < 7
......@@ -996,7 +991,7 @@ static void native_slot_merge_by_array(const upb_fielddef* field, const void* fr
}
case UPB_TYPE_MESSAGE: {
const upb_msgdef* msg = upb_fielddef_msgsubdef(field);
Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj(msg));
DescriptorInternal* desc = get_msgdef_desc(upb_fielddef_msgsubdef(field));
zend_class_entry* ce = desc->klass;
#if PHP_MAJOR_VERSION < 7
MAKE_STD_ZVAL(DEREF(to_memory, zval*));
......
......@@ -4589,6 +4589,13 @@ const upb_filedef *upb_symtab_lookupfile(const upb_symtab *s, const char *name)
: NULL;
}
const upb_filedef *upb_symtab_lookupfile2(
const upb_symtab *s, const char *name, size_t len) {
upb_value v;
return upb_strtable_lookup2(&s->files, name, len, &v) ?
upb_value_getconstptr(v) : NULL;
}
const upb_filedef *upb_symtab_addfile(
upb_symtab *s, const google_protobuf_FileDescriptorProto *file_proto,
upb_status *status) {
......
......@@ -3760,6 +3760,8 @@ const upb_msgdef *upb_symtab_lookupmsg2(
const upb_symtab *s, const char *sym, size_t len);
const upb_enumdef *upb_symtab_lookupenum(const upb_symtab *s, const char *sym);
const upb_filedef *upb_symtab_lookupfile(const upb_symtab *s, const char *name);
const upb_filedef *upb_symtab_lookupfile2(
const upb_symtab *s, const char *name, size_t len);
int upb_symtab_filecount(const upb_symtab *s);
const upb_filedef *upb_symtab_addfile(
upb_symtab *s, const google_protobuf_FileDescriptorProto *file,
......
......@@ -20,12 +20,22 @@ do
echo ""
done
for t in "${tests[@]}"
do
echo "****************************"
echo "* $t persistent"
echo "****************************"
php -d protobuf.keep_descriptor_pool_after_request=1 -dextension=../ext/google/protobuf/modules/protobuf.so `which phpunit` --bootstrap autoload.php $t
echo ""
done
# # Make sure to run the memory test in debug mode.
# php -dextension=../ext/google/protobuf/modules/protobuf.so memory_leak_test.php
export ZEND_DONT_UNLOAD_MODULES=1
export USE_ZEND_ALLOC=0
valgrind --leak-check=yes php -dextension=../ext/google/protobuf/modules/protobuf.so memory_leak_test.php
valgrind --leak-check=yes php -d protobuf.keep_descriptor_pool_after_request=1 -dextension=../ext/google/protobuf/modules/protobuf.so memory_leak_test.php
# TODO(teboring): Only for debug (phpunit has memory leak which blocks this beging used by
# regresssion test.)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment