Re: [PHP-DEV] Zend fast cache

2002-12-01 Thread Sterling Hughes
 At 07:17 PM 11/30/2002 -0500, Sterling Hughes wrote:
 hrm. :)
 
 My only question is really about sequential accesses.  for the purpose of 
 example
 let's pretend its just for zvals...
 
 (pool is our pool array of zval structs)
 ALLOC_ZVAL()
  - Do we have a zval available?
   - yes!
- return pool[0][0]
 
 ALLOC_ZVAL()
 ...
  - return pool[0][1]
 
 ALLOC_ZVAL()
 ...
  - return pool[0][2]
 
 FREE_ZVAL()
  - Clear memory @ pool[0][1]
 
 ALLOC_ZVAL()
  - Do we have a zval available?
- return pool[0][3] or do we return pool[0][1]
 
 The problem I see with an array approach from an api perspective is simply 
 when a bucket
 is free'd, in order to have efficient memory usage, we'd need a second 
 level array scan
 for every ALLOC_ZVAL().
 
 Perhaps a linked list would be a better choice for this, as we can just be 
 smart about bucket
 access, and eliminate the need for a scan (could be possible I'm missing 
 something?)
 
 I think I was misunderstood. Of course I would want a free list.
 Check out the objects_store code in ZE2. The idea is to have something 
 similar. When we free allocated buckets we add them to a linked list. The 
 linked list is inside the structure itself, i.e., when the bucket isn't 
 used we can use its memory for the pointer to the next element. So 
 allocation just takes the bucket out of the free list. So basically the 
 bucket is a union between sizeof(zval) and sizeof(*) (or sizeof(int)).
 If it's still not clear I can explain it in a longer letter later on.


Ok, i understand - you basically are doing the linked list approach, but 
using a two-tiered storage paradigm to avoid fragmentation?

My only thought now is the dirty specifics:

1) Thread-safety: Will we have to mutex access to this cache?  We shouldn't
get corruption (I'd assume that on threaded environments we'd use a shared
cache) if we have multiple accesses, and if we mutex, we might as well malloc().

2) Growing buffer sizes.  Say we have a _really_ intensive script that does 
make us grow our zval/object/hashtable cache substantially, however, it is run
once every blue moon.  Do we after execution is finished than realloc() that huge
buffer back down to a normal size?  Or perhaps we should just malloc() after a 
certain size is reached  (ok, 16k of prealloc'd stuff, if we don't have a free 
slot, just do uncached mallocs).

-Sterling

-- 
PHP Development Mailing List http://www.php.net/
To unsubscribe, visit: http://www.php.net/unsub.php




Re: [PHP-DEV] Zend fast cache

2002-12-01 Thread Andi Gutmans
At 05:27 PM 12/1/2002 -0500, Sterling Hughes wrote:

 At 07:17 PM 11/30/2002 -0500, Sterling Hughes wrote:
 hrm. :)
 
 My only question is really about sequential accesses.  for the purpose of
 example
 let's pretend its just for zvals...
 
 (pool is our pool array of zval structs)
 ALLOC_ZVAL()
  - Do we have a zval available?
   - yes!
- return pool[0][0]
 
 ALLOC_ZVAL()
 ...
  - return pool[0][1]
 
 ALLOC_ZVAL()
 ...
  - return pool[0][2]
 
 FREE_ZVAL()
  - Clear memory @ pool[0][1]
 
 ALLOC_ZVAL()
  - Do we have a zval available?
- return pool[0][3] or do we return pool[0][1]
 
 The problem I see with an array approach from an api perspective is 
simply
 when a bucket
 is free'd, in order to have efficient memory usage, we'd need a second
 level array scan
 for every ALLOC_ZVAL().
 
 Perhaps a linked list would be a better choice for this, as we can 
just be
 smart about bucket
 access, and eliminate the need for a scan (could be possible I'm missing
 something?)

 I think I was misunderstood. Of course I would want a free list.
 Check out the objects_store code in ZE2. The idea is to have something
 similar. When we free allocated buckets we add them to a linked list. The
 linked list is inside the structure itself, i.e., when the bucket isn't
 used we can use its memory for the pointer to the next element. So
 allocation just takes the bucket out of the free list. So basically the
 bucket is a union between sizeof(zval) and sizeof(*) (or sizeof(int)).
 If it's still not clear I can explain it in a longer letter later on.


Ok, i understand - you basically are doing the linked list approach, but
using a two-tiered storage paradigm to avoid fragmentation?

My only thought now is the dirty specifics:

1) Thread-safety: Will we have to mutex access to this cache?  We shouldn't
get corruption (I'd assume that on threaded environments we'd use a shared
cache) if we have multiple accesses, and if we mutex, we might as well 
malloc().

This pool would be per-thread.


2) Growing buffer sizes.  Say we have a _really_ intensive script that does
make us grow our zval/object/hashtable cache substantially, however, it is run
once every blue moon.  Do we after execution is finished than realloc() 
that huge
buffer back down to a normal size?  Or perhaps we should just malloc() 
after a
certain size is reached  (ok, 16k of prealloc'd stuff, if we don't have a 
free
slot, just do uncached mallocs).

We'd recreate the cache ever request. It wouldn't cost very much. By the 
way, I think you did misunderstand me. In my way there wouldn't be a huge 
buffer. We'd have X buffers. Basically my idea was a two-dimensional array:
arr[0] - buffer of size n
arr[1] - buffer of size n
arr[2] - buffer of size n
arr[3] - buffer of size n
.
And we allocate buffers as needed. Block 1*n+4 would be in arr[1] slot 5

Andi


--
PHP Development Mailing List http://www.php.net/
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] Zend fast cache

2002-11-30 Thread Sterling Hughes
Hey,

I was checking the CVS logs, and I read ::

revision 1.13
date: 2001/11/26 17:27:59;  author: andi;  state: Exp;  lines: +1 -1
- Turn off fast cache until we make sure it performs well.
- The best solution is probably to limit its size.

I was just wondering what was wrong, and what it would take to 
get this thing up and running... Thies and I were looking at a 
little hack, similiar in nature to this, with preallocating a pool of
zval's, and it yielded a 5% performance increase (all hacking credit 
goes to thies btw :).

If we preallocated some basic, often used types, i think we'd get a 
nice performance increase, perhaps even if we initialized in sapi 
modes a few structures in MINIT, we could reuse those instead of 
creating and destroying which is currently quite expensive?

-Sterling

-- 
PHP Development Mailing List http://www.php.net/
To unsubscribe, visit: http://www.php.net/unsub.php




Re: [PHP-DEV] Zend fast cache

2002-11-30 Thread Andi Gutmans
At 02:59 PM 11/30/2002 -0500, Sterling Hughes wrote:

Hey,

I was checking the CVS logs, and I read ::

revision 1.13
date: 2001/11/26 17:27:59;  author: andi;  state: Exp;  lines: +1 -1
- Turn off fast cache until we make sure it performs well.
- The best solution is probably to limit its size.

I was just wondering what was wrong, and what it would take to
get this thing up and running... Thies and I were looking at a
little hack, similiar in nature to this, with preallocating a pool of
zval's, and it yielded a 5% performance increase (all hacking credit
goes to thies btw :).


First of all, let me just say that I wouldn't be too excited about 5% 
performance difference either way. I already told Thies that from my 
experience 5% is within the error margin and can change according to 
compile flags, platform and so on.
The reason why the fast cache didn't work well was because it created quite 
a bit of memory fragmentation which killed MT servers and also made PHP 
take up too much memory.

If we preallocated some basic, often used types, i think we'd get a
nice performance increase, perhaps even if we initialized in sapi
modes a few structures in MINIT, we could reuse those instead of
creating and destroying which is currently quite expensive?


That said, I do think that if we can get very fast code to pre-allocate 
zval's it would be a good idea (hopefully we could get more than 5% increase).
I already have an idea for how I would want such an API to look like and I 
was planning to write it. It would also be useful for Zend objects which 
are preallocated today but if a realloc() were to be reached it would take 
quite some time (although one or two realloc()'s wouldn't be terrible).
My idea is a two dimensional array. We'd allocate 2^n of memory blocks and 
assign it to array[0]. Once these are full we'd allocate another 2^n memory 
blocks and realloc() array to size of 2 and make array[1] point to it. The 
index to a block would be X and to find the right position it'd be 
array[X/2^n][X%2^n] of course as the length of each array is a power of two 
we wouldn't actually need to use division and modulo so it'd be fast.
As we don't have templates in C we might be able to put all of this inline 
in a header file and with macros create such a fast allocating pool for 
some of the most used types specifically I think it'd be useful for zval's, 
objects and possible hash tables. I wouldn't overdo the amount of types I'd 
add to this pool because unless they are allocated and freed extremely 
often we wouldn't notice a speed difference.

But remember what I said about 5% :)
Andi


--
PHP Development Mailing List http://www.php.net/
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Zend fast cache

2002-11-30 Thread Sterling Hughes
 At 02:59 PM 11/30/2002 -0500, Sterling Hughes wrote:
 Hey,
 
 I was checking the CVS logs, and I read ::
 
 revision 1.13
 date: 2001/11/26 17:27:59;  author: andi;  state: Exp;  lines: +1 -1
 - Turn off fast cache until we make sure it performs well.
 - The best solution is probably to limit its size.
 
 I was just wondering what was wrong, and what it would take to
 get this thing up and running... Thies and I were looking at a
 little hack, similiar in nature to this, with preallocating a pool of
 zval's, and it yielded a 5% performance increase (all hacking credit
 goes to thies btw :).
 
 First of all, let me just say that I wouldn't be too excited about 5% 
 performance difference either way. I already told Thies that from my 
 experience 5% is within the error margin and can change according to 
 compile flags, platform and so on.

perhaps... this was 5% worse case though, comparing to similairly compiled
source trees.  In some cases it yielded 15-30% percent, but that can be
as you say, attributed to flukes.

Still, it would follow that having a memory cache would be a good thing,
even if it does only show 5% (on a small script btw)...

 The reason why the fast cache didn't work well was because it created quite 
 a bit of memory fragmentation which killed MT servers and also made PHP 
 take up too much memory.

 If we preallocated some basic, often used types, i think we'd get a
 nice performance increase, perhaps even if we initialized in sapi
 modes a few structures in MINIT, we could reuse those instead of
 creating and destroying which is currently quite expensive?
 
 That said, I do think that if we can get very fast code to pre-allocate 
 zval's it would be a good idea (hopefully we could get more than 5% 
 increase).
 I already have an idea for how I would want such an API to look like and I 
 was planning to write it. It would also be useful for Zend objects which 
 are preallocated today but if a realloc() were to be reached it would take 
 quite some time (although one or two realloc()'s wouldn't be terrible).

no it wouldn't, and you've also gotta look @ this in terms of what would 
cause a realloc(), for example, say we have a 16 k pool, hardly anything, and
yet we'd need to have _a ton_ of concurrently allocated zvals in order to 
fill that up.

Plus, while the realloc would be expensive, it would be better than doing that
many mallocs.  Anyhow, we pretty much agree, soo :)

 My idea is a two dimensional array. We'd allocate 2^n of memory blocks and 
 assign it to array[0]. Once these are full we'd allocate another 2^n memory 
 blocks and realloc() array to size of 2 and make array[1] point to it. The 
 index to a block would be X and to find the right position it'd be 
 array[X/2^n][X%2^n] of course as the length of each array is a power of two 
 we wouldn't actually need to use division and modulo so it'd be fast.
 As we don't have templates in C we might be able to put all of this inline 
 in a header file and with macros create such a fast allocating pool for 
 some of the most used types specifically I think it'd be useful for zval's, 
 objects and possible hash tables. I wouldn't overdo the amount of types I'd 
 add to this pool because unless they are allocated and freed extremely 
 often we wouldn't notice a speed difference.
 
 But remember what I said about 5% :)

hrm. :)

My only question is really about sequential accesses.  for the purpose of example
let's pretend its just for zvals...

(pool is our pool array of zval structs)
ALLOC_ZVAL()
 - Do we have a zval available?
  - yes!
   - return pool[0][0]

ALLOC_ZVAL()
...
 - return pool[0][1]

ALLOC_ZVAL()
...
 - return pool[0][2]

FREE_ZVAL()
 - Clear memory @ pool[0][1]

ALLOC_ZVAL()
 - Do we have a zval available?
   - return pool[0][3] or do we return pool[0][1]

The problem I see with an array approach from an api perspective is simply when a 
bucket
is free'd, in order to have efficient memory usage, we'd need a second level array 
scan 
for every ALLOC_ZVAL().

Perhaps a linked list would be a better choice for this, as we can just be smart about 
bucket
access, and eliminate the need for a scan (could be possible I'm missing something?)

-Sterling

-- 
PHP Development Mailing List http://www.php.net/
To unsubscribe, visit: http://www.php.net/unsub.php




Re: [PHP-DEV] Zend fast cache

2002-11-30 Thread George Schlossnagle
How does searching the freelist work in this? How is this faster than 
say a 3-level page table implementation?

That said, I do think that if we can get very fast code to pre-allocate 
zval's it would be a good idea (hopefully we could get more than 5% 
increase).
I already have an idea for how I would want such an API to look like 
and I was planning to write it. It would also be useful for Zend 
objects which are preallocated today but if a realloc() were to be 
reached it would take quite some time (although one or two realloc()'s 
wouldn't be terrible).
My idea is a two dimensional array. We'd allocate 2^n of memory blocks 
and assign it to array[0]. Once these are full we'd allocate another 
2^n memory blocks and realloc() array to size of 2 and make array[1] 
point to it. The index to a block would be X and to find the right 
position it'd be array[X/2^n][X%2^n] of course as the length of each 
array is a power of two we wouldn't actually need to use division and 
modulo so it'd be fast.
As we don't have templates in C we might be able to put all of this 
inline in a header file and with macros create such a fast allocating 
pool for some of the most used types specifically I think it'd be 
useful for zval's, objects and possible hash tables. I wouldn't overdo 
the amount of types I'd add to this pool because unless they are 
allocated and freed extremely often we wouldn't notice a speed 
difference.

But remember what I said about 5% :)
Andi


--
PHP Development Mailing List http://www.php.net/
To unsubscribe, visit: http://www.php.net/unsub.php



--
PHP Development Mailing List http://www.php.net/
To unsubscribe, visit: http://www.php.net/unsub.php




Re: [PHP-DEV] Zend fast cache

2002-11-30 Thread Daniel Cowgill

On Saturday, November 30, 2002, at 07:17 PM, Sterling Hughes wrote:


The problem I see with an array approach from an api perspective is 
simply when a bucket
is free'd, in order to have efficient memory usage, we'd need a second 
level array scan
for every ALLOC_ZVAL().

Perhaps a linked list would be a better choice for this, as we can 
just be smart about bucket
access, and eliminate the need for a scan (could be possible I'm 
missing something?)

I agree, a singly linked list seems like a no-brainer; it's an ideal 
memory-pool data structure because inserts and deletes occur only at 
the front of the list (so they're constant-time), the links are free, 
and the implementation is straightforward.


--
PHP Development Mailing List http://www.php.net/
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Zend fast cache

2002-11-30 Thread George Schlossnagle
The problem I see with an array approach from an api perspective is 
simply when a bucket
is free'd, in order to have efficient memory usage, we'd need a second 
level array scan
for every ALLOC_ZVAL().

Perhaps a linked list would be a better choice for this, as we can 
just be smart about bucket
access, and eliminate the need for a scan (could be possible I'm 
missing something?)

A number of memory allocators use a multi-tiered page table for this.  
basically for each object type you have a array of N pointers to level 
1 objects and a freelist for them, basically tier one has N elements 
that each contain a freelist bitmask value and an array of pointers to 
level 2 objects.  Level 2 objects have a freelist of N allocations for 
the desired object type and pointers to each of them.  This may be what 
Andi was talking about, but it wasn't clear to me from his description.

So you get N^3 aloocations you can track, and a freelist search 
involves looking at 3 bitmasks.  Significantly faster than a linked 
list implementation.  By keeping a separate tree for each allocation 
type (or at least allocation size), you also end up with basically no 
fragmentation.



-Sterling

--
PHP Development Mailing List http://www.php.net/
To unsubscribe, visit: http://www.php.net/unsub.php




--
PHP Development Mailing List http://www.php.net/
To unsubscribe, visit: http://www.php.net/unsub.php




Re: [PHP-DEV] Zend fast cache

2002-11-30 Thread George Schlossnagle
A little off-list discussion has sold me on the linked list 
implementation.  Seems very fast and very simple.

George


On Saturday, November 30, 2002, at 07:53  PM, Daniel Cowgill wrote:


On Saturday, November 30, 2002, at 07:17 PM, Sterling Hughes wrote:


The problem I see with an array approach from an api perspective is 
simply when a bucket
is free'd, in order to have efficient memory usage, we'd need a 
second level array scan
for every ALLOC_ZVAL().

Perhaps a linked list would be a better choice for this, as we can 
just be smart about bucket
access, and eliminate the need for a scan (could be possible I'm 
missing something?)

I agree, a singly linked list seems like a no-brainer; it's an ideal 
memory-pool data structure because inserts and deletes occur only at 
the front of the list (so they're constant-time), the links are free, 
and the implementation is straightforward.


--
PHP Development Mailing List http://www.php.net/
To unsubscribe, visit: http://www.php.net/unsub.php



--
PHP Development Mailing List http://www.php.net/
To unsubscribe, visit: http://www.php.net/unsub.php




Re: [PHP-DEV] Zend fast cache

2002-11-30 Thread Sascha Schumann
On Sat, 30 Nov 2002, George Schlossnagle wrote:

 A little off-list discussion has sold me on the linked list
 implementation.  Seems very fast and very simple.

O(1) operations are hard to beat.  Note that free lists are
not primarily about speed, they are also an extremely helpful
tool in the fight against memory fragmentation.

That said, IRCG has been using single-linked lists for its
free lists (3 or 4 data structures) since its inception.  I'm
moving IRCG right now to a multi-process model and still need
to evaluate whether a central free list (based in shared
memory and protected by a semaphore) actually works that
well.  For example, lock contention issues could affect the
performance.  Some systems in the kernel world use per-node
(=CPU) locks which might prove to be a necessary step for
applications as well.

- Sascha


-- 
PHP Development Mailing List http://www.php.net/
To unsubscribe, visit: http://www.php.net/unsub.php




Re: [PHP-DEV] Zend fast cache

2002-11-30 Thread Andi Gutmans
At 07:17 PM 11/30/2002 -0500, Sterling Hughes wrote:

hrm. :)

My only question is really about sequential accesses.  for the purpose of 
example
let's pretend its just for zvals...

(pool is our pool array of zval structs)
ALLOC_ZVAL()
 - Do we have a zval available?
  - yes!
   - return pool[0][0]

ALLOC_ZVAL()
...
 - return pool[0][1]

ALLOC_ZVAL()
...
 - return pool[0][2]

FREE_ZVAL()
 - Clear memory @ pool[0][1]

ALLOC_ZVAL()
 - Do we have a zval available?
   - return pool[0][3] or do we return pool[0][1]

The problem I see with an array approach from an api perspective is simply 
when a bucket
is free'd, in order to have efficient memory usage, we'd need a second 
level array scan
for every ALLOC_ZVAL().

Perhaps a linked list would be a better choice for this, as we can just be 
smart about bucket
access, and eliminate the need for a scan (could be possible I'm missing 
something?)

I think I was misunderstood. Of course I would want a free list.
Check out the objects_store code in ZE2. The idea is to have something 
similar. When we free allocated buckets we add them to a linked list. The 
linked list is inside the structure itself, i.e., when the bucket isn't 
used we can use its memory for the pointer to the next element. So 
allocation just takes the bucket out of the free list. So basically the 
bucket is a union between sizeof(zval) and sizeof(*) (or sizeof(int)).
If it's still not clear I can explain it in a longer letter later on.

Andi


--
PHP Development Mailing List http://www.php.net/
To unsubscribe, visit: http://www.php.net/unsub.php