Tisztán hatékonyabb

Pfeiffer Szilárd
szenior szoftverfejlesztő
pfeiffer.szilard@balabit.hu

char *tmp1, ...
       ..., *tmp9;
int pid;
// semmitmondó nevek
// félrevezető nevek
int dpt;
int i;
// tömörített nevek
// újrahasznosított nevek

Névválasztás

Drágák a betűk?!

#define max_macro(a,b) ((a)>(b)?(a):(b))

static int max_function(int a, int b)
{
  return a > b ? a : b;
}

static int first(int a, int b)
{
  return max_macro(a, b);
}

static int second(int a, int b)
{
  return max_function(a, b);
}

Makrók


cmp    %edi,%esi
mov    %edi,%eax
cmovge %esi,%eax


cmp    %edi,%esi
mov    %edi,%eax
cmovge %esi,%eax

Makrók

return x*256;
shl    $0x8,%eax          //eax<<=8
retq

Bitmágia

shl    $0x8,%eax          //eax<<=8
add    %edi,%eax          //eax+=edi
retq 
return x*(256+1);
return x*(256+2);
shl    $0x8,%eax          //eax<<=8
lea    (%rax,%rdi,2),%eax //eax+=
retq                      //rdi*2
return x*(256-1);
shl    $0x8,%eax          //eax<<=8
sub    %edi,%eax          //eax-=edx
retq
return x*48;
lea    (%rdi,%rdi,2),%eax //eax*=3
shl    $0x4,%eax          //eax<<=4
retq
int abs(int x)
{
  return (x>0)?x:(-x);
}
mov    %edi,%edx
mov    %edi,%eax
sar    $0x1f,%edx //edx>>=31
                  //kivéve előjel bit
xor    %edx,%eax  //előjel bit törlése
sub    %edx,%eax  //kettes komplemens
retq

Bitmágia

Bitmágia

static int A[0x10000];

void update(int idx,int val)
{
  if(idx>=0 && idx<0x10000)
    A[idx]=val;
}


cmp    $0x0ffff,%edi
ja     0x400502 <update+18>
movslq %edi,%rdi
mov    %esi,0x601060(,%rdi,4)
repz retq //<updae+18>

Feltételek kivétele


mov    $0x40000,%edx
xor    %esi,%esi
mov    $0x601060,%edi
	jmpq   0x400410 //memset
void updatearray()
{
  int i;
  for (i=0;i<0x10000;i++)
    update(i, 0);
}
static int A[0x10000];

void update(int idx,int val)
{
  if(idx>=0 && idx<0x10000)
    A[idx]=val;
}


cmp    $0x0ffff,%edi
ja     0x400502 <update+18>
movslq %edi,%rdi
mov    %esi,0x601060(,%rdi,4)
repz retq //<updae+18>

Feltételek kivétele


mov    $0x40000,%edx
xor    %esi,%esi
mov    $0x601060,%edi
	jmpq   0x400410 //memset
void updatearray()
{
  int i;
  for (i=0;i<0x10000;i++)
    update(i, 0);
}
static int A[0x10000];

void update(int idx,int val)
{
  if(idx>=5 && idx<0x1005)
    A[idx]=val;
}
lea    -0x5(%rdi),%eax
cmp    $0xfff,%eax
ja     0x4005f4 <update+20>
movslq %edi,%rdi
mov    %esi,0x601060(,%rdi,4)
repz retq //<update+20>

Feltételek kivétele

Feltételek kivétele

void memcpy_int()
{
  int i;
  for (i=0;i<0x123456;i++)
    b[i]=a[i];
}
sub    $0x8,%rsp
mov    $0x123456,%edx
mov    $0x7244e0,%esi
mov    $0x601080,%edi
callq  0x4004b0 <memcpy@plt>
add    $0x8,%rsp
retq   

Memória műveletek

push   %rax
mov    $0x601060,%edi
mov    $0x7244c0,%esi
mov    $0x123456,%edx
callq  0x4004a0 <memcpy@plt>
pop    %rax
retq   
void
memcpy_n_char(char dest[],
              char src[],
              int n)
{
  int i;
  for (i=0;i<n;i++)
    dest[i]=src[i];
}
test   %edx,%edx
jle    0x40090c <memcpy_n_char+684>
lea    0x10(%rdi),%rax
cmp    %rax,%rsi
lea    0x10(%rsi),%rax
setae  %cl
cmp    %rax,%rdi
setae  %al
or     %al,%cl
je     0x400910 <memcpy_n_char+688>
cmp    $0x16,%edx
jbe    0x400910 <memcpy_n_char+688>
mov    %rsi,%rax
push   %rbp
push   %rbx
neg    %rax
and    $0xf,%eax
cmp    %edx,%eax
cmova  %edx,%eax
xor    %ecx,%ecx
test   %eax,%eax
je     0x400791 <memcpy_n_char+305>
movzbl (%rsi),%ecx
cmp    $0x1,%eax
mov    %cl,(%rdi)
je     0x400940 <memcpy_n_char+736>
movzbl 0x1(%rsi),%ecx
cmp    $0x2,%eax
mov    %cl,0x1(%rdi)
je     0x400950 <memcpy_n_char+752>
movzbl 0x2(%rsi),%ecx
cmp    $0x3,%eax
mov    %cl,0x2(%rdi)
je     0x400960 <memcpy_n_char+768>
movzbl 0x3(%rsi),%ecx
cmp    $0x4,%eax
mov    %cl,0x3(%rdi)
je     0x400970 <memcpy_n_char+784>
movzbl 0x4(%rsi),%ecx
cmp    $0x5,%eax
mov    %cl,0x4(%rdi)
je     0x400980 <memcpy_n_char+800>
movzbl 0x5(%rsi),%ecx
cmp    $0x6,%eax
mov    %cl,0x5(%rdi)
je     0x400990 <memcpy_n_char+816>
movzbl 0x6(%rsi),%ecx
cmp    $0x7,%eax
mov    %cl,0x6(%rdi)
je     0x4009a0 <memcpy_n_char+832>
movzbl 0x7(%rsi),%ecx
cmp    $0x8,%eax
mov    %cl,0x7(%rdi)
je     0x4009b0 <memcpy_n_char+848>
movzbl 0x8(%rsi),%ecx
cmp    $0x9,%eax
mov    %cl,0x8(%rdi)
je     0x4009c0 <memcpy_n_char+864>
movzbl 0x9(%rsi),%ecx
cmp    $0xa,%eax
mov    %cl,0x9(%rdi)
je     0x4009d0 <memcpy_n_char+880>
movzbl 0xa(%rsi),%ecx
cmp    $0xb,%eax
mov    %cl,0xa(%rdi)
je     0x4009e0 <memcpy_n_char+896>
movzbl 0xb(%rsi),%ecx
cmp    $0xc,%eax
mov    %cl,0xb(%rdi)
je     0x4009f0 <memcpy_n_char+912>
movzbl 0xc(%rsi),%ecx
cmp    $0xd,%eax
mov    %cl,0xc(%rdi)
je     0x400a00 <memcpy_n_char+928>
movzbl 0xd(%rsi),%ecx
cmp    $0xf,%eax
mov    %cl,0xd(%rdi)
jne    0x400930 <memcpy_n_char+720>
movzbl 0xe(%rsi),%ecx
mov    %cl,0xe(%rdi)
mov    $0xf,%ecx
mov    %edx,%r11d
lea    -0x1(%rdx),%r9d
mov    %eax,%r10d
sub    %eax,%r11d
lea    -0x10(%r11),%r8d
sub    %eax,%r9d
shr    $0x4,%r8d
add    $0x1,%r8d
mov    %r8d,%ebx
shl    $0x4,%ebx
cmp    $0xe,%r9d
jbe    0x4007e8 <memcpy_n_char+392>
lea    (%rsi,%r10,1),%rbp
xor    %eax,%eax
add    %rdi,%r10
xor    %r9d,%r9d
movdqa 0x0(%rbp,%rax,1),%xmm0
add    $0x1,%r9d
movups %xmm0,(%r10,%rax,1)
add    $0x10,%rax
cmp    %r8d,%r9d
jb     0x4007c5 <memcpy_n_char+357>
add    %ebx,%ecx
cmp    %ebx,%r11d
je     0x40090a <memcpy_n_char+682>
movslq %ecx,%rax
movzbl (%rsi,%rax,1),%r8d
mov    %r8b,(%rdi,%rax,1)
lea    0x1(%rcx),%eax
cmp    %eax,%edx
jle    0x40090a <memcpy_n_char+682>
cltq   
movzbl (%rsi,%rax,1),%r8d
mov    %r8b,(%rdi,%rax,1)
lea    0x2(%rcx),%eax
cmp    %eax,%edx
jle    0x40090a <memcpy_n_char+682>
cltq   
movzbl (%rsi,%rax,1),%r8d
mov    %r8b,(%rdi,%rax,1)
lea    0x3(%rcx),%eax
cmp    %eax,%edx
jle    0x40090a <memcpy_n_char+682>
cltq   
movzbl (%rsi,%rax,1),%r8d
mov    %r8b,(%rdi,%rax,1)
lea    0x4(%rcx),%eax
cmp    %eax,%edx
jle    0x40090a <memcpy_n_char+682>
cltq   
movzbl (%rsi,%rax,1),%r8d
mov    %r8b,(%rdi,%rax,1)
lea    0x5(%rcx),%eax
cmp    %eax,%edx
jle    0x40090a <memcpy_n_char+682>
cltq   
movzbl (%rsi,%rax,1),%r8d
mov    %r8b,(%rdi,%rax,1)
lea    0x6(%rcx),%eax
cmp    %eax,%edx
jle    0x40090a <memcpy_n_char+682>
cltq   
movzbl (%rsi,%rax,1),%r8d
mov    %r8b,(%rdi,%rax,1)
lea    0x7(%rcx),%eax
cmp    %eax,%edx
jle    0x40090a <memcpy_n_char+682>
cltq   
movzbl (%rsi,%rax,1),%r8d
mov    %r8b,(%rdi,%rax,1)
lea    0x8(%rcx),%eax
cmp    %eax,%edx
jle    0x40090a <memcpy_n_char+682>
cltq   
movzbl (%rsi,%rax,1),%r8d
mov    %r8b,(%rdi,%rax,1)
lea    0x9(%rcx),%eax
cmp    %eax,%edx
jle    0x40090a <memcpy_n_char+682>
cltq   
movzbl (%rsi,%rax,1),%r8d
mov    %r8b,(%rdi,%rax,1)
lea    0xa(%rcx),%eax
cmp    %eax,%edx
jle    0x40090a <memcpy_n_char+682>
cltq   
movzbl (%rsi,%rax,1),%r8d
mov    %r8b,(%rdi,%rax,1)
lea    0xb(%rcx),%eax
cmp    %eax,%edx
jle    0x40090a <memcpy_n_char+682>
cltq   
movzbl (%rsi,%rax,1),%r8d
mov    %r8b,(%rdi,%rax,1)
lea    0xc(%rcx),%eax
cmp    %eax,%edx
jle    0x40090a <memcpy_n_char+682>
cltq   
movzbl (%rsi,%rax,1),%r8d
mov    %r8b,(%rdi,%rax,1)
lea    0xd(%rcx),%eax
cmp    %eax,%edx
jle    0x40090a <memcpy_n_char+682>
cltq   
movzbl (%rsi,%rax,1),%r8d
mov    %r8b,(%rdi,%rax,1)
lea    0xe(%rcx),%eax
cmp    %eax,%edx
jle    0x40090a <memcpy_n_char+682>
cltq   
movzbl (%rsi,%rax,1),%edx
mov    %dl,(%rdi,%rax,1)
pop    %rbx
pop    %rbp
repz retq 
xchg   %ax,%ax
xor    %eax,%eax
nopw   0x0(%rax,%rax,1)
movzbl (%rsi,%rax,1),%ecx
mov    %cl,(%rdi,%rax,1)
add    $0x1,%rax
cmp    %eax,%edx
jg     0x400918 <memcpy_n_char+696>
repz retq 
nopl   0x0(%rax)
mov    $0xe,%ecx
jmpq   0x400791 <memcpy_n_char+305>
nopw   0x0(%rax,%rax,1)
mov    $0x1,%ecx
jmpq   0x400791 <memcpy_n_char+305>
nopw   0x0(%rax,%rax,1)
mov    $0x2,%ecx
jmpq   0x400791 <memcpy_n_char+305>
nopw   0x0(%rax,%rax,1)
mov    $0x3,%ecx
jmpq   0x400791 <memcpy_n_char+305>
nopw   0x0(%rax,%rax,1)
mov    $0x4,%ecx
jmpq   0x400791 <memcpy_n_char+305>
nopw   0x0(%rax,%rax,1)
mov    $0x5,%ecx
jmpq   0x400791 <memcpy_n_char+305>
nopw   0x0(%rax,%rax,1)
mov    $0x6,%ecx
jmpq   0x400791 <memcpy_n_char+305>
nopw   0x0(%rax,%rax,1)
mov    $0x7,%ecx
jmpq   0x400791 <memcpy_n_char+305>
nopw   0x0(%rax,%rax,1)
mov    $0x8,%ecx
jmpq   0x400791 <memcpy_n_char+305>
nopw   0x0(%rax,%rax,1)
mov    $0x9,%ecx
jmpq   0x400791 <memcpy_n_char+305>
nopw   0x0(%rax,%rax,1)
mov    $0xa,%ecx
jmpq   0x400791 <memcpy_n_char+305>
nopw   0x0(%rax,%rax,1)
mov    $0xb,%ecx
jmpq   0x400791 <memcpy_n_char+305>
nopw   0x0(%rax,%rax,1)
mov    $0xc,%ecx
jmpq   0x400791 <memcpy_n_char+305>
nopw   0x0(%rax,%rax,1)
mov    $0xd,%ecx
jmpq   0x400791 <memcpy_n_char+305>

Memória műveletek


void inlined_memcpy_n_char()
{
  memcpy_n_char(b,a,0x12345);
}

xor    %eax,%eax
nopw   0x0(%rax,%rax,1)
movzbl 0x7244c0(%rax),%edx
add    $0x1,%rax
mov    %dl,0x60105f(%rax)
cmp    $0x12345,%rax
jne    0x400688 <inlined_memcpy_n_char+8>
repz retq 

Memória műveletek

int fact(int x)
{
  if (x<=0) return 1;
  return x*fact(x-1);
}
test   %edi,%edi
jle    0x4005fa <fact+26>
mov    $0x1,%eax
nopl   0x0(%rax)
imul   %edi,%eax
sub    $0x1,%edi
jne    0x4005f0 <fact+16>
repz retq 
mov    $0x1,%eax //<fact+16>
retq   

Rekurzió

Rekurzió

Vezérlésfolyam megértése

  • függvény mutatók
  • nagy méretű switch kifejezések
  • ciklusok break kifejezésekkel
  • ciklusok ismeretlen határokkal

 

Adathozzáférés megértése

  • cím szerint átadott változók
  • globális változók
  • függvény paraméterek
  • mutatón keresztüli hozzáférés

Ha nem sikerül

  • csökken az átalakítás hatóköre
  • csökken az átalakítás "erőssége"
  • nő a változatlanul hagyott kód

Köszönöm a figyelmet!

Tisztán hatékonyabb

By Szilárd Pfeiffer

Tisztán hatékonyabb

A Clean Code elvek kapcsán gyakran felmerülő kérdés, hogy az átlátható, ember által olvasható kód írása nem okoz-e hatékonyságcsökkenést futtatáskor. Nos, az eredmény C/C++ kódok esetén meglehetősen érdekes. Számos esetben nemhogy ráfordított időben kifejezett ráfizetés a bitekkel való varázslás, de a hatékonyság oldalán sem nyerünk egy fikarcnyit sem, a feleslegesen túloptimalizált kód karbantartásának nehézségeit már meg sem említem. Az előadás keretében néhány gyakorlati példán keresztül világítok rá arra, hogy a Clean Code nem csak a fejlesztőt, de a fordító programokat is segíti a hatékonyabb kódok előállításában.

  • 950