* 32bit vs 64bit, C vs C++
-(by [[K]], 2019.10.25)
** (0) はじめに
-C++ではオブジェクトが生存スコープを抜けると自動でデストラクタが呼ばれますが、それがとてもうらやましくて、私は4月ごろにメイン使用言語をC++に変更しました。
-しかしC++でプログラムを書くと、なんかやたらと実行ファイルが大きくなるような気がして、気のせいなのかなあ、それとも本当なのかなあと気になっていました。
-今回、それを(厳密ではないものの)確認する機会があったので、ここにその記録をメモします。
** (1)
-私は今年の4月くらいから自作のライブラリを多用していますが、このライブラリは32bitのC++だけを想定して書かれていました。
-これを先日C言語に書き直し、64bit/32bitの両対応にすることができました。
-C言語で書き直す際には、多少の改良もしているので、おそらく速度は少し上がっていると思います。
-それで同じような処理をこれらのライブラリを使って実装して実行時間を比較しました。処理内容は、簡単なソートプログラムです。65536個のデータをソートする処理を、1024回やっています。
-最適化レベルは、どれも-O3です。
| |bit数|言語|バージョン|実行時間|実行ファイルサイズ|補足|h
|#1|32bit|C|gcc (GCC) 3.4.5|23.9秒|RIGHT:9,216バイト|昨年まではこのバージョンばかり使っていました|
|#2|32bit|C++|g++ (MinGW.org GCC-6.3.0-1) 6.3.0|16.9秒|RIGHT:111,104バイト|つい先日までメインで使っていました|
|#3|32bit|C|gcc (MinGW.org GCC-6.3.0-1) 6.3.0|16.8秒|RIGHT:23,040バイト|今月から使い始めています|
|#4|64bit|C|gcc (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 8.1.0|14.9秒|RIGHT:17,920バイト|今月から使い始めています|
-考察
--古いgccの実行ファイルはダントツにコンパクトだけど、遅い!(#1)
--g++の実行ファイルの大きさはもはや異常(でもこれは最新の64bit版なら改良されてマシになっている可能性はある、しかし比較する手段が私にはまだない)(#2)
--64bitのC言語って、速くて常識的なファイルサイズで一番いいかもしれない。少なくともこの中では一番いい。(#4)
-ということで、とりあえず当面は、#3と#4の環境を使えば良さそう。
** (2)
-その後、uchanさんに、いくらなんでもそんなに大きなサイズの差になるのはおかしいのではないかと教えてもらって、いくつか確認したところ、以下のことが分かりました。
-私は、C++版のコンパイルにあたって、「-static-libgcc -static-libstdc++」というオプションを指定しています。これのせいでC++版はサイズで不利になったのではないかと気づきました。
-実際、このオプションを付けずにビルドしたらC++版でも 28,160バイト になりました。・・・おおおお!・・・なんか一気にまともな大きさに戻ったぞ!
-しかし私はそれでもこのオプションを外す気にはなれません。なぜなら、このオプションを外すと、"libgcc_s_dw2-1.dll"と"libstdc++-6.dll"が実行に際して必要になってしまうからです。・・・これは私にとってはうっとうしい!!
-私はEXEファイルの簡易解析ツールを持っているので([[p20181026c]]の''pe_info0a''のこと)、それを使ってどんな関数をダイナミックリンクしようとしているのか比較してみました。
||111,104バイト版|28,160バイト版|
|KERNEL32.dll|RIGHT:30シンボル|RIGHT:18シンボル|
|msvcrt.dll|RIGHT:43シンボル|RIGHT:38シンボル|
|libgcc_s_dw2-1.dll|RIGHT:0シンボル|RIGHT:3シンボル|
|libstdc++-6.dll|RIGHT:0シンボル|RIGHT:1シンボル|
-なるほどなー。では、2つのlibなんちゃらはどんなやつをリンクしているのか確認してみると、こうなっていました。
import "libgcc_s_dw2-1.dll":
0x0040a268: hint:0x000f name:"_Unwind_Resume"
0x0040a26c: hint:0x0025 name:"__deregister_frame_info"
0x0040a270: hint:0x006a name:"__register_frame_info"
import "libstdc++-6.dll":
0x0040a278: hint:0x1443 name:"__gxx_personality_v0"
-うーん、なんかそんなに巨大そうな関数には見えないけどなあ。これらをstaticリンクしただけで、どうしてこんなことになってしまうのだろう・・・。
--「_Unwind_Resume」が巨大なのだろうか・・・。
* こめんと欄
#comment