LINUX.ORG.RU

Ламерский вопрос по структурам и sizeof


0

0

Есть такая вот структура:

struct tagBMPFileHeader
{
short int bfType;
int bfSize;
short int bfReserved1;
short int bfReserved2;
int bfOffBits;
};


Почему sizeof(tagBMPFileHeader) == 16 ?
Если убрать к примеру short int bfType
sizeof становится равен 12.
Это как ?
Выравнивание что ли?
И как от этого избавится, т. к. из файла структуру читает неправильно:
fread(&BMPFileHeader, sizeof(BMPFileHeader), 1, f);
выдаёт информацию со "сдвигом" на 2 байта вправо.

Компилятор gcc 2.96


Ответ на: комментарий от Die-Hard

>Ты действительно веришь, что _упакованная_ структура является _оптимизированной_?

Она такой и является. Тут и спорить не о чем. Посмотри на чем основаны все файловые системы (понятие inode). Опять на чистых структурах (только правильных, как я и говорил раньше). Если иметь голову, _можно_ писать структуры куда угодно. А в случаях когда нужна скорость, это делать _нужно_.

Вы спорите с основами, и впариваете сериализацию, там где она не нужна. Неплохо Sun промыла мозги своей явой... да так промыла, что кодеры боятся опуститься чуть ниже уровня XML. ;-) Хотя может так оно и правильнее... не всем дано головой думать, а несмышленых, действительно, надо отгораживать от потенциалных проблем.

logIN
()
Ответ на: комментарий от logIN

> Она такой и является. Тут и спорить не о чем. 

 Чушь и бред. С какой радости она "оптимизированная"?

 Всё равно, однажды прочитав её в память, тебе, в целях оптимизации 
доступа, ПРИДЁТСЯ разобрать её в выровненную структуру. Так не лучше ли 
это сделать сразу, а?

> А в случаях когда нужна скорость, это делать _нужно_. 

 Лжешь. По причине глупости и безграмотности. Посмотри на сырцы любых 
нормальных СУБД.

> да так промыла, что кодеры боятся опуститься чуть ниже уровня XML. ;-) 

 Да ты идиот, как я погляжу. То, что я тут предлагаю - это как раз 
сильно более низкий уровень, чем тупая запись структуры целиком - я 
предлагаю писать и читать структуры поэлементно, примерно так:

 begin_pack(out_file);
   pack_ui32(s->x);
   pack_ui32(s->y);
   pack_i8(s->n);
 end_pack(out_file);


 Резюме - ты - дурак и быдлокодеришко.

JavaHarlal
()
Ответ на: комментарий от logIN

logIN (18.10.2005 16:43:55):

>>Ты действительно веришь, что _упакованная_ структура является _оптимизированной_?

> Она такой и является. Тут и спорить не о чем.

Извини, но ты говоришь "то, чего нет". Возвращая комплимент ;), споришь с основами.

Доступ к упакованной структуре почти всегда дольше, чем к выровненной.

> Если иметь голову, _можно_ писать структуры куда угодно. А в случаях когда нужна скорость, это делать _нужно_.

Дык, голову-то, действительно, нужно иметь!

Запись/чтение структур допустимо только в одном случае: когда речь идет о конкретном железе и компиляторе. И при этом не упаковывать их, а выравнивать вручную железо/компиляторозависимыми паддингами. Это делают драверо- и ФС- писатели, а также прикладники-пионэры (впрочем, последние наивно предпочитают структуры паковать).

Die-Hard ★★★★★
()
Ответ на: комментарий от JavaHarlal

>в целях оптимизации доступа, ПРИДЁТСЯ разобрать её в выровненную структуру.

Если ты думаешь, что выравнивание служит лишь для того чтобы былокодеры смогли записать структуру файл - ты глубоко заблуждаешься. Отсылаю тебя к gcc manual, на предмет aligned/packed. Как подсказка: выравнивание может позволить оперировать с потоком структур в разы быстрее (за счет выравнивания их для нужной архитектуры). А также подумай почему заголовки в tcp/ip, составляющие огромную часть трафика, выровнены по 32 бита. Теоретик хренов.

>Посмотри на сырцы любых нормальных СУБД.

Написанных на java? Увольте.

>предлагаю писать и читать структуры поэлементно

см. "в целях оптимизации доступа".

logIN
()
Ответ на: комментарий от logIN

> Кстати, уверен, что в базах данных используют структуры напрямую. Объяснение простое: довольно накладно парсить такой вот портируемый формат хранения структур.

А вот фиг. Если ты имел ввиду формат хранения данных, советую вспомнить что SQL типы данных ну никак не мапятся напрямую на сишные. Вот посмотри например на внутреннее представление NUMBER в оракле: http://www.ixora.com.au/notes/number_representation.htm

Cantor ★★
()
Ответ на: комментарий от logIN

logIN (18.10.2005 17:27:42):

>>Доступ к упакованной структуре почти всегда дольше, чем к выровненной

>См. предыдущий ответ.

Мне это напоминает разговор слепого с глухим.

Ты утверждаешь, что скорость доступа к полям упакованной структуры выше, чем скорость доступа к полям выровненной структуры? Да или нет?

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

прочитал еще раз, на что отвечал.

>>Ты действительно веришь, что _упакованная_ структура является _оптимизированной_?

Die-Hard, мои извинения. Выравнивание по минимальному размеру (упакова), конечно же может привести к деградации скорости.

logIN
()
Ответ на: комментарий от Cantor

>Если ты имел ввиду формат хранения данных

Хранение произвольных данных действительно не всегда удобно помещать в структуры, особенно если мы говорим о текстовых полях, или полях произвольной длины. Как представляется число в оракле, еще не говорит о том, что хранятся они неструктурированно. Однако, индексы обязаны быть структурами, там их размерность всегда определена.

logIN
()
Ответ на: комментарий от Die-Hard

>Ты действительно веришь, что _упакованная_ структура является _оптимизированной_

Я не говорил об упаковке сишных "структур". _Внутреннее_ представление очевидно является наиболее производительным. Построение его для больших структур(не C struct, а всяких там графов,деревьев,хешей,пр.) данных _может_ занимать неприемлемо много времени. И "оффлайновое" построение оных с последующим mmap-ом вполне себя оправдывает. Чем-то это похоже на компиляцию программ vs. интерпретация исходников.

>Весь бенефит от чтения структуры mmap'ом вместо поэлементного чтения

Удельная стоимость поэлементного чтения из удаленной базы данных или XML файла _чрезвычайно_ велика. Если я буду это делать в указаных условиях - накладные расходы сделают систему неработоспособной. Проверено:-).

DonkeyHot ★★★★★
()
Ответ на: комментарий от DonkeyHot

DonkeyHot(*) (18.10.2005 18:16:15):

> Я не говорил об упаковке сишных "структур"

Ну. извини, речь-то в топике шла именно о них, родимых!

> Построение его для больших структур(не C struct, а всяких там графов,деревьев,хешей,пр.) данных _может_ занимать неприемлемо много времени. И "оффлайновое" построение оных с последующим mmap-ом вполне себя оправдывает.

Это по определению невозможно: run-time структуры (типа списков на указателях) должны быть оптимизированы под конкретные адреса.

То, что ты описываешь, и есть сериализация -- только не пойму, как сюда mmap прикрутить.

> Удельная стоимость поэлементного чтения из удаленной базы данных или XML файла _чрезвычайно_ велика.

Чур меня!

Это только современные студенты-информатики с кафедр уэбинджиниринга понимают под сериализацией запихивание в XML.

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

>> Я не говорил об упаковке

>Ну. извини, речь-то в топике шла именно о них, родимых!

Но не об упаковке. Тезис звучал "НИКОГДА НЕЛЬЗЯ писать Сишные структуры"(безотносительно к их упакованости). Я спорю о том, что слова "НИКОГДА НЕЛЬЗЯ" следует заменить на "обычно не стоит".

>Это по определению невозможно:

(почёсывая затылок:-) и как это оно работает?

>run-time структуры (типа списков на указателях) должны быть оптимизированы под конкретные адреса

И в чем проблема? Адресного пространства на современных процессорах - хоть leak-ой жуй.

>То, что ты описываешь, и есть сериализация -- только не пойму, как сюда mmap прикрутить.

"Десериализованые" отдельной программой данные сохраняешь в файл, который потом mmap-ить "рабочий" процесс, мгновенно получая готовое к работе эффективное представление.

DonkeyHot ★★★★★
()
Ответ на: комментарий от DonkeyHot

Один момент - оффлайново построять это дело должен ТОЧНО ТАКОЙ ЖЕ бинарник, mmap-я файло по точно тому же адресу.

Пример реализации - почти все Common Lisp-ы.

anonymous
()
Ответ на: комментарий от anonymous

anonymous (*) (18.10.2005 19:01:46):

> Один момент - оффлайново построять это дело должен ТОЧНО ТАКОЙ ЖЕ бинарник, mmap-я файло по точно тому же адресу.

Не, ну, конечно, загрузчик грузит бинарь тоже mmap'ом, и шареные либы так же грузятся.

Конечно, если ты пишешь а-ля виртуальную машину, жестко затачивая ее под определенное железо, то так можно. Можно даже просто где надо смешения подкрутить после mmap'а.

Однако это не повод объявлять спасение в файлы указателей универсальным выходом из положения...

Die-Hard ★★★★★
()
Ответ на: комментарий от anonymous

>Один момент - оффлайново построять это дело должен ТОЧНО ТАКОЙ ЖЕ бинарник

Точнее собраный тем же компилером с теми же опциями и с эквивалентными описаниями типов в исходниках.

DonkeyHot ★★★★★
()
Ответ на: комментарий от Die-Hard

>Однако это не повод объявлять спасение в файлы указателей универсальным выходом из положения.

Я и не говорил про универсальность. Это просто один из _приемлемых_ методов _оптимизации_. Что доказывает ложность утверждения "НИКОГДА НЕЛЬЗЯ" этого делать. Иногда можно:-)

DonkeyHot ★★★★★
()
Ответ на: комментарий от DonkeyHot

DonkeyHot:

>>Ну. извини, речь-то в топике шла именно о них, родимых!

> Но не об упаковке. Тезис звучал "НИКОГДА НЕЛЬЗЯ писать Сишные структуры"(безотносительно к их упакованости). Я спорю о том, что слова "НИКОГДА НЕЛЬЗЯ" следует заменить на "обычно не стоит".

Полностью согласен.

Думаю, наш излишне эмоциональный коллега ;) примерно это и имел в виду: "НИКОГДА НЕЛЬЗЯ" -> "...не понимая, зачем ты это делаешь".

Я влез не совсем по делу, поскольку "держал голове" I/O с использованием упакованных структур.

Die-Hard ★★★★★
()
Ответ на: комментарий от DonkeyHot

DonkeyHot:

> Точнее собраный тем же компилером с теми же опциями и с эквивалентными описаниями типов в исходниках.

Мало этого будет!

Тогда придется еще адреса поднастраивать, и весь бенефит на нет сойдет. Или я опять тебя не понимаю?

Die-Hard ★★★★★
()
Ответ на: комментарий от phrm

2 phm

>struct tagBMPFileHeader >{ >short int bfType:1; >......................... >};

Ne pravil'no. Nekotorye kompil'atory vyrovn'ajut konec struktury.

anonymous
()
Ответ на: комментарий от anonymous

>Так это, как хранить-то правильно? Чтоб переносимо было?

Die-Hard uje skazal - poelementno 4itat'/pisat'

anonymous
()
Ответ на: комментарий от Baraban

Baraban (*) (18.10.2005 21:07:34):

>> Тогда придется еще адреса поднастраивать

> Ну так и man mmap. Можно адрес выбрать...

Тогда это будет, скорее всего, не один большой mmap, а много мелких, и, все равно, не факт, что проканает с ненулевым адресом. И, возможно, придется внутри адресА подкручивать -- предполагалось же _указатели_ в файл запихивать.

Впрочем, все это возможно, только

1. сложно

2. ни разу не I/O

3. выигрыш по сравнению с "ручной" сериализацией не так уж и очевиден.

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

>Тогда придется еще адреса поднастраивать, и весь бенефит на нет сойдет. Или я опять тебя не понимаю

На 64битах можно не сильно беспокоясь выделять произвольный фиксированый адрес, ммапить файл туда во всех программах. Еще нужен специфичный malloc для "нужных" данных, хотя, наверное, можно использовать стандартный, если во внутренности залезть. Тогда адреса просто совпадают.

DonkeyHot ★★★★★
()
Ответ на: комментарий от DonkeyHot

DonkeyHot (18.10.2005 21:23:53):

Да, так можно.

Вместо маллока можно просто анонимный mmap по фиксированному адресу.

Die-Hard ★★★★★
()

Что же, по итогам обсуждения получается одно из двух: или переносимое приложение, но несколько медленное или быстрое, но использующее упакованые структуры и т.п. зависимые от компилятора и платформы способы. Потому что мы или используем содержимое файла в памяти напрямую или распихиваем после считывания, тратя ресурсы на лишнее копирование.

anonymous_incognito ★★★★★
()
Ответ на: комментарий от anonymous_incognito

>или переносимое приложение, но несколько медленное или быстрое, но использующее

На вопрос "вам кофе с сахаром или без" программисты всегда отвечают "да":-).

DonkeyHot ★★★★★
()
Ответ на: комментарий от anonymous_incognito

anonymous_incognito :

> ...или переносимое приложение, но несколько медленное или быстрое, но использующее упакованые структуры...

Ну не совсем согласен!

Именно "по итогам обсуждения" получается, что использование упакованных структур приводит одновременно и к непортабельности, и к тормозам.

Если нужна скорость ценой непортабельности, то мы используем содержимое файла в памяти напрямую, но упакованные структуры тут не при чем.

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

> Именно "по итогам обсуждения" получается, что использование упакованных структур приводит одновременно и к непортабельности, и к тормозам.

> Если нужна скорость ценой непортабельности, то мы используем содержимое файла в памяти напрямую, но упакованные структуры тут не при чем.

Теперь уже я не совсем согласен. :)

Есть задача, озвученная автором темы --- считывать и разбирать сложно структурированый файл, в данном случае BMP.

И обычный read и mmap --- это способ _доступа_ к файлу. В любом случае, его содержимое считывается с диска в оперативную память или явно или задействуя механизм виртуализации. mmap нам даёт адрес отображения файла в виртуальной памяти. Или мы считываем через read явно в некоторую область памяти по какому-то, выделенному в куче (или статически) адресу памяти.

Но что делать с ним дальше? Присвоить его указателю на _упакованую_ структуру? Или если хотим сохранить переносимость, то перекопировать куски в _неупакованую_ структуру. Или по char'у считывать файл (что очень тормозно, но наверное, совместимее всего). Вот диллема, нормального решения которой я не увидел, а обсуждение зачем-то зашло об mmap, который здесь перпендикулярен теме.

anonymous_incognito ★★★★★
()
Ответ на: комментарий от anonymous_incognito

anonymous_incognito (20.10.2005 22:24:34):

> Присвоить его указателю на _упакованую_ структуру? Или если хотим сохранить переносимость, то перекопировать куски в _неупакованую_ структуру.

Что ты будешь делать с _упакованной_ структурой?

Пойми, _каждое_ обращение к упакованной структуре (если она случайно не оказалась выравненной) эквивалентно "перекопировыванию" соответсвующего поля + обращению.

> ...обсуждение зачем-то зашло об mmap, который здесь перпендикулярен теме.

Не совсем.

Есть разница между побитовым дампом/восстановлением куска RAM'а и I/O: в первом случае побитовый образ восстанавливается _в_точности_ в тех же адресах виртуального пространства, а во втором случае нас не интересуют адреса вообще.

В рамках текущей дискуссии достигнут (на данный момент) конценсус, что:

в первом случае стуктуры, ессно, пишуться/читаются как есть, но: а) упаковка тут не при чем; б) нужен mmap;

во втором случае структуры следует каким-то образом сериализовть.

Die-Hard ★★★★★
()
Ответ на: комментарий от omerm

omerm (20.10.2005 22:11:09):

> bole'e togo, nevyrownenoj na razmer cache-line.

Ну, насколько я знаю, выравнивание по кышам идет далеко не у всех компиляторов, и начинается как минимум с опции -O2. Обычно вместо выравнивания по кышам компиляторы просто генерят префетчинг.

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

> Пойми, _каждое_ обращение к упакованной структуре (если она случайно не оказалась выравненной) эквивалентно "перекопировыванию" соответсвующего поля + обращению.

Честно говоря, не знаю что будет происходить на аппаратных платформах, не поддерживающих произвольную адресацию --- исключение при исполнении или компилятор обойдёт его более сложным кодом с "перекопированием", начиная с выровненных границ или просто будет проигнорировано указание строить неупакованую структуру. Ясно только, что ничего хорошего.

Но x86 -ые умеют адресоваться с точностью до 8-ми битного байта, хотя возможно с потерей производительности, если адрес не выровнен на 32 бит(или 16 для 16 бит. режимов, опять же не в курсе с x86-64). Но эта потеря производительности, по-моему, явно меньше, чем если тратить время на "растаскивание" по границам.

Конечно, при проектировании новых форматов и программ, если нет режима жёсткой экономии памяти, то данные разумно распологать, выровненными, но речь ведь зашла об _уже_ имеющемся формате.

> Есть разница между побитовым дампом/восстановлением куска RAM'а и I/O: в первом случае побитовый образ восстанавливается _в_точности_ в тех же адресах виртуального пространства, а во втором случае нас не интересуют адреса вообще.

Опять я не понял. Мы делаем mmap, отображаем файл в память, а кроме того у нас объявлен указатель некоторого структурного типа, который мы инициализируем значением от mmap. После чего работаем с файлом как с областью памяти.

Можно, разумеется, и образы виртуальной памяти хранить и восстанавливать точно по прежним адресам, но мы ведь говорим об обработке имеющегося файла.

То есть, условно говоря (писать настоящую программу сейчас лень)

int fd=open(&filename,flags); ... tagBMPFileHeader bmp*=mmap(0, length, prot, flags, fd, offset);

.....

if (bmp->bfSize<somelength){ .... }

anonymous_incognito ★★★★★
()
Ответ на: комментарий от anonymous_incognito

> Но x86 -ые умеют адресоваться с точностью до 8-ми битного байта, хотя возможно с потерей производительности, если адрес не выровнен на 32 бит

Даже на i386 эта самая потеря производительности будет сопоставима с оверхэдом от "растаскивания" по границам.

И это при _каждом_ обращении! А "растащить" достаточно только один раз...

> но речь ведь зашла об _уже_ имеющемся формате.

Оно -- на диске, Если надо его только прочитать, и ничего с ним не надо делать, тогда, конечно, ты прав. Только тогда можно еще соптимизировать -- _вообще_ не читать :-)

> Мы делаем mmap, отображаем файл в память, а кроме того у нас объявлен указатель некоторого структурного типа, который мы инициализируем значением от mmap. После чего работаем с файлом как с областью памяти.

Если структура упакована, то получаем гемморой, о чем я и заметил (Die-Hard (18.10.2005 16:25:59)).

Если структура одна, но большая, то не совсем понятно, нахрена она нужна. Ведь DonkeyHot повел речь (я не сразу это понял) о неких сложных конструкциях, состоящих из структур-ячеек и связей. Их придется настраивать после mmap'а.

Потом мы договорились до другого варианта -- именно "образы виртуальной памяти хранить и восстанавливать точно по прежним адресам".

Я домой пошел, не знаю, отвечу ли сегодня еще.

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

> Даже на i386 эта самая потеря производительности будет сопоставима с оверхэдом от "растаскивания" по границам.

Надо будет подумать над программкой, которая бы этот эффект наглядно показала.

> Я домой пошел, не знаю, отвечу ли сегодня еще.

Ладно я убедился, что непонимание с чьей-нибудь стороны теперь отсутствует и предмет спора таким образом исчерпан. Ты домой идёшь, а я уже дома и сейчас сразу спать завалюсь :-)

anonymous_incognito ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.