ゆとりーなの日記

日記的な事を書いて行くと思はれる

代入した方が早し

C言語でとある構󠄁造󠄁體のswapを實裝すると云ふ話に某所󠄁でなつたのですが、

// とある構造體
struct hoge {
  int a;
  int b;
  char c[32]; // 文字列を想定
};

この構󠄁造󠄁體をコピーする際に普通󠄁に=を使󠄁ふかメンバを總て明示的にコピーするかでどちらが良いかとなつた訣です。ものぐさゆとり系男子の私は=で普通󠄁に良いと思つてゐたのですが、cが文󠄁字列なのでNULL終󠄁端以降󠄁もコピーするからメンバを總てコピーした方が良いと云ふ派󠄂がゐたのでどちらが良いかをテキトーに計測してみました。
まずゆとり派󠄂です。面倒なのでインライン展開は阻止してをります。

__attribute__((noinline)) void swap(struct hoge *l, struct hoge *r) {
  struct hoge tmp = *l;
  *l = *r;
  *r = tmp;
}

このswapをこれ

int main(void) {
  struct hoge a = {211, 313, "yutorina"};
  struct hoge b = {103, 311, "nagoya"};
  int i;
  for (i = 0; i < 100000000; ++i) {
    swap(&a, &b);
  }
  return 0;
}

にかけてtimeします。最適󠄁化󠄁オプションは-O3です。
結果は

real	0m0.604s
user	0m0.604s
sys	0m0.000s

real	0m0.616s
user	0m0.616s
sys	0m0.000s

real	0m0.597s
user	0m0.597s
sys	0m0.000s

real	0m0.695s
user	0m0.695s
sys	0m0.000s

real	0m0.606s
user	0m0.606s
sys	0m0.000s

こんなもんでした。
續いて全󠄁コピー版です。strcpyを使󠄁ふ事でコピー囘數を減らしたのがウリです。

__attribute__((noinline)) void swap(struct hoge *l, struct hoge *r) {
  struct hoge tmp;
  tmp.a = l->a;
  tmp.b = l->b;
  strcpy(tmp.c, l->c);
  l->a = r->a;
  l->b = r->b;
  strcpy(l->c, r->c);
  r->a = tmp.a;
  r->b = tmp.b;
  strcpy(r->c, tmp.c);
}

ゆとり版と同樣な事をした結果です。

real	0m2.020s
user	0m2.020s
sys	0m0.000s

real	0m2.613s
user	0m2.611s
sys	0m0.000s

real	0m1.957s
user	0m1.957s
sys	0m0.000s

real	0m2.373s
user	0m2.373s
sys	0m0.000s

real	0m2.797s
user	0m2.797s
sys	0m0.000s

結構󠄁差が出ました。殘念乍らゆとりの完勝󠄁の樣です。自分でコピーするよりはコンパイラに任せた方が良いと云ふ、まあ文󠄁字列が32程󠄁度なのも影響󠄃してるとは思ひますが。
折角なのでアセンブリ
ゆとり版

0000000000400620 <swap>:
  400620:	48 83 ec 38          	sub    $0x38,%rsp
  400624:	4c 8b 16             	mov    (%rsi),%r10
  400627:	4c 8b 0f             	mov    (%rdi),%r9
  40062a:	4c 8b 47 08          	mov    0x8(%rdi),%r8
  40062e:	48 8b 4f 10          	mov    0x10(%rdi),%rcx
  400632:	48 8b 57 18          	mov    0x18(%rdi),%rdx
  400636:	4c 89 17             	mov    %r10,(%rdi)
  400639:	4c 8b 56 08          	mov    0x8(%rsi),%r10
  40063d:	64 48 8b 04 25 28 00 	mov    %fs:0x28,%rax
  400644:	00 00 
  400646:	48 89 44 24 28       	mov    %rax,0x28(%rsp)
  40064b:	31 c0                	xor    %eax,%eax
  40064d:	48 8b 47 20          	mov    0x20(%rdi),%rax
  400651:	4c 89 0c 24          	mov    %r9,(%rsp)
  400655:	4c 89 57 08          	mov    %r10,0x8(%rdi)
  400659:	4c 8b 56 10          	mov    0x10(%rsi),%r10
  40065d:	4c 89 44 24 08       	mov    %r8,0x8(%rsp)
  400662:	48 89 4c 24 10       	mov    %rcx,0x10(%rsp)
  400667:	48 89 44 24 20       	mov    %rax,0x20(%rsp)
  40066c:	48 89 54 24 18       	mov    %rdx,0x18(%rsp)
  400671:	4c 89 57 10          	mov    %r10,0x10(%rdi)
  400675:	4c 8b 56 18          	mov    0x18(%rsi),%r10
  400679:	4c 89 57 18          	mov    %r10,0x18(%rdi)
  40067d:	4c 8b 56 20          	mov    0x20(%rsi),%r10
  400681:	4c 89 57 20          	mov    %r10,0x20(%rdi)
  400685:	48 89 46 20          	mov    %rax,0x20(%rsi)
  400689:	48 8b 44 24 28       	mov    0x28(%rsp),%rax
  40068e:	64 48 33 04 25 28 00 	xor    %fs:0x28,%rax
  400695:	00 00 
  400697:	4c 89 0e             	mov    %r9,(%rsi)
  40069a:	4c 89 46 08          	mov    %r8,0x8(%rsi)
  40069e:	48 89 4e 10          	mov    %rcx,0x10(%rsi)
  4006a2:	48 89 56 18          	mov    %rdx,0x18(%rsi)
  4006a6:	75 05                	jne    4006ad <swap+0x8d>
  4006a8:	48 83 c4 38          	add    $0x38,%rsp
  4006ac:	c3                   	retq   
  4006ad:	e8 8e fd ff ff       	callq  400440 <__stack_chk_fail@plt>
  4006b2:	66 2e 0f 1f 84 00 00 	nopw   %cs:0x0(%rax,%rax,1)
  4006b9:	00 00 00 
  4006bc:	0f 1f 40 00          	nopl   0x0(%rax)

脫ゆとり版

0000000000400730 <swap>:
  400730:	41 57                	push   %r15
  400732:	ba 20 00 00 00       	mov    $0x20,%edx
  400737:	41 56                	push   %r14
  400739:	41 55                	push   %r13
  40073b:	4c 8d 6f 08          	lea    0x8(%rdi),%r13
  40073f:	41 54                	push   %r12
  400741:	55                   	push   %rbp
  400742:	48 89 fd             	mov    %rdi,%rbp
  400745:	53                   	push   %rbx
  400746:	48 89 f3             	mov    %rsi,%rbx
  400749:	4c 89 ee             	mov    %r13,%rsi
  40074c:	48 83 ec 48          	sub    $0x48,%rsp
  400750:	44 8b 37             	mov    (%rdi),%r14d
  400753:	44 8b 7f 04          	mov    0x4(%rdi),%r15d
  400757:	4c 8d 64 24 18       	lea    0x18(%rsp),%r12
  40075c:	64 48 8b 04 25 28 00 	mov    %fs:0x28,%rax
  400763:	00 00 
  400765:	48 89 44 24 38       	mov    %rax,0x38(%rsp)
  40076a:	31 c0                	xor    %eax,%eax
  40076c:	4c 89 e7             	mov    %r12,%rdi
  40076f:	e8 fc fd ff ff       	callq  400570 <__stpcpy_chk@plt>
  400774:	48 89 44 24 08       	mov    %rax,0x8(%rsp)
  400779:	8b 03                	mov    (%rbx),%eax
  40077b:	4c 89 ef             	mov    %r13,%rdi
  40077e:	89 45 00             	mov    %eax,0x0(%rbp)
  400781:	8b 43 04             	mov    0x4(%rbx),%eax
  400784:	89 45 04             	mov    %eax,0x4(%rbp)
  400787:	48 8d 6b 08          	lea    0x8(%rbx),%rbp
  40078b:	48 89 ee             	mov    %rbp,%rsi
  40078e:	e8 8d fd ff ff       	callq  400520 <strcpy@plt>
  400793:	44 89 33             	mov    %r14d,(%rbx)
  400796:	4c 8b 74 24 08       	mov    0x8(%rsp),%r14
  40079b:	4c 89 e6             	mov    %r12,%rsi
  40079e:	44 89 7b 04          	mov    %r15d,0x4(%rbx)
  4007a2:	48 89 ef             	mov    %rbp,%rdi
  4007a5:	4d 29 e6             	sub    %r12,%r14
  4007a8:	49 8d 56 01          	lea    0x1(%r14),%rdx
  4007ac:	e8 af fd ff ff       	callq  400560 <memcpy@plt>
  4007b1:	48 8b 44 24 38       	mov    0x38(%rsp),%rax
  4007b6:	64 48 33 04 25 28 00 	xor    %fs:0x28,%rax
  4007bd:	00 00 
  4007bf:	75 0f                	jne    4007d0 <swap+0xa0>
  4007c1:	48 83 c4 48          	add    $0x48,%rsp
  4007c5:	5b                   	pop    %rbx
  4007c6:	5d                   	pop    %rbp
  4007c7:	41 5c                	pop    %r12
  4007c9:	41 5d                	pop    %r13
  4007cb:	41 5e                	pop    %r14
  4007cd:	41 5f                	pop    %r15
  4007cf:	c3                   	retq   
  4007d0:	e8 5b fd ff ff       	callq  400530 <__stack_chk_fail@plt>
  4007d5:	66 2e 0f 1f 84 00 00 	nopw   %cs:0x0(%rax,%rax,1)
  4007dc:	00 00 00 
  4007df:	90                   	nop

しかしこの手のやつはよくうつかりをやらかすのでまた何か勘違󠄂ひしてないか怖いところです。