Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
uint32_t nTableSize избыточно. Оно хранит 29 различных значений (5 бит), а рядом есть uint16_t reserved. Можно ещё на 4 байта сократить. :)reserved это неиспользуемое поле, просто overhead.reserve это не поле union-а, а поле структуры. Оно не используется — в него не пишутся данные и не читаются, и служит оно не для туфты, что Fesor написал, а чтобы верно адресовать 8-битные поля той же структуры на LE и BE машинах.Поле reserve это не поле union-а, а поле структуры.А ничего, что это поле другой структуры? Которая, в свою очередь, расположена в unionе?flags до 16 бит и/или перенести в него nTableSize — то так и пишите. Я не знаю — используют ли разработчики больше 16 бит в поле flags или нет, но если не используют, то, действительно, можно откуcить пару байт от поля flags пару байт и перенести из в nTableSize. Но использовать reserve вместо nTableSize, увы, нельзя — о чём вам Fesor и написал. И он совершенно прав.reserved (или похожим образом) обозначают неиспользуемое, «зарезервированное» для будущего использования пространство в памяти. Это позволяет расширять контракт (протокол, ABI, что угодно) не ломая обратной совместимости. Также эти поля иногда зовутся «паддингами» (padding) и служат для установления размера структуры, к которой они принадлежат, или смещения следующего за ними поля.uint16_t reserve занимает два байта и «двигает» два следующих за ним поля на эти два байта. Таким образом в наименее значащих байтах структуры, при представлении структуры в виде машинного 32-битного значения, оказывается одно и то же поле, вне зависимости от порядка байтов в машинном слове.flags намекают на использовании этого отрезка памяти в виде флагов, а битовые операции с ними тоже быстрее работают с 32-битными значениями.uint32_t flags, занимающее то же адресное пространство, что и структура с полем reserve. Наименее значащий байт этого поля занимает 8-битное поле flags. Поэтому битовые операции в пределах 8 бит над обоими полями flags будут полностью эквивалентны, и не будут модифицировать какие-либо биты в пределах наименее значащих восьми. (почему)reserve для хранения каких-то данных. Ранее это уже было сделано, так появилось поле nApplyCount.Вы, похоже, никогда не писали на Си.А вы, похоже, писали, но не так чтобы много.
Таким образом появляется поле uint32_t flags, занимающее то же адресное пространство, что и структура с полем reserveчто, я извиняюсь, ниоткуда не следует. Кто вам сказал, что uint32_t flags — это оптимизация и ничего больше? Кто вам сказал, что никаких других флагов, кроме тех, которые есть в 8-битном поле flags в природе не бывает? Почему не может быть так, что при некоторых условиях (скажем в зависимости от значение поля nTableSize, LOL) у вас не могут появится там дополнительные флаги? Я ничего не знаю про PHP, но в GCC, с которым я за последние лет 10 успел пообщаться изрядно так бывает сплошь и рядом: в одной ветке у вас будут использоваться uint8_t flags и nApplyCount (и там, в этой ветке, поле reserved таки будет именно reserved), а в другой ветке — у вас будет 30 флагов поле uint32_t flags и никакого nApplyCount. И как вы тут будете избавляться от nTableSize в «большой» структуре?nTableSize нельзя, уж извините. Для этого нужно не только точно знать что там происходит в коде сейчас, но и иметь какую-то информацию о том, что там планируется делать в будущем. Как вы смогли залезть в голову к разработчикам PHP чтобы узнать об их планах — для меня, извините, загадка. Тем более странны удивляет ваша реакция на указание на вашу ошибку: вместо того, чтобы сказать что-нибудь типа «я знаю человека, который этот код разрабатывал и он мне сказал, что uint32_t flags — это оптимизация и ничего больше» (после чего весь ваш гонор имел бы смысл) вы поёте какие-то странные песни про названия полей и прочую муру.Они бы поставили какой-то комментарий, если бы были такие уловки, как вы описали.С каких это пор стандартное использование union'ов требует отдельных комментариев? Это не уловки, это стандартный способ использования union'ов. Собственно единственно возможный в соответствии со стандартом.
flags, вообще говоря, не работают (вернее работают на GCC в некоторых случаях, но может не работать на других компиляторах). Дело в том, что компилятор имеет право считать, что изменение 8-битового поля flags никак не влияет на 32-битовое поле flags. И наоборот. Несколько лет назад на Хабре была статья, где всё это осуждалось. А вне Хабра это обсуждалось ещё раньше.А я перед своим первым сообщением проверил исходный код.Вот с этого и нужно было начинать. С того, что вы проверили код, обнаружили, что в нём используется непереносимое расширение GCC (о чём, разумеется, разработчики даже не удосужились написать в комментариях к типу, что вряд ли делает им честь) и что исходя из вот всего этого можно перенести
nTableMask.unionы используются так, как они должны использоваться… не стоит.С каких это пор стандартное использование union'ов требует отдельных комментариев? Это не уловки, это стандартный способ использования union'ов. Собственно единственно возможный в соответствии со стандартом.Вы как-то поздно начали стандартом махать. Надо было здесь начать: с каких это пор стандартное использование функций языка Си требует отдельных комментариев?
Разумеется, ничего подобного разработчики php не делают.Ась? А это тогда что?
Поэтому битовые операции в пределах 8 бит над обоими полями flags будут полностью эквивалентны, и не будут модифицировать какие-либо биты в пределах наименее значащих восьми. (почему)flags существует для оптимизаций и используется вперемешку с 8-битным или нет. И если нет — тогда зачем он вообще нужен и зачем нужен обсуждаемый union?поскольку для корректной работы по стандарту достаточно либо не брать указатели на непосредственно его поляНедостаточно. Это — как раз и есть расширение GCC. По стандарту — если вы пишете
uint8_t, то и читать должны uint8_t, если пишете uint32_t, то и читать должны uint32_t.uint8_t и прочитав uint32_t вы обязательно получите-таки какое-то значение и винчестер вам никто не отформатирует, но вот беда: оно может не иметь никакого отношения к тому, что в union было записано.Поле uint32_t nTableSize избыточно. Оно хранит 29 различных значений (5 бит), а рядом есть uint16_t reserved.
(8 << packedSize) - 1 достаточно лёгкая, а сдвиг придётся делать в любом случае.В остальном khim уже описал другие мои недопонимания в силу слишком малого опыта работы с Си.Это не малый опыт работы с Си. Это малый опыт работы с разработчиками PHP. Потому что когда вы стреляете себе между яйцами из гранатомёта, то правила хорошего тона говорят, что этот момент стоит обговорить хотя бы в комментариях, а не предполагать, что «все так делают».
int_fast32_t вместо int32_t), то можете легко свалиться в undefined behavior и потом долго ловить ошибки.$startMemory = memory_get_usage();
$array[] = range(1, 100000);
echo memory_get_usage() - $startMemory, " bytes\n";
P.S. И таки да — Юникод. Говорим про 7-ку, даже не про 6-ку. Какой там год на дворе к ее выходу будет?..
совершенно внутренняя вещь, такая, как конкретная реализация работы с hashtable
static HashTable *sort(HashTable *ht)
{
HashTable *result;
zval *value;
php_printf("size hashtable: %d used %d ", ht->nTableSize, ht->nNumUsed);
php_printf("count: %d ", ht->nNumOfElements);
....
}
php > ms_sort([]);
size hashtable: 8 used 0 count: 0
php > ms_sort([0]);
size hashtable: 8 used 1 count: 1 item: 0.000000
php > ms_sort([0,1]);
size hashtable: 8 used 2 count: 2 item: 0.000000 item: 1.000000
php > ms_sort([0,1,2]);
size hashtable: 8 used 3 count: 3 item: 0.000000 item: 1.000000 item: 2.000000
php > ms_sort([0,1,2,3]);
size hashtable: 8 used 4 count: 4 item: 0.000000 item: 1.000000 item: 2.000000 item: 3.000000
php > ms_sort([0,1,2,3,4]);
size hashtable: 8 used 5 count: 5 item: 0.000000 item: 1.000000 item: 2.000000 item: 3.000000 item: 4.000000
php > ms_sort([0,1,2,3,4,5]);
size hashtable: 8 used 6 count: 6 item: 0.000000 item: 1.000000 item: 2.000000 item: 3.000000 item: 4.000000 item: 5.000000
php > ms_sort([0,1,2,3,4,5,6]);
size hashtable: 8 used 7 count: 7 item: 0.000000 item: 1.000000 item: 2.000000 item: 3.000000 item: 4.000000 item: 5.000000 item: 6.000000
php > ms_sort([0,1,2,3,4,5,6,7]);
size hashtable: 8 used 8 count: 8 item: 0.000000 item: 1.000000 item: 2.000000 item: 3.000000 item: 4.000000 item: 5.000000 item: 6.000000 item: 7.000000
php > ms_sort([0,1,2,3,4,5,6,7,8]);
size hashtable: 16 used 9 count: 9 item: 0.000000 item: 1.000000 item: 2.000000 item: 3.000000 item: 4.000000 item: 5.000000 item: 6.000000 item: 7.000000 item: 8.000000
PHP 7 получит в два раза более эффективный Hashtable