Paul Hsieh в документе "Programming Optimization (http://www.azillionmonkeys.com/qed/optimize.html)" обобщил свой опыт оптимизации производительности приложений на языке Си. Рассмотрены приемы эффективного кодирования, типичные ошибки, необходимость грамотного проектирования.URL: http://www.azillionmonkeys.com/qed/optimize.html
Новость: http://www.opennet.me/opennews/art.shtml?num=8492
Очень бы хотелось на могучем русском языке почитать, уровень английского не позволяет полноценно воспринять информацию. Стыдно, но что поделаешь, говорили мне "учи английски - пригодится", но тогда было не до него. :-[
Тута круче... http://www.agner.org/optimize/
памятка конечно забавная, но читать а тем более применять следует с большой оглядкой. например навскидку:--- cut ---
void
foo1(void)
{
int i;for(i = 0; i < 100; i++) {
map[i].visited = 0;
}
}void
foo2(void)
{
int i = 99;
do {
map[i].visited = 0;
i--;
} while (i >= 0);
}
--- cut ---с точки зрения читабельности кода, первый foo1() смотрится явно естественнее, в то время как на foo2() взгляд спотыкается. с точки зрения полученного кода, все сильно зависит от того, как определена map и есть ли, к примеру, выравнивание.
1. map определена без выравнивания:
struct {
int visited;
char foo;
} map[100];имеем:
$ cc --version
cc (GCC) 3.4.3 20041212 (Red Hat 3.4.3-9.EL4)
$ cc -c -O2 foo.c
$ objdump -d -M intel foo.o | less--- cut ---
foo.o: формат файла elf32-i386Диассемблирование раздела .text:
00000000 <foo1>:
0: 55 push ebp
1: 89 e5 mov ebp,esp
3: 31 c0 xor eax,eax
5: 8d 76 00 lea esi,[esi]
8: c7 04 c5 00 00 00 00 mov DWORD PTR [eax*8],0x0
f: 00 00 00 00
13: 40 inc eax
14: 83 f8 63 cmp eax,0x63
17: 7e ef jle 8 <foo1+0x8>
19: c9 leave
1a: c3 ret
1b: 90 nop0000001c <foo2>:
1c: 55 push ebp
1d: 89 e5 mov ebp,esp
1f: b8 63 00 00 00 mov eax,0x63
24: c7 04 c5 00 00 00 00 mov DWORD PTR [eax*8],0x0
2b: 00 00 00 00
2f: 48 dec eax
30: 79 f2 jns 24 <foo2+0x8>
32: c9 leave
33: c3 ret
--- cut ---foo2() IMHO заметно выигрывает у foo1() so why not.
2. map определена с выравниванием:
struct {
int visited;
char foo;
} __attribute__((__packed__)) map[100];имеем:
$ cc -c -O2 foo.c
$ objdump -d -M intel foo.o | less--- cut ---
foo.o: формат файла elf32-i386Диассемблирование раздела .text:
00000000 <foo1>:
0: 55 push ebp
1: 89 e5 mov ebp,esp
3: ba 00 00 00 00 mov edx,0x0
8: b8 63 00 00 00 mov eax,0x63
d: 8d 76 00 lea esi,[esi]
10: c7 02 00 00 00 00 mov DWORD PTR [edx],0x0
16: 83 c2 05 add edx,0x5
19: 48 dec eax
1a: 79 f4 jns 10 <foo1+0x10>
1c: c9 leave
1d: c3 ret
1e: 89 f6 mov esi,esi00000020 <foo2>:
20: 55 push ebp
21: 89 e5 mov ebp,esp
23: ba 63 00 00 00 mov edx,0x63
28: b8 ef 01 00 00 mov eax,0x1ef
2d: 8d 76 00 lea esi,[esi]
30: c7 00 00 00 00 00 mov DWORD PTR [eax],0x0
36: 83 e8 05 sub eax,0x5
39: 4a dec edx
3a: 79 f4 jns 30 <foo2+0x10>
3c: c9 leave
3d: c3 ret
--- cut ---тут уже что foo1() что foo2() как-то пофигу :) причем что человек, который писал foo() заранее может и не знать о том, как именно определена map а тем более то, как она будет модифицироваться в будущем..
// wbr
Ну почему же, циклы с пост-условием дают очень неплохие результаты на х86, и хз какие компиляторы умеют сами так оптимайзить.
не тестил на гцц, но msvc очень нравится подобная фишка, а писатель явно пользуется студией.