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

Preallocate global memory frames in advance #1987

Merged
merged 3 commits into from Feb 7, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions ext/config/adapter/php.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
+------------------------------------------------------------------------+
*/

#include "php_phalcon.h"

#include "config/adapter/php.h"
#include "config/exception.h"
#include "pconfig.h"
Expand Down Expand Up @@ -104,6 +102,7 @@ PHP_METHOD(Phalcon_Config_Adapter_Php, __construct){
}

PHALCON_MM_GROW();
Z_DELREF_P(config);
PHALCON_CALL_PARENT_NORET(phalcon_config_adapter_php_ce, this_ptr, "__construct", config);
PHALCON_MM_RESTORE();
}
156 changes: 78 additions & 78 deletions ext/kernel/memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,17 @@
* allocated empty frame that points to the real first frame. The start
* memory frame is globally accesed using PHALCON_GLOBAL(start_frame)
*
* Not all methods must grown/restore the phalcon_memory_entry.
* Not all methods must grow/restore the phalcon_memory_entry.
*/

static phalcon_memory_entry* phalcon_memory_grow_stack_common(zend_phalcon_globals *phalcon_globals_ptr)
static phalcon_memory_entry* phalcon_memory_grow_stack_common(zend_phalcon_globals *g)
{
assert(phalcon_globals_ptr->start_memory != NULL);
if (!phalcon_globals_ptr->active_memory) {
phalcon_globals_ptr->active_memory = phalcon_globals_ptr->start_memory;
return phalcon_globals_ptr->start_memory;
assert(g->start_memory != NULL);
if (!g->active_memory) {
g->active_memory = g->start_memory;
}

{
else if (!g->active_memory->next) {
assert(g->active_memory >= g->end_memory - 1 || g->active_memory < g->start_memory);
phalcon_memory_entry *entry = (phalcon_memory_entry *) ecalloc(1, sizeof(phalcon_memory_entry));
/* ecalloc() will take care of these members
entry->pointer = 0;
Expand All @@ -62,53 +61,43 @@ static phalcon_memory_entry* phalcon_memory_grow_stack_common(zend_phalcon_globa
entry->hash_addresses = NULL;
entry->next = NULL;
*/
entry->prev = phalcon_globals_ptr->active_memory;
entry->prev = g->active_memory;
entry->prev->next = entry;
phalcon_globals_ptr->active_memory = entry;
return entry;
g->active_memory = entry;
}
else {
assert(g->active_memory < g->end_memory);
g->active_memory = g->active_memory->next;
}
}

static void phalcon_memory_restore_stack_common(zend_phalcon_globals *phalcon_globals_ptr TSRMLS_DC) {
return g->active_memory;
}

static void phalcon_memory_restore_stack_common(zend_phalcon_globals *g TSRMLS_DC)
{
size_t i;
phalcon_memory_entry *prev, *active_memory;
phalcon_symbol_table *active_symbol_table;
/*
#if ZEND_DEBUG
char* __zend_filename = __FILE__;
char* __zend_orig_filename = __FILE__;
int __zend_lineno = 0;
int __zend_orig_lineno = 0;
#endif
*/

active_memory = phalcon_globals_ptr->active_memory;
active_memory = g->active_memory;
assert(active_memory != NULL);

if (likely(!CG(unclean_shutdown))) {
if (EXPECTED(!CG(unclean_shutdown))) {
/* Clean active symbol table */
if (phalcon_globals_ptr->active_symbol_table) {
active_symbol_table = phalcon_globals_ptr->active_symbol_table;
if (g->active_symbol_table) {
active_symbol_table = g->active_symbol_table;
if (active_symbol_table->scope == active_memory) {
zend_hash_destroy(EG(active_symbol_table));
FREE_HASHTABLE(EG(active_symbol_table));
EG(active_symbol_table) = active_symbol_table->symbol_table;
phalcon_globals_ptr->active_symbol_table = active_symbol_table->prev;
g->active_symbol_table = active_symbol_table->prev;
efree(active_symbol_table);
}
}

/**
* Check for non freed hash key zvals, mark as null to avoid string freeing
*/
/* Check for non freed hash key zvals, mark as null to avoid string freeing */
for (i = 0; i < active_memory->hash_pointer; ++i) {
assert(active_memory->hash_addresses[i] != NULL && *(active_memory->hash_addresses[i]) != NULL);
/*
#if ZEND_DEBUG
_mem_block_check(*active_memory->hash_addresses[i], 1 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
#endif
*/
if (Z_REFCOUNT_PP(active_memory->hash_addresses[i]) <= 1) {
ZVAL_NULL(*active_memory->hash_addresses[i]);
} else {
Expand All @@ -118,13 +107,8 @@ static void phalcon_memory_restore_stack_common(zend_phalcon_globals *phalcon_gl

#ifndef PHALCON_RELEASE
for (i = 0; i < active_memory->pointer; ++i) {
if (likely(active_memory->addresses[i] != NULL && *(active_memory->addresses[i]) != NULL)) {
if (active_memory->addresses[i] != NULL && *(active_memory->addresses[i]) != NULL) {
zval **var = active_memory->addresses[i];
/*
#if ZEND_DEBUG
_mem_block_check(*var, 1 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
#endif
*/
#if PHP_VERSION_ID < 50400
if (Z_TYPE_PP(var) > IS_CONSTANT_ARRAY) {
fprintf(stderr, "%s: observed variable #%d (%p) has invalid type %u\n", __func__, (int)i, *var, Z_TYPE_PP(var));
Expand All @@ -148,11 +132,9 @@ static void phalcon_memory_restore_stack_common(zend_phalcon_globals *phalcon_gl
}
#endif

/**
* Traverse all zvals allocated, reduce the reference counting or free them
*/
/* Traverse all zvals allocated, reduce the reference counting or free them */
for (i = 0; i < active_memory->pointer; ++i) {
if (likely(active_memory->addresses[i] != NULL && *(active_memory->addresses[i]) != NULL)) {
if (EXPECTED(active_memory->addresses[i] != NULL && *(active_memory->addresses[i]) != NULL)) {
if (Z_REFCOUNT_PP(active_memory->addresses[i]) == 1) {
zval_ptr_dtor(active_memory->addresses[i]);
} else {
Expand All @@ -164,25 +146,37 @@ static void phalcon_memory_restore_stack_common(zend_phalcon_globals *phalcon_gl

prev = active_memory->prev;

if (prev != NULL) {
if (active_memory >= g->end_memory || active_memory < g->start_memory) {
if (active_memory->hash_addresses != NULL) {
efree(active_memory->hash_addresses);
}

if (likely(active_memory->addresses != NULL)) {
if (active_memory->addresses != NULL) {
efree(active_memory->addresses);
}

efree(phalcon_globals_ptr->active_memory);
phalcon_globals_ptr->active_memory = prev;
efree(g->active_memory);
g->active_memory = prev;
prev->next = NULL;
} else {
assert(phalcon_globals_ptr->start_memory == active_memory);
assert(active_memory->next == NULL);
}
else {
active_memory->pointer = 0;
active_memory->hash_pointer = 0;
phalcon_globals_ptr->active_memory = NULL;
g->active_memory = prev;
}

#ifndef PHALCON_RELEASE
if (g->active_memory) {
phalcon_memory_entry *f = g->active_memory;
if (f >= g->end_memory && f < g->end_memory - 1) {
assert(f->next != NULL);

if (f > g->start_memory) {
assert(f->prev != NULL);
}
}
}
#endif
}

#ifndef PHALCON_RELEASE
Expand All @@ -203,7 +197,7 @@ void phalcon_dump_memory_frame(phalcon_memory_entry *active_memory TSRMLS_DC)
}

for (i = 0; i < active_memory->pointer; ++i) {
if (likely(active_memory->addresses[i] != NULL && *(active_memory->addresses[i]) != NULL)) {
if (EXPECTED(active_memory->addresses[i] != NULL && *(active_memory->addresses[i]) != NULL)) {
zval **var = active_memory->addresses[i];
fprintf(stderr, "Obs var %lu (%p => %p), type=%u, refcnt=%u; ", (ulong)i, var, *var, Z_TYPE_PP(var), Z_REFCOUNT_PP(var));
switch (Z_TYPE_PP(var)) {
Expand All @@ -227,7 +221,7 @@ void phalcon_dump_current_frame(TSRMLS_D)
{
zend_phalcon_globals *phalcon_globals_ptr = PHALCON_VGLOBAL;

if (unlikely(phalcon_globals_ptr->active_memory == NULL)) {
if (UNEXPECTED(phalcon_globals_ptr->active_memory == NULL)) {
fprintf(stderr, "WARNING: calling %s() without an active memory frame!\n", __func__);
phalcon_print_backtrace();
return;
Expand Down Expand Up @@ -257,13 +251,13 @@ int ZEND_FASTCALL phalcon_memory_restore_stack(const char *func TSRMLS_DC)
{
zend_phalcon_globals *phalcon_globals_ptr = PHALCON_VGLOBAL;

if (unlikely(phalcon_globals_ptr->active_memory == NULL)) {
if (UNEXPECTED(phalcon_globals_ptr->active_memory == NULL)) {
fprintf(stderr, "WARNING: calling phalcon_memory_restore_stack() without an active memory frame!\n");
phalcon_print_backtrace();
return FAILURE;
}

if (unlikely(phalcon_globals_ptr->active_memory->func != func)) {
if (UNEXPECTED(phalcon_globals_ptr->active_memory->func != func)) {
fprintf(stderr, "Trying to free someone else's memory frame!\n");
fprintf(stderr, "The frame was created by %s\n", phalcon_globals_ptr->active_memory->func);
fprintf(stderr, "Calling function: %s\n", func);
Expand Down Expand Up @@ -301,10 +295,11 @@ int ZEND_FASTCALL phalcon_memory_restore_stack(TSRMLS_D) {
}
#endif

static void phalcon_reallocate_memory(phalcon_memory_entry *frame)
PHALCON_ATTR_NONNULL static void phalcon_reallocate_memory(const zend_phalcon_globals *g)
{
void *buf = perealloc(frame->addresses, sizeof(zval **) * (frame->capacity + 16), unlikely(frame->prev == NULL));
if (likely(buf != NULL)) {
phalcon_memory_entry *frame = g->active_memory;
void *buf = perealloc(frame->addresses, sizeof(zval **) * (frame->capacity + 16), (frame < g->end_memory));
if (EXPECTED(buf != NULL)) {
frame->capacity += 16;
frame->addresses = buf;
}
Expand All @@ -313,10 +308,11 @@ static void phalcon_reallocate_memory(phalcon_memory_entry *frame)
}
}

static void phalcon_reallocate_hmemory(phalcon_memory_entry *frame)
PHALCON_ATTR_NONNULL static void phalcon_reallocate_hmemory(const zend_phalcon_globals *g)
{
void *buf = perealloc(frame->hash_addresses, sizeof(zval **) * (frame->hash_capacity + 4), unlikely(frame->prev == NULL));
if (likely(buf != NULL)) {
phalcon_memory_entry *frame = g->active_memory;
void *buf = perealloc(frame->hash_addresses, sizeof(zval **) * (frame->hash_capacity + 4), (frame < g->end_memory));
if (EXPECTED(buf != NULL)) {
frame->hash_capacity += 4;
frame->hash_addresses = buf;
}
Expand All @@ -325,18 +321,19 @@ static void phalcon_reallocate_hmemory(phalcon_memory_entry *frame)
}
}

static inline void phalcon_do_memory_observe(zval **var, phalcon_memory_entry *frame)
PHALCON_ATTR_NONNULL1(2) static inline void phalcon_do_memory_observe(zval **var, const zend_phalcon_globals *g)
{
phalcon_memory_entry *frame = g->active_memory;
#ifndef PHALCON_RELEASE
if (unlikely(frame == NULL)) {
if (UNEXPECTED(frame == NULL)) {
fprintf(stderr, "PHALCON_MM_GROW() must be called before using any of MM functions or macros!");
phalcon_print_backtrace();
abort();
}
#endif

if (unlikely(frame->pointer == frame->capacity)) {
phalcon_reallocate_memory(frame);
if (UNEXPECTED(frame->pointer == frame->capacity)) {
phalcon_reallocate_memory(g);
}

frame->addresses[frame->pointer] = var;
Expand All @@ -346,42 +343,45 @@ static inline void phalcon_do_memory_observe(zval **var, phalcon_memory_entry *f
/**
* Observes a memory pointer to release its memory at the end of the request
*/
void ZEND_FASTCALL phalcon_memory_observe(zval **var TSRMLS_DC) {

phalcon_do_memory_observe(var, PHALCON_GLOBAL(active_memory));
void ZEND_FASTCALL phalcon_memory_observe(zval **var TSRMLS_DC)
{
zend_phalcon_globals *g = PHALCON_VGLOBAL;
phalcon_do_memory_observe(var, g);
*var = NULL; /* In case an exception or error happens BEFORE the observed variable gets initialized */
}

/**
* Observes a variable and allocates memory for it
*/
void ZEND_FASTCALL phalcon_memory_alloc(zval **var TSRMLS_DC) {

phalcon_do_memory_observe(var, PHALCON_GLOBAL(active_memory));
void ZEND_FASTCALL phalcon_memory_alloc(zval **var TSRMLS_DC)
{
zend_phalcon_globals *g = PHALCON_VGLOBAL;
phalcon_do_memory_observe(var, g);
ALLOC_INIT_ZVAL(*var);
}

/**
* Observes a variable and allocates memory for it
* Marks hash key zvals to be nulled before freeing
*/
void ZEND_FASTCALL phalcon_memory_alloc_pnull(zval **var TSRMLS_DC) {

phalcon_memory_entry *active_memory = PHALCON_GLOBAL(active_memory);
void ZEND_FASTCALL phalcon_memory_alloc_pnull(zval **var TSRMLS_DC)
{
zend_phalcon_globals *g = PHALCON_VGLOBAL;
phalcon_memory_entry *active_memory = g->active_memory;

#ifndef PHALCON_RELEASE
if (unlikely(active_memory == NULL)) {
if (UNEXPECTED(active_memory == NULL)) {
fprintf(stderr, "PHALCON_MM_GROW() must be called before using any of MM functions or macros!");
phalcon_print_backtrace();
abort();
}
#endif

phalcon_do_memory_observe(var, active_memory);
phalcon_do_memory_observe(var, g);
ALLOC_INIT_ZVAL(*var);

if (active_memory->hash_pointer == active_memory->hash_capacity) {
phalcon_reallocate_hmemory(active_memory);
phalcon_reallocate_hmemory(g);
}

active_memory->hash_addresses[active_memory->hash_pointer] = var;
Expand Down
21 changes: 10 additions & 11 deletions ext/kernel/memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,23 +46,22 @@ int ZEND_FASTCALL phalcon_memory_restore_stack(TSRMLS_D);

#endif

extern void ZEND_FASTCALL phalcon_memory_observe(zval **var TSRMLS_DC);
extern void ZEND_FASTCALL phalcon_memory_remove(zval **var TSRMLS_DC);
extern void ZEND_FASTCALL phalcon_memory_alloc(zval **var TSRMLS_DC);
extern void ZEND_FASTCALL phalcon_memory_alloc_pnull(zval **var TSRMLS_DC);
void ZEND_FASTCALL phalcon_memory_observe(zval **var TSRMLS_DC) PHALCON_ATTR_NONNULL;
void ZEND_FASTCALL phalcon_memory_remove(zval **var TSRMLS_DC) PHALCON_ATTR_NONNULL;
void ZEND_FASTCALL phalcon_memory_alloc(zval **var TSRMLS_DC);
void ZEND_FASTCALL phalcon_memory_alloc_pnull(zval **var TSRMLS_DC);

extern int ZEND_FASTCALL phalcon_clean_restore_stack(TSRMLS_D);
int ZEND_FASTCALL phalcon_clean_restore_stack(TSRMLS_D);

/* Virtual symbol tables */
extern void phalcon_create_symbol_table(TSRMLS_D);
/*extern void phalcon_restore_symbol_table(TSRMLS_D);*/
extern void phalcon_clean_symbol_tables(TSRMLS_D);
void phalcon_create_symbol_table(TSRMLS_D);
void phalcon_clean_symbol_tables(TSRMLS_D);

/** Export symbols to active symbol table */
extern int phalcon_set_symbol(zval *key_name, zval *value TSRMLS_DC);
extern int phalcon_set_symbol_str(char *key_name, unsigned int key_length, zval *value TSRMLS_DC);
int phalcon_set_symbol(zval *key_name, zval *value TSRMLS_DC);
int phalcon_set_symbol_str(char *key_name, unsigned int key_length, zval *value TSRMLS_DC);

extern void ZEND_FASTCALL phalcon_copy_ctor(zval *destiny, zval *origin);
void ZEND_FASTCALL phalcon_copy_ctor(zval *destiny, zval *origin) PHALCON_ATTR_NONNULL;

/* Memory macros */
#define PHALCON_ALLOC_GHOST_ZVAL(z) \
Expand Down
2 changes: 1 addition & 1 deletion ext/kernel/string.c
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ void phalcon_fast_explode(zval *result, zval *delimiter, zval *str){
*/
void phalcon_fast_explode_str(zval *result, const char *delimiter, int delimiter_length, zval *str){

zval delimiter_zval;
zval delimiter_zval = zval_used_for_init;

if (unlikely(Z_TYPE_P(str) != IS_STRING)) {
ZVAL_NULL(result);
Expand Down
Loading