Hi everyone, thank team so much for development PHP interpreter.
I think this PR will reduce minimum requirements for hardware, and it will decrease costs copying, moving, and creating object-structures only for common 64bit processors due to the 8-byte data alignment.
Smaller size structure or class, higher chance putting into CPU cache. Most processors are already 64 bit, so the change won't make it any worse.
Info about technique:
https://hpc.rz.rptu.de/Tutorials/AVX/alignment.shtml
https://wr.informatik.uni-hamburg.de/_media/teaching/wintersemester_2013_2014/epc-14-haase-svenhendrik-alignmentinc-presentation.pdf
https://en.wikipedia.org/wiki/Data_structure_alignment
https://stackoverflow.com/a/20882083
https://zijishi.xyz/post/optimization-technique/learning-to-use-data-alignment/
Pahole log:
- Comment
/* XXX {n} bytes hole, try to pack */
shows where optimization is possible by rearranging the order of fields structures and classes
Master branch
struct _phpdbg_breakbase_t {
int id; /* 0 4 */
uint8_t type; /* 4 1 */
/* XXX 3 bytes hole, try to pack */
zend_ulong hits; /* 8 8 */
_Bool disabled; /* 16 1 */
/* XXX 7 bytes hole, try to pack */
const char * name; /* 24 8 */
/* size: 32, cachelines: 1, members: 5 */
/* sum members: 22, holes: 2, sum holes: 10 */
/* last cacheline: 32 bytes */
struct _phpdbg_breakop_t {
int id; /* 0 4 */
uint8_t type; /* 4 1 */
/* XXX 3 bytes hole, try to pack */
zend_ulong hits; /* 8 8 */
_Bool disabled; /* 16 1 */
/* XXX 7 bytes hole, try to pack */
const char * name; /* 24 8 */
zend_ulong hash; /* 32 8 */
/* size: 40, cachelines: 1, members: 6 */
/* sum members: 30, holes: 2, sum holes: 10 */
/* last cacheline: 40 bytes */
struct _phpdbg_breakcond_t {
int id; /* 0 4 */
uint8_t type; /* 4 1 */
/* XXX 3 bytes hole, try to pack */
zend_ulong hits; /* 8 8 */
_Bool disabled; /* 16 1 */
/* XXX 7 bytes hole, try to pack */
const char * code; /* 24 8 */
size_t code_len; /* 32 8 */
_Bool paramed; /* 40 1 */
/* XXX 7 bytes hole, try to pack */
phpdbg_param_t param; /* 48 88 */
/* --- cacheline 2 boundary (128 bytes) was 8 bytes ago --- */
zend_ulong hash; /* 136 8 */
zend_op_array * ops; /* 144 8 */
/* size: 152, cachelines: 3, members: 10 */
/* sum members: 135, holes: 3, sum holes: 17 */
/* last cacheline: 24 bytes */
struct _phpdbg_breaksymbol_t {
int id; /* 0 4 */
uint8_t type; /* 4 1 */
/* XXX 3 bytes hole, try to pack */
zend_ulong hits; /* 8 8 */
_Bool disabled; /* 16 1 */
/* XXX 7 bytes hole, try to pack */
const char * symbol; /* 24 8 */
/* size: 32, cachelines: 1, members: 5 */
/* sum members: 22, holes: 2, sum holes: 10 */
/* last cacheline: 32 bytes */
struct _zend_smm_shared_globals {
zend_shared_segment * * shared_segments; /* 0 8 */
int shared_segments_count; /* 8 4 */
/* XXX 4 bytes hole, try to pack */
size_t shared_free; /* 16 8 */
size_t wasted_shared_memory; /* 24 8 */
_Bool memory_exhausted; /* 32 1 */
/* XXX 7 bytes hole, try to pack */
zend_shared_memory_state shared_memory_state; /* 40 16 */
void * app_shared_globals; /* 56 8 */
/* --- cacheline 1 boundary (64 bytes) --- */
void * reserved; /* 64 8 */
size_t reserved_size; /* 72 8 */
/* size: 80, cachelines: 2, members: 9 */
/* sum members: 69, holes: 2, sum holes: 11 */
/* last cacheline: 16 bytes */
struct _phpdbg_command_t {
const char * name; /* 0 8 */
size_t name_len; /* 8 8 */
const char * tip; /* 16 8 */
size_t tip_len; /* 24 8 */
char alias; /* 32 1 */
/* XXX 7 bytes hole, try to pack */
phpdbg_command_handler_t handler; /* 40 8 */
const phpdbg_command_t * subs; /* 48 8 */
char * args; /* 56 8 */
/* --- cacheline 1 boundary (64 bytes) --- */
const phpdbg_command_t * parent; /* 64 8 */
_Bool flags; /* 72 1 */
/* size: 80, cachelines: 2, members: 10 */
/* sum members: 66, holes: 1, sum holes: 7 */
/* padding: 7 */
/* last cacheline: 16 bytes */
struct lxb_css_syntax_token {
union lxb_css_syntax_token_u types; /* 0 80 */
/* --- cacheline 1 boundary (64 bytes) was 16 bytes ago --- */
lxb_css_syntax_token_type_t type; /* 80 4 */
/* XXX 4 bytes hole, try to pack */
uintptr_t offset; /* 88 8 */
_Bool cloned; /* 96 1 */
/* size: 104, cachelines: 2, members: 4 */
/* sum members: 93, holes: 1, sum holes: 4 */
/* padding: 7 */
/* last cacheline: 40 bytes */
struct _phpdbg_breakopline_t {
int id; /* 0 4 */
uint8_t type; /* 4 1 */
/* XXX 3 bytes hole, try to pack */
zend_ulong hits; /* 8 8 */
_Bool disabled; /* 16 1 */
/* XXX 7 bytes hole, try to pack */
const char * func_name; /* 24 8 */
size_t func_len; /* 32 8 */
const char * class_name; /* 40 8 */
size_t class_len; /* 48 8 */
zend_ulong opline_num; /* 56 8 */
/* --- cacheline 1 boundary (64 bytes) --- */
zend_ulong opline; /* 64 8 */
/* size: 72, cachelines: 2, members: 10 */
/* sum members: 62, holes: 2, sum holes: 10 */
/* last cacheline: 8 bytes */
struct _phpdbg_breakfile_t {
int id; /* 0 4 */
uint8_t type; /* 4 1 */
/* XXX 3 bytes hole, try to pack */
zend_ulong hits; /* 8 8 */
_Bool disabled; /* 16 1 */
/* XXX 7 bytes hole, try to pack */
const char * filename; /* 24 8 */
zend_ulong line; /* 32 8 */
/* size: 40, cachelines: 1, members: 6 */
/* sum members: 30, holes: 2, sum holes: 10 */
/* last cacheline: 40 bytes */
struct _phpdbg_breakline_t {
int id; /* 0 4 */
uint8_t type; /* 4 1 */
/* XXX 3 bytes hole, try to pack */
zend_ulong hits; /* 8 8 */
_Bool disabled; /* 16 1 */
/* XXX 7 bytes hole, try to pack */
const char * name; /* 24 8 */
zend_ulong opline; /* 32 8 */
phpdbg_breakopline_t * base; /* 40 8 */
/* size: 48, cachelines: 1, members: 7 */
/* sum members: 38, holes: 2, sum holes: 10 */
/* last cacheline: 48 bytes */
struct _phpdbg_breakmethod_t {
int id; /* 0 4 */
uint8_t type; /* 4 1 */
/* XXX 3 bytes hole, try to pack */
zend_ulong hits; /* 8 8 */
_Bool disabled; /* 16 1 */
/* XXX 7 bytes hole, try to pack */
const char * class_name; /* 24 8 */
size_t class_len; /* 32 8 */
const char * func_name; /* 40 8 */
size_t func_len; /* 48 8 */
/* size: 56, cachelines: 1, members: 8 */
/* sum members: 46, holes: 2, sum holes: 10 */
/* last cacheline: 56 bytes */
struct _php_netstream_data_t {
php_socket_t socket; /* 0 4 */
char is_blocked; /* 4 1 */
/* XXX 3 bytes hole, try to pack */
struct timeval timeout; /* 8 16 */
char timeout_event; /* 24 1 */
/* XXX 7 bytes hole, try to pack */
size_t ownsize; /* 32 8 */
/* size: 40, cachelines: 1, members: 5 */
/* sum members: 30, holes: 2, sum holes: 10 */
/* last cacheline: 40 bytes */
My PR changes:
struct _phpdbg_breakbase_t {
uint8_t type; /* 0 1 */
_Bool disabled; /* 1 1 */
/* XXX 2 bytes hole, try to pack */
int id; /* 4 4 */
zend_ulong hits; /* 8 8 */
const char * name; /* 16 8 */
/* size: 24, cachelines: 1, members: 5 */
/* sum members: 22, holes: 1, sum holes: 2 */
/* last cacheline: 24 bytes */
struct _phpdbg_breakop_t {
uint8_t type; /* 0 1 */
_Bool disabled; /* 1 1 */
/* XXX 2 bytes hole, try to pack */
int id; /* 4 4 */
zend_ulong hits; /* 8 8 */
const char * name; /* 16 8 */
zend_ulong hash; /* 24 8 */
/* size: 32, cachelines: 1, members: 6 */
/* sum members: 30, holes: 1, sum holes: 2 */
/* last cacheline: 32 bytes */
struct _phpdbg_breakcond_t {
_Bool paramed; /* 0 1 */
uint8_t type; /* 1 1 */
_Bool disabled; /* 2 1 */
/* XXX 1 byte hole, try to pack */
int id; /* 4 4 */
zend_ulong hits; /* 8 8 */
const char * code; /* 16 8 */
size_t code_len; /* 24 8 */
phpdbg_param_t param; /* 32 88 */
/* --- cacheline 1 boundary (64 bytes) was 56 bytes ago --- */
zend_ulong hash; /* 120 8 */
/* --- cacheline 2 boundary (128 bytes) --- */
zend_op_array * ops; /* 128 8 */
/* size: 136, cachelines: 3, members: 10 */
/* sum members: 135, holes: 1, sum holes: 1 */
/* last cacheline: 8 bytes */
struct _phpdbg_breaksymbol_t {
uint8_t type; /* 0 1 */
_Bool disabled; /* 1 1 */
/* XXX 2 bytes hole, try to pack */
int id; /* 4 4 */
zend_ulong hits; /* 8 8 */
const char * symbol; /* 16 8 */
/* size: 24, cachelines: 1, members: 5 */
/* sum members: 22, holes: 1, sum holes: 2 */
/* last cacheline: 24 bytes */
struct _zend_smm_shared_globals {
zend_shared_segment * * shared_segments; /* 0 8 */
int shared_segments_count; /* 8 4 */
_Bool memory_exhausted; /* 12 1 */
/* XXX 3 bytes hole, try to pack */
size_t shared_free; /* 16 8 */
size_t wasted_shared_memory; /* 24 8 */
zend_shared_memory_state shared_memory_state; /* 32 16 */
void * app_shared_globals; /* 48 8 */
void * reserved; /* 56 8 */
/* --- cacheline 1 boundary (64 bytes) --- */
size_t reserved_size; /* 64 8 */
/* size: 72, cachelines: 2, members: 9 */
/* sum members: 69, holes: 1, sum holes: 3 */
/* last cacheline: 8 bytes */
struct _phpdbg_command_t {
const char * name; /* 0 8 */
size_t name_len; /* 8 8 */
const char * tip; /* 16 8 */
size_t tip_len; /* 24 8 */
char alias; /* 32 1 */
_Bool flags; /* 33 1 */
/* XXX 6 bytes hole, try to pack */
phpdbg_command_handler_t handler; /* 40 8 */
const phpdbg_command_t * subs; /* 48 8 */
char * args; /* 56 8 */
/* --- cacheline 1 boundary (64 bytes) --- */
const phpdbg_command_t * parent; /* 64 8 */
/* size: 72, cachelines: 2, members: 10 */
/* sum members: 66, holes: 1, sum holes: 6 */
/* last cacheline: 8 bytes */
struct lxb_css_syntax_token {
union lxb_css_syntax_token_u types; /* 0 80 */
/* --- cacheline 1 boundary (64 bytes) was 16 bytes ago --- */
lxb_css_syntax_token_type_t type; /* 80 4 */
_Bool cloned; /* 84 1 */
/* XXX 3 bytes hole, try to pack */
uintptr_t offset; /* 88 8 */
/* size: 96, cachelines: 2, members: 4 */
/* sum members: 93, holes: 1, sum holes: 3 */
/* last cacheline: 32 bytes */
struct _phpdbg_breakopline_t {
uint8_t type; /* 0 1 */
_Bool disabled; /* 1 1 */
/* XXX 2 bytes hole, try to pack */
int id; /* 4 4 */
zend_ulong hits; /* 8 8 */
const char * func_name; /* 16 8 */
size_t func_len; /* 24 8 */
const char * class_name; /* 32 8 */
size_t class_len; /* 40 8 */
zend_ulong opline_num; /* 48 8 */
zend_ulong opline; /* 56 8 */
/* size: 64, cachelines: 1, members: 10 */
/* sum members: 62, holes: 1, sum holes: 2 */
struct _phpdbg_breakfile_t {
uint8_t type; /* 0 1 */
_Bool disabled; /* 1 1 */
/* XXX 2 bytes hole, try to pack */
int id; /* 4 4 */
zend_ulong hits; /* 8 8 */
const char * filename; /* 16 8 */
zend_ulong line; /* 24 8 */
/* size: 32, cachelines: 1, members: 6 */
/* sum members: 30, holes: 1, sum holes: 2 */
/* last cacheline: 32 bytes */
struct _phpdbg_breakline_t {
uint8_t type; /* 0 1 */
_Bool disabled; /* 1 1 */
/* XXX 2 bytes hole, try to pack */
int id; /* 4 4 */
zend_ulong hits; /* 8 8 */
const char * name; /* 16 8 */
zend_ulong opline; /* 24 8 */
phpdbg_breakopline_t * base; /* 32 8 */
/* size: 40, cachelines: 1, members: 7 */
/* sum members: 38, holes: 1, sum holes: 2 */
/* last cacheline: 40 bytes */
struct _phpdbg_breakmethod_t {
uint8_t type; /* 0 1 */
_Bool disabled; /* 1 1 */
/* XXX 2 bytes hole, try to pack */
int id; /* 4 4 */
zend_ulong hits; /* 8 8 */
const char * class_name; /* 16 8 */
size_t class_len; /* 24 8 */
const char * func_name; /* 32 8 */
size_t func_len; /* 40 8 */
/* size: 48, cachelines: 1, members: 8 */
/* sum members: 46, holes: 1, sum holes: 2 */
/* last cacheline: 48 bytes */
struct _php_netstream_data_t {
php_socket_t socket; /* 0 4 */
char is_blocked; /* 4 1 */
char timeout_event; /* 5 1 */
/* XXX 2 bytes hole, try to pack */
struct timeval timeout; /* 8 16 */
size_t ownsize; /* 24 8 */
/* size: 32, cachelines: 1, members: 5 */
/* sum members: 30, holes: 1, sum holes: 2 */
/* last cacheline: 32 bytes */
Affected structs (decreased sizes):
- _phpdbg_breakbase_t 32 to 24 bytes
- lxb_css_property_float_t 40 to 32 bytes
- _phpdbg_breakop_t 40 to 32 bytes
- zend_hooked_object_iterator 160 to 152 bytes
- _phpdbg_breakcond_t 152 to 136 bytes
- lxb_css_selectors_pseudo_data_func_t 72 to 64 bytes
- _phpdbg_breaksymbol_t 32 to 24 bytes
- _zend_smm_shared_globals 80 to 72 bytes
- lxb_encoding_ctx_2022_jp_t 16 to 12 bytes
- _phpdbg_command_t 80 to 72 bytes
- lxb_css_syntax_token 104 to 96 bytes
- _phpdbg_breakopline_t 72 to 64 bytes
- cdf_directory_t 136 to 128 bytes
- _phpdbg_breakfile_t 40 to 32 bytes
- err_buf 32 to 24 bytes
- phpdbg_lexer_data 48 to 40 bytes
- Table 64 to 56 bytes
- _phpdbg_breakline_t 48 to 40 bytes
- glob_s_t 144 to 136 bytes
- _phpdbg_breakmethod_t 56 to 48 bytes
- _php_netstream_data_t 40 to 32 bytes
Uh oh!
There was an error while loading. Please reload this page.
Hi everyone, thank team so much for development PHP interpreter.
I think this PR will reduce minimum requirements for hardware, and it will decrease costs copying, moving, and creating object-structures only for common 64bit processors due to the 8-byte data alignment.
Smaller size structure or class, higher chance putting into CPU cache. Most processors are already 64 bit, so the change won't make it any worse.
Info about technique:
https://hpc.rz.rptu.de/Tutorials/AVX/alignment.shtml
https://wr.informatik.uni-hamburg.de/_media/teaching/wintersemester_2013_2014/epc-14-haase-svenhendrik-alignmentinc-presentation.pdf
https://en.wikipedia.org/wiki/Data_structure_alignment
https://stackoverflow.com/a/20882083
https://zijishi.xyz/post/optimization-technique/learning-to-use-data-alignment/
Pahole log:
/* XXX {n} bytes hole, try to pack */
shows where optimization is possible by rearranging the order of fields structures and classesMaster branch
My PR changes:
Affected structs (decreased sizes):