У меня вопрос больше академического характера Просьба отнестись к этому вопросу адекватно.
Скажем, мне надо производить какие-то действия и при этом данные, сопровождающие эти действия, хранятся в некоторой структуре и активно ими используются. При этом вряд ли будет создаваться больше одной переменной типа этой структуры.
у меня два варианта возможного дизайна. В первом я объявляю статическую перемнную типа структуры и при где-нибудь её инициализирую, а потом где-нибудь удаляю. При этом все функции пользуются только этой переменной.
Первый:
....
typedef struct {
...
...
} my_type_t;
static my_type_t my_var;
int create_my_var();
int release_my_var();
int do_something1();
int do_something2();
....
Во втором варианте я предоставляю пользователю завести переменную типа структуры и потом каждая функция получает её как параметер.
Второй:
....
typedef struct {
...
...
} my_type_t;
int create_my_var(my_type_t*);
int release_my_var(my_type_t*);
int do_something1(const my_type_t*);
int do_something2(const my_type_t*);
....
Вопрос: Есть ли какое-то преимущество одного из методов с точки зрения быстродействия?
Во втором варианте вроде бы более или менее понятно. При вызове функции адрес структуры помещается в регистер, вызывается цалл и функция берёт адрес из регистра.
Что происходит в первом варианте?
Здравствуйте, ra88, Вы писали:
R>Что происходит в первом варианте?
Адреса полей являются литералами в коде.
В общем случае подход со статической переменной быстрее. Особенно если ты будешь свою структуру инициализировать агрегатом, так как тогда у компилятора будут шансы догадаться до значений и по адресам вообще не лазить...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
извиняюсь. как всегда забыл указать важное. Использую gcc 4.3.2 (без плюсов).
R>>Что происходит в первом варианте? E>Адреса полей являются литералами в коде.
Я могу путаться в терминологии, немного не понятно, что ты имеешь ввиду? Под полями в данном случае ты понимаешь поля структуры? Или что-то иное? Вопрос был, куда и с какой скоростью функции обращаются за глобальной статической переменоой? Есть что-нибудь вроде таблицы глобальных переменных? Если есть, то где она и как быстро до неё добраться?
E>В общем случае подход со статической переменной быстрее. Особенно если ты будешь свою структуру инициализировать агрегатом, так как тогда у компилятора будут шансы догадаться до значений и по адресам вообще не лазить...
Здравствуйте, ra88, Вы писали: R>Вопрос: Есть ли какое-то преимущество одного из методов с точки зрения быстродействия?
Я бы не делал далекоидущих предположений. Думаю, мало у кого есть четкое понимание того, что происходит у оптимизатора при уровне, стремящемся к O3.
Хотя первый метод и кажется навскидку быстрее, я бы
1)Предположил, что оверхед от второго варианта будет весьма невелик.
2)Прогнал бы какие-нибудь синтетические тесты, если производительность реально настолько важна.
Здравствуйте, Mr.Cat, Вы писали: MC>при уровне, стремящемся к O3.
кстати, задумался тут. Почему уровни оптимизации у того же GCC маркируются натуральными числами? Почему между -O2 и -O3 нет, например, -Oe, а до -O2 нет -Osqrt2?
Для начала не кисло бы описать
1) Язык (С или С++)
2) Компилятор
3) Платформу
Я отвечаю в предположении: С++, MSVC, OS Windows XP
R>Я могу путаться в терминологии, немного не понятно, что ты имеешь ввиду? Под полями в данном случае ты понимаешь поля структуры? Или что-то иное? Вопрос был, куда и с какой скоростью функции обращаются за глобальной статической переменоой? Есть что-нибудь вроде таблицы глобальных переменных? Если есть, то где она и как быстро до неё добраться?
Да, поля структуры. Эта структура будет расположена в памяти по фиксированному адресу. При этом, она может даже не инициализироваться, а просто грузиться из экзешника.
Соответсвенно код, обращающийся кданным в такой структуре будет знать адреса данных непосредственно, и сможет обращаться непосредственно по ним. То есть инструкции будут содержать адреса данных непосредственно в себе
E>>В общем случае подход со статической переменной быстрее. Особенно если ты будешь свою структуру инициализировать агрегатом, так как тогда у компилятора будут шансы догадаться до значений и по адресам вообще не лазить...
Что такое агрегат -- знаешь? Это конструкция типа
const static struct MyData {
int Field1;
int Field2;
int Field3;
} = {
1, 2, 4 // это вот и есть агрегат
};
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, ra88, Вы писали:
R>Вопрос: Есть ли какое-то преимущество одного из методов с точки зрения быстродействия?
Неправильно поставлен вопрос. О быстродействии на этом этапе заботиться еще рано. Вопрос должен звучать так: как организовать код чтобы сделать его максимально простым, понятным и легко сопровождаемым.
Я бы предложил тебе сделать my_type классом, а do_something1/do_something2 — методами класса. Тогда тебе, во-первых, не прийдется оперировать глобальными объектами, и, во-вторых, твой код будет чище и понятнее, чем, когда ты просто структуру пихаешь в параметры функций.
Здравствуйте, alexeiz, Вы писали:
A>Я бы предложил тебе сделать my_type классом, а do_something1/do_something2 — методами класса. Тогда тебе, во-первых, не прийдется оперировать глобальными объектами, и, во-вторых, твой код будет чище и понятнее, чем, когда ты просто структуру пихаешь в параметры функций.
А ты уверен, что это плюсы?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, ra88, Вы писали:
R>... R>Вопрос: Есть ли какое-то преимущество одного из методов с точки зрения быстродействия? R>Во втором варианте вроде бы более или менее понятно. При вызове функции адрес структуры помещается в регистер, вызывается цалл и функция берёт адрес из регистра. R>Что происходит в первом варианте?
Вы совершаете типичную для начинающего программиста ошибку: все свое внимание сосредотачиваете на быстродействии, забывая о гораздо более важных аспектах программирования, таких как, надежность программ, простота и понятность кода, расширяемость, сопровождаемость, тестопригодность и т.д. Те моменты, которым Вы сейчас уделяете столько внимания, вероятнее всего никогда не будут узким горлышком Вашей программы. Мой Вам совет: начните с чтения книжек, Вы очень быстро поймете, что гораздо проще правильную программу сделать быстрой, чем быструю правильной.
--
Справедливость выше закона. А человечность выше справедливости.
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, ra88, Вы писали:
E>Для начала не кисло бы описать E>1) Язык (С или С++) E>2) Компилятор E>3) Платформу
извиняюсь ещё раз. первое и второе указал вроде бы в ответе, третье думал следует из контекста, но на всякий случай ещё раз:
1) С
2) gcc-4.3.2
3) linux
E>Да, поля структуры. Эта структура будет расположена в памяти по фиксированному адресу. При этом, она может даже не инициализироваться, а просто грузиться из экзешника. E>Соответсвенно код, обращающийся кданным в такой структуре будет знать адреса данных непосредственно, и сможет обращаться непосредственно по ним. То есть инструкции будут содержать адреса данных непосредственно в себе E>Что такое агрегат -- знаешь? Это конструкция типа
const static struct MyData {
E> int Field1;
E> int Field2;
E> int Field3;
E>} = {
E> 1, 2, 4 // это вот и есть агрегат
E>};
спасибо, действительно не знал такого слова. К сожалению, в моём случае структура выглядит несколько сложнее и неконстантная, т.е. она может принимать различные состояния.
Тем не менее многое прояснилось. Думаю, что справедливо полагать, что первый вариант должен быть быстрее. GCC переводит статическую структуру в данном случае в заклинание типа
98 .local my_var
99 .comm my_var,16,16
что на сколько я понимаю означает, что резервируется память в (в данном случае) в 16 байт с соответствующиим выравниванием и закрепляется за my_var, который потом и используется в коде.
Здравствуйте, Mr.Cat, Вы писали:
MC>Здравствуйте, ra88, Вы писали: R>>Вопрос: Есть ли какое-то преимущество одного из методов с точки зрения быстродействия?
MC>Я бы не делал далекоидущих предположений. Думаю, мало у кого есть четкое понимание того, что происходит у оптимизатора при уровне, стремящемся к O3.
MC>Хотя первый метод и кажется навскидку быстрее, я бы MC>1)Предположил, что оверхед от второго варианта будет весьма невелик. MC>2)Прогнал бы какие-нибудь синтетические тесты, если производительность реально настолько важна.
согласен про оптимизатор. и с остальным тоже. просто было интересно с академической точки зрения.
A>Неправильно поставлен вопрос. О быстродействии на этом этапе заботиться еще рано. Вопрос должен звучать так: как организовать код чтобы сделать его максимально простым, понятным и легко сопровождаемым.
это уже другой вопрос. меня в данном случае интересовал именно первый (опять же больше теоретически)
A>Я бы предложил тебе сделать my_type классом, а do_something1/do_something2 — методами класса. Тогда тебе, во-первых, не прийдется оперировать глобальными объектами, и, во-вторых, твой код будет чище и понятнее, чем, когда ты просто структуру пихаешь в параметры функций.
R>Вы совершаете типичную для начинающего программиста ошибку: все свое внимание сосредотачиваете на быстродействии, забывая о гораздо более важных аспектах программирования, таких как, надежность программ, простота и понятность кода, расширяемость, сопровождаемость, тестопригодность и т.д. Те моменты, которым Вы сейчас уделяете столько внимания, вероятнее всего никогда не будут узким горлышком Вашей программы. Мой Вам совет: начните с чтения книжек, Вы очень быстро поймете, что гораздо проще правильную программу сделать быстрой, чем быструю правильной.
R>
спасибо за совет. Но интересовал вопрос именно в той постановке, которую я использовал. Думаю, что теперь разобрался.
Здравствуйте, ra88, Вы писали:
R>извиняюсь ещё раз. первое и второе указал вроде бы в ответе, третье думал следует из контекста, но на всякий случай
Прошу прощения, не понял надпись в скобочках
ещё раз: R>1) С R>2) gcc-4.3.2 R>3) linux
Спасибо. Теперь стало понятнее.
R>спасибо, действительно не знал такого слова. К сожалению, в моём случае структура выглядит несколько сложнее и неконстантная, т.е. она может принимать различные состояния.
Ну всё равно структуры часто можно агрегатами инициализировать. Правда в C, кажется, только константными выражениями...
R>Тем не менее многое прояснилось. Думаю, что справедливо полагать, что первый вариант должен быть быстрее. GCC переводит статическую структуру в данном случае в заклинание типа R>
R> 98 .local my_var
R> 99 .comm my_var,16,16
R>
R>что на сколько я понимаю означает, что резервируется память в (в данном случае) в 16 байт с соответствующиим выравниванием и закрепляется за my_var, который потом и используется в коде.
Ну да. Кроме того, обычно доступ к полю, это не только получение откуда-то указателя на структуру, но и добавление к нему смещения поля. А в случае статической структуры компилятор может сразу, во время компиляции и линковки найти нужный адрес, типа my_var + my_field_offset, и использовать в инструкциях непосредственно его...
Правда тут есть одна тонкость. Такого рода адреса при загрузке приложения в память имеют свойство перенастраиваться загрузчиком задачи, если "родные" адреса загрузки уже в адресном пространстве заняты. Я не знаю как эти дела делаются в линуксе, но знаю, как в винде. Соответственно код может быть как-то модифицирован компилятором так, чтобы уменьшить число страниц памяти, подвергающихся модификации при загрузке.
Так что точный ответ про быстродействие на самом деле может дать только тест...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
ra88 пишет:
> Вопрос: Есть ли какое-то преимущество одного из методов с точки зрения > быстродействия?
Очень маленькое у варианта с глобальными переменными.
Параметр не пихается в стек. Это конечно если он на данной платформе есть.
> Во втором варианте вроде бы более или менее понятно. При вызове функции > адрес структуры помещается в регистер,
в стек чаще всего.
вызывается цалл и функция берёт > адрес из регистра.
> Что происходит в первом варианте?
в функцию просто в код прошивается константное значение — адрес этой вашей
глобальной переменной.
на практике лучше вариант с параметром. Так обеспечивается большая
гибкость кода — если завтра переменных будет несколько, эта ваша
функция этого не заметит.
Erop пишет:
> А ты уверен, что это плюсы?
А что, есть разница ?
Posted via RSDN NNTP Server 2.1 beta
Re[3]: глобальные переменные
От:
Аноним
Дата:
23.01.09 19:46
Оценка:
Здравствуйте, ra88, Вы писали:
R>согласен про оптимизатор. и с остальным тоже. просто было интересно с академической точки зрения.
На академию этот вопрос вообще не тянет.
Разница если и есть, то ею можно пренебречь и больше
позаботиться об удобстве использования и последующиего сопровождения.
Здравствуйте, MasterZiv, Вы писали:
MZ>А что, есть разница ?
А что, в С есть классы?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
А>На академию этот вопрос вообще не тянет. А>Разница если и есть, то ею можно пренебречь и больше А>позаботиться об удобстве использования и последующиего сопровождения.
всегда удивляют люди, которые на конкретный вопрос пытаются впарить своё мнение на все жизненные темы сразу.