プロファイラの比較（＋簡単な使い方）



[![](https://mermaid.ink/img/eyJjb2RlIjoiZ3JhcGggVEJcblxuTShXaW5kb3dzLCBtYWNPUywgTGludXjlhajjgabjgac8YnI-5Yip55So44GX44Gf44GEKVxuRChtYWNPU-OBq-eJueWMluOBl-OBn-ODl-ODreODleOCoeOCpOODqeOBjDxicj7liKnnlKjjgZfjgZ_jgYQpXG5GKGZsYXQgcHJvZmlsZeOBqzxicj7lr77lv5zjgZfjgabjgYTjgovlv4XopoHjgYzjgYLjgospXG5UKOmAn-W6puOCkuaxguOCgeOCiylcblxuTSAtLT58WWVzfCBGXG5NIC0tPnxOb3wgRFxuRCAtLT58Tm98IFRcblxuRCAtLT58WWVzfCBJbnN0cnVtZW50c1xuRiAtLT58WWVzfCBncHJvZlxuRiAtLT58Tm98IEdEQlxuVCAtLT58WWVzfCBwZXJmXG5UIC0tPnxOb3wgVmFsZ3JpbmRcbiIsIm1lcm1haWQiOiJ7XG4gIFwidGhlbWVcIjogXCJkZWZhdWx0XCIsXG4gIFwidGhlbWVWYXJpYWJsZXNcIjoge1xuICAgIFwiYmFja2dyb3VuZFwiOiBcIndoaXRlXCIsXG4gICAgXCJwcmltYXJ5Q29sb3JcIjogXCIjRUNFQ0ZGXCIsXG4gICAgXCJzZWNvbmRhcnlDb2xvclwiOiBcIiNmZmZmZGVcIixcbiAgICBcInRlcnRpYXJ5Q29sb3JcIjogXCJoc2woODAsIDEwMCUsIDk2LjI3NDUwOTgwMzklKVwiLFxuICAgIFwicHJpbWFyeUJvcmRlckNvbG9yXCI6IFwiaHNsKDI0MCwgNjAlLCA4Ni4yNzQ1MDk4MDM5JSlcIixcbiAgICBcInNlY29uZGFyeUJvcmRlckNvbG9yXCI6IFwiaHNsKDYwLCA2MCUsIDgzLjUyOTQxMTc2NDclKVwiLFxuICAgIFwidGVydGlhcnlCb3JkZXJDb2xvclwiOiBcImhzbCg4MCwgNjAlLCA4Ni4yNzQ1MDk4MDM5JSlcIixcbiAgICBcInByaW1hcnlUZXh0Q29sb3JcIjogXCIjMTMxMzAwXCIsXG4gICAgXCJzZWNvbmRhcnlUZXh0Q29sb3JcIjogXCIjMDAwMDIxXCIsXG4gICAgXCJ0ZXJ0aWFyeVRleHRDb2xvclwiOiBcInJnYig5LjUwMDAwMDAwMDEsIDkuNTAwMDAwMDAwMSwgOS41MDAwMDAwMDAxKVwiLFxuICAgIFwibGluZUNvbG9yXCI6IFwiIzMzMzMzM1wiLFxuICAgIFwidGV4dENvbG9yXCI6IFwiIzMzM1wiLFxuICAgIFwibWFpbkJrZ1wiOiBcIiNFQ0VDRkZcIixcbiAgICBcInNlY29uZEJrZ1wiOiBcIiNmZmZmZGVcIixcbiAgICBcImJvcmRlcjFcIjogXCIjOTM3MERCXCIsXG4gICAgXCJib3JkZXIyXCI6IFwiI2FhYWEzM1wiLFxuICAgIFwiYXJyb3doZWFkQ29sb3JcIjogXCIjMzMzMzMzXCIsXG4gICAgXCJmb250RmFtaWx5XCI6IFwiXFxcInRyZWJ1Y2hldCBtc1xcXCIsIHZlcmRhbmEsIGFyaWFsXCIsXG4gICAgXCJmb250U2l6ZVwiOiBcIjE2cHhcIixcbiAgICBcImxhYmVsQmFja2dyb3VuZFwiOiBcIiNlOGU4ZThcIixcbiAgICBcIm5vZGVCa2dcIjogXCIjRUNFQ0ZGXCIsXG4gICAgXCJub2RlQm9yZGVyXCI6IFwiIzkzNzBEQlwiLFxuICAgIFwiY2x1c3RlckJrZ1wiOiBcIiNmZmZmZGVcIixcbiAgICBcImNsdXN0ZXJCb3JkZXJcIjogXCIjYWFhYTMzXCIsXG4gICAgXCJkZWZhdWx0TGlua0NvbG9yXCI6IFwiIzMzMzMzM1wiLFxuICAgIFwidGl0bGVDb2xvclwiOiBcIiMzMzNcIixcbiAgICBcImVkZ2VMYWJlbEJhY2tncm91bmRcIjogXCIjZThlOGU4XCIsXG4gICAgXCJhY3RvckJvcmRlclwiOiBcImhzbCgyNTkuNjI2MTY4MjI0MywgNTkuNzc2NTM2MzEyOCUsIDg3LjkwMTk2MDc4NDMlKVwiLFxuICAgIFwiYWN0b3JCa2dcIjogXCIjRUNFQ0ZGXCIsXG4gICAgXCJhY3RvclRleHRDb2xvclwiOiBcImJsYWNrXCIsXG4gICAgXCJhY3RvckxpbmVDb2xvclwiOiBcImdyZXlcIixcbiAgICBcInNpZ25hbENvbG9yXCI6IFwiIzMzM1wiLFxuICAgIFwic2lnbmFsVGV4dENvbG9yXCI6IFwiIzMzM1wiLFxuICAgIFwibGFiZWxCb3hCa2dDb2xvclwiOiBcIiNFQ0VDRkZcIixcbiAgICBcImxhYmVsQm94Qm9yZGVyQ29sb3JcIjogXCJoc2woMjU5LjYyNjE2ODIyNDMsIDU5Ljc3NjUzNjMxMjglLCA4Ny45MDE5NjA3ODQzJSlcIixcbiAgICBcImxhYmVsVGV4dENvbG9yXCI6IFwiYmxhY2tcIixcbiAgICBcImxvb3BUZXh0Q29sb3JcIjogXCJibGFja1wiLFxuICAgIFwibm90ZUJvcmRlckNvbG9yXCI6IFwiI2FhYWEzM1wiLFxuICAgIFwibm90ZUJrZ0NvbG9yXCI6IFwiI2ZmZjVhZFwiLFxuICAgIFwibm90ZVRleHRDb2xvclwiOiBcImJsYWNrXCIsXG4gICAgXCJhY3RpdmF0aW9uQm9yZGVyQ29sb3JcIjogXCIjNjY2XCIsXG4gICAgXCJhY3RpdmF0aW9uQmtnQ29sb3JcIjogXCIjZjRmNGY0XCIsXG4gICAgXCJzZXF1ZW5jZU51bWJlckNvbG9yXCI6IFwid2hpdGVcIixcbiAgICBcInNlY3Rpb25Ca2dDb2xvclwiOiBcInJnYmEoMTAyLCAxMDIsIDI1NSwgMC40OSlcIixcbiAgICBcImFsdFNlY3Rpb25Ca2dDb2xvclwiOiBcIndoaXRlXCIsXG4gICAgXCJzZWN0aW9uQmtnQ29sb3IyXCI6IFwiI2ZmZjQwMFwiLFxuICAgIFwidGFza0JvcmRlckNvbG9yXCI6IFwiIzUzNGZiY1wiLFxuICAgIFwidGFza0JrZ0NvbG9yXCI6IFwiIzhhOTBkZFwiLFxuICAgIFwidGFza1RleHRMaWdodENvbG9yXCI6IFwid2hpdGVcIixcbiAgICBcInRhc2tUZXh0Q29sb3JcIjogXCJ3aGl0ZVwiLFxuICAgIFwidGFza1RleHREYXJrQ29sb3JcIjogXCJibGFja1wiLFxuICAgIFwidGFza1RleHRPdXRzaWRlQ29sb3JcIjogXCJibGFja1wiLFxuICAgIFwidGFza1RleHRDbGlja2FibGVDb2xvclwiOiBcIiMwMDMxNjNcIixcbiAgICBcImFjdGl2ZVRhc2tCb3JkZXJDb2xvclwiOiBcIiM1MzRmYmNcIixcbiAgICBcImFjdGl2ZVRhc2tCa2dDb2xvclwiOiBcIiNiZmM3ZmZcIixcbiAgICBcImdyaWRDb2xvclwiOiBcImxpZ2h0Z3JleVwiLFxuICAgIFwiZG9uZVRhc2tCa2dDb2xvclwiOiBcImxpZ2h0Z3JleVwiLFxuICAgIFwiZG9uZVRhc2tCb3JkZXJDb2xvclwiOiBcImdyZXlcIixcbiAgICBcImNyaXRCb3JkZXJDb2xvclwiOiBcIiNmZjg4ODhcIixcbiAgICBcImNyaXRCa2dDb2xvclwiOiBcInJlZFwiLFxuICAgIFwidG9kYXlMaW5lQ29sb3JcIjogXCJyZWRcIixcbiAgICBcImxhYmVsQ29sb3JcIjogXCJibGFja1wiLFxuICAgIFwiZXJyb3JCa2dDb2xvclwiOiBcIiM1NTIyMjJcIixcbiAgICBcImVycm9yVGV4dENvbG9yXCI6IFwiIzU1MjIyMlwiLFxuICAgIFwiY2xhc3NUZXh0XCI6IFwiIzEzMTMwMFwiLFxuICAgIFwiZmlsbFR5cGUwXCI6IFwiI0VDRUNGRlwiLFxuICAgIFwiZmlsbFR5cGUxXCI6IFwiI2ZmZmZkZVwiLFxuICAgIFwiZmlsbFR5cGUyXCI6IFwiaHNsKDMwNCwgMTAwJSwgOTYuMjc0NTA5ODAzOSUpXCIsXG4gICAgXCJmaWxsVHlwZTNcIjogXCJoc2woMTI0LCAxMDAlLCA5My41Mjk0MTE3NjQ3JSlcIixcbiAgICBcImZpbGxUeXBlNFwiOiBcImhzbCgxNzYsIDEwMCUsIDk2LjI3NDUwOTgwMzklKVwiLFxuICAgIFwiZmlsbFR5cGU1XCI6IFwiaHNsKC00LCAxMDAlLCA5My41Mjk0MTE3NjQ3JSlcIixcbiAgICBcImZpbGxUeXBlNlwiOiBcImhzbCg4LCAxMDAlLCA5Ni4yNzQ1MDk4MDM5JSlcIixcbiAgICBcImZpbGxUeXBlN1wiOiBcImhzbCgxODgsIDEwMCUsIDkzLjUyOTQxMTc2NDclKVwiXG4gIH1cbn0iLCJ1cGRhdGVFZGl0b3IiOnRydWUsImF1dG9TeW5jIjp0cnVlLCJ1cGRhdGVEaWFncmFtIjp0cnVlfQ)](https://mermaid-js.github.io/mermaid-live-editor/edit/#eyJjb2RlIjoiZ3JhcGggVEJcblxuTShXaW5kb3dzLCBtYWNPUywgTGludXjlhajjgabjgac8YnI-5Yip55So44GX44Gf44GEKVxuRChtYWNPU-OBq-eJueWMluOBl-OBn-ODl-ODreODleOCoeOCpOODqeOBjDxicj7liKnnlKjjgZfjgZ_jgYQpXG5GKGZsYXQgcHJvZmlsZeOBqzxicj7lr77lv5zjgZfjgabjgYTjgovlv4XopoHjgYzjgYLjgospXG5UKOmAn-W6puOCkuaxguOCgeOCiylcblxuTSAtLT58WWVzfCBGXG5NIC0tPnxOb3wgRFxuRCAtLT58Tm98IFRcblxuRCAtLT58WWVzfCBJbnN0cnVtZW50c1xuRiAtLT58WWVzfCBncHJvZlxuRiAtLT58Tm98IEdEQlxuVCAtLT58WWVzfCBwZXJmXG5UIC0tPnxOb3wgVmFsZ3JpbmRcbiIsIm1lcm1haWQiOiJ7XG4gIFwidGhlbWVcIjogXCJkZWZhdWx0XCIsXG4gIFwidGhlbWVWYXJpYWJsZXNcIjoge1xuICAgIFwiYmFja2dyb3VuZFwiOiBcIndoaXRlXCIsXG4gICAgXCJwcmltYXJ5Q29sb3JcIjogXCIjRUNFQ0ZGXCIsXG4gICAgXCJzZWNvbmRhcnlDb2xvclwiOiBcIiNmZmZmZGVcIixcbiAgICBcInRlcnRpYXJ5Q29sb3JcIjogXCJoc2woODAsIDEwMCUsIDk2LjI3NDUwOTgwMzklKVwiLFxuICAgIFwicHJpbWFyeUJvcmRlckNvbG9yXCI6IFwiaHNsKDI0MCwgNjAlLCA4Ni4yNzQ1MDk4MDM5JSlcIixcbiAgICBcInNlY29uZGFyeUJvcmRlckNvbG9yXCI6IFwiaHNsKDYwLCA2MCUsIDgzLjUyOTQxMTc2NDclKVwiLFxuICAgIFwidGVydGlhcnlCb3JkZXJDb2xvclwiOiBcImhzbCg4MCwgNjAlLCA4Ni4yNzQ1MDk4MDM5JSlcIixcbiAgICBcInByaW1hcnlUZXh0Q29sb3JcIjogXCIjMTMxMzAwXCIsXG4gICAgXCJzZWNvbmRhcnlUZXh0Q29sb3JcIjogXCIjMDAwMDIxXCIsXG4gICAgXCJ0ZXJ0aWFyeVRleHRDb2xvclwiOiBcInJnYig5LjUwMDAwMDAwMDEsIDkuNTAwMDAwMDAwMSwgOS41MDAwMDAwMDAxKVwiLFxuICAgIFwibGluZUNvbG9yXCI6IFwiIzMzMzMzM1wiLFxuICAgIFwidGV4dENvbG9yXCI6IFwiIzMzM1wiLFxuICAgIFwibWFpbkJrZ1wiOiBcIiNFQ0VDRkZcIixcbiAgICBcInNlY29uZEJrZ1wiOiBcIiNmZmZmZGVcIixcbiAgICBcImJvcmRlcjFcIjogXCIjOTM3MERCXCIsXG4gICAgXCJib3JkZXIyXCI6IFwiI2FhYWEzM1wiLFxuICAgIFwiYXJyb3doZWFkQ29sb3JcIjogXCIjMzMzMzMzXCIsXG4gICAgXCJmb250RmFtaWx5XCI6IFwiXFxcInRyZWJ1Y2hldCBtc1xcXCIsIHZlcmRhbmEsIGFyaWFsXCIsXG4gICAgXCJmb250U2l6ZVwiOiBcIjE2cHhcIixcbiAgICBcImxhYmVsQmFja2dyb3VuZFwiOiBcIiNlOGU4ZThcIixcbiAgICBcIm5vZGVCa2dcIjogXCIjRUNFQ0ZGXCIsXG4gICAgXCJub2RlQm9yZGVyXCI6IFwiIzkzNzBEQlwiLFxuICAgIFwiY2x1c3RlckJrZ1wiOiBcIiNmZmZmZGVcIixcbiAgICBcImNsdXN0ZXJCb3JkZXJcIjogXCIjYWFhYTMzXCIsXG4gICAgXCJkZWZhdWx0TGlua0NvbG9yXCI6IFwiIzMzMzMzM1wiLFxuICAgIFwidGl0bGVDb2xvclwiOiBcIiMzMzNcIixcbiAgICBcImVkZ2VMYWJlbEJhY2tncm91bmRcIjogXCIjZThlOGU4XCIsXG4gICAgXCJhY3RvckJvcmRlclwiOiBcImhzbCgyNTkuNjI2MTY4MjI0MywgNTkuNzc2NTM2MzEyOCUsIDg3LjkwMTk2MDc4NDMlKVwiLFxuICAgIFwiYWN0b3JCa2dcIjogXCIjRUNFQ0ZGXCIsXG4gICAgXCJhY3RvclRleHRDb2xvclwiOiBcImJsYWNrXCIsXG4gICAgXCJhY3RvckxpbmVDb2xvclwiOiBcImdyZXlcIixcbiAgICBcInNpZ25hbENvbG9yXCI6IFwiIzMzM1wiLFxuICAgIFwic2lnbmFsVGV4dENvbG9yXCI6IFwiIzMzM1wiLFxuICAgIFwibGFiZWxCb3hCa2dDb2xvclwiOiBcIiNFQ0VDRkZcIixcbiAgICBcImxhYmVsQm94Qm9yZGVyQ29sb3JcIjogXCJoc2woMjU5LjYyNjE2ODIyNDMsIDU5Ljc3NjUzNjMxMjglLCA4Ny45MDE5NjA3ODQzJSlcIixcbiAgICBcImxhYmVsVGV4dENvbG9yXCI6IFwiYmxhY2tcIixcbiAgICBcImxvb3BUZXh0Q29sb3JcIjogXCJibGFja1wiLFxuICAgIFwibm90ZUJvcmRlckNvbG9yXCI6IFwiI2FhYWEzM1wiLFxuICAgIFwibm90ZUJrZ0NvbG9yXCI6IFwiI2ZmZjVhZFwiLFxuICAgIFwibm90ZVRleHRDb2xvclwiOiBcImJsYWNrXCIsXG4gICAgXCJhY3RpdmF0aW9uQm9yZGVyQ29sb3JcIjogXCIjNjY2XCIsXG4gICAgXCJhY3RpdmF0aW9uQmtnQ29sb3JcIjogXCIjZjRmNGY0XCIsXG4gICAgXCJzZXF1ZW5jZU51bWJlckNvbG9yXCI6IFwid2hpdGVcIixcbiAgICBcInNlY3Rpb25Ca2dDb2xvclwiOiBcInJnYmEoMTAyLCAxMDIsIDI1NSwgMC40OSlcIixcbiAgICBcImFsdFNlY3Rpb25Ca2dDb2xvclwiOiBcIndoaXRlXCIsXG4gICAgXCJzZWN0aW9uQmtnQ29sb3IyXCI6IFwiI2ZmZjQwMFwiLFxuICAgIFwidGFza0JvcmRlckNvbG9yXCI6IFwiIzUzNGZiY1wiLFxuICAgIFwidGFza0JrZ0NvbG9yXCI6IFwiIzhhOTBkZFwiLFxuICAgIFwidGFza1RleHRMaWdodENvbG9yXCI6IFwid2hpdGVcIixcbiAgICBcInRhc2tUZXh0Q29sb3JcIjogXCJ3aGl0ZVwiLFxuICAgIFwidGFza1RleHREYXJrQ29sb3JcIjogXCJibGFja1wiLFxuICAgIFwidGFza1RleHRPdXRzaWRlQ29sb3JcIjogXCJibGFja1wiLFxuICAgIFwidGFza1RleHRDbGlja2FibGVDb2xvclwiOiBcIiMwMDMxNjNcIixcbiAgICBcImFjdGl2ZVRhc2tCb3JkZXJDb2xvclwiOiBcIiM1MzRmYmNcIixcbiAgICBcImFjdGl2ZVRhc2tCa2dDb2xvclwiOiBcIiNiZmM3ZmZcIixcbiAgICBcImdyaWRDb2xvclwiOiBcImxpZ2h0Z3JleVwiLFxuICAgIFwiZG9uZVRhc2tCa2dDb2xvclwiOiBcImxpZ2h0Z3JleVwiLFxuICAgIFwiZG9uZVRhc2tCb3JkZXJDb2xvclwiOiBcImdyZXlcIixcbiAgICBcImNyaXRCb3JkZXJDb2xvclwiOiBcIiNmZjg4ODhcIixcbiAgICBcImNyaXRCa2dDb2xvclwiOiBcInJlZFwiLFxuICAgIFwidG9kYXlMaW5lQ29sb3JcIjogXCJyZWRcIixcbiAgICBcImxhYmVsQ29sb3JcIjogXCJibGFja1wiLFxuICAgIFwiZXJyb3JCa2dDb2xvclwiOiBcIiM1NTIyMjJcIixcbiAgICBcImVycm9yVGV4dENvbG9yXCI6IFwiIzU1MjIyMlwiLFxuICAgIFwiY2xhc3NUZXh0XCI6IFwiIzEzMTMwMFwiLFxuICAgIFwiZmlsbFR5cGUwXCI6IFwiI0VDRUNGRlwiLFxuICAgIFwiZmlsbFR5cGUxXCI6IFwiI2ZmZmZkZVwiLFxuICAgIFwiZmlsbFR5cGUyXCI6IFwiaHNsKDMwNCwgMTAwJSwgOTYuMjc0NTA5ODAzOSUpXCIsXG4gICAgXCJmaWxsVHlwZTNcIjogXCJoc2woMTI0LCAxMDAlLCA5My41Mjk0MTE3NjQ3JSlcIixcbiAgICBcImZpbGxUeXBlNFwiOiBcImhzbCgxNzYsIDEwMCUsIDk2LjI3NDUwOTgwMzklKVwiLFxuICAgIFwiZmlsbFR5cGU1XCI6IFwiaHNsKC00LCAxMDAlLCA5My41Mjk0MTE3NjQ3JSlcIixcbiAgICBcImZpbGxUeXBlNlwiOiBcImhzbCg4LCAxMDAlLCA5Ni4yNzQ1MDk4MDM5JSlcIixcbiAgICBcImZpbGxUeXBlN1wiOiBcImhzbCgxODgsIDEwMCUsIDkzLjUyOTQxMTc2NDclKVwiXG4gIH1cbn0iLCJ1cGRhdGVFZGl0b3IiOmZhbHNlLCJhdXRvU3luYyI6dHJ1ZSwidXBkYXRlRGlhZ3JhbSI6ZmFsc2V9)


profiler | flat profile | call graph profile | interface | platform | profiling speed | to Flame Graph | to dot graph
--- | --- | --- | --- | --- | --- | --- | ---
gprof | ✅ | ✅ | CUI, GUI※1 | Windows, macOS, Linux | 0m2.891s※2 | ❌ | ✅
perf | ✅ | ✅ | CUI, GUI※1 | Linux | 0m3.617s※2 | ✅ | ✅
Valgrind | ✅ | ✅ | CUI, GUI※1 | macOS, Linux | 0m52.814s※2 | ❌ | ✅
GDB | ❌ | ✅ | CUI, GUI※1 | Windows, macOS, Linux | 0m1.761s※2 | ✅ | ❌
Instruments| ✅ | ✅ | CUI, GUI | macOS | 0m4.387s※3 | ❌ | ❌

※1 サードパーティ製のアプリケーションを採用することで実現が可能
※2 後述のプログラムの解析時間（timeコマンドのuser。CentOS）
※3 後述のプログラムの解析時間（timeコマンドのuser。macOS）

この他にもVisualStudio(VSPerf, VSDiagnostics)等色々なプロファイラがあるみたいなので、暇な時にでも追記していこうかなと思います。


## 性能解析対象

以下のプログラムを利用します。

```main.c
#define MAX 10000

void initialize(int result[MAX]) {
    for (int i=0; i<MAX; i++) result[i] = 0;
}

void ten_thousand_loop(int result[MAX]) {
    for (int j=0; j<MAX; j++)
        for (int i=0; i<MAX; i++) result[i] = 0;
}

void twenty_thousand_loop(int result[MAX]) {
    for (int j=0; j<2*MAX; j++)
        for (int i=0; i<MAX; i++) result[i] = 0;
}

void thirty_thousand_loop(int result[MAX]) {
    for (int j=0; j<3*MAX; j++)
        for (int i=0; i<MAX; i++) result[i] = 0;
}

int main() {
    int result[MAX];

    initialize(result);
    ten_thousand_loop(result);
    twenty_thousand_loop(result);
    thirty_thousand_loop(result);

    return 0;
}
```

## スペック

スペックは以下の通り。

### Linux (CentOS8)

* CPU: Intel(R) Core(TM) m3-7Y32 CPU @ 1.10GHz
* memory: 4GB

今回は、ビルドに`GCC`を利用します。
OSは`CentOS Linux release 8.1.1911 (Core)`です。

```bash
# GCCのインストール
$ dnf install -y gcc

# ビルド (-g オプションでデバッグ情報を生成しておく)
$ gcc main.c -o sample_app -g

# 速度
$ time ./sample_app 

real	0m2.325s
user	0m2.287s
sys	0m0.004s

```

### macOS

* CPU: Intel(R) Core(TM) i7-1060NG7 CPU @ 1.20GHz
* memory: 16GB

今回は、ビルドに`Clang`を利用します。
OSは`macOS Catalina version 10.15.7`です。

```bash
# 事前にXcodeをAppstoreからダウンロードしてインストールしておく
# command line tools のインストール (Clangのインストール)
$ xcode-select --install

# ビルド (-g オプションでデバッグ情報を生成しておく)
$ clang main.c -o sample_app -g

# 速度
$ bash -c "time ./sample_app"

real	0m0.790s
user	0m0.754s
sys	0m0.004s
```


## プロファイラ

### gprof

gprof[^0]はbinutilsに付属しているプロファイラです。
多分一番手軽です。

```bash
# gccを利用してビルドを行う（-pgオプションを忘れないこと）
$ gcc main.c -pg -o sample_app

# 実行とプロファイルデータの吐き出し
$ ./sample_app

# プロファイルデータの解析
$ gprof ./sample_app gmon.out
```

`flat profile`及び`call graph profile`を吐き出してくれます。

```bash
Flat profile:

Each sample counts as 0.01 seconds.
  %   cumulative   self              self     total           
 time   seconds   seconds    calls   s/call   s/call  name    
 53.86      1.37     1.37        1     1.37     1.37  thirty_thousand_loop
 31.92      2.18     0.81        1     0.81     0.81  twenty_thousand_loop
 15.56      2.57     0.40        1     0.40     0.40  ten_thousand_loop
  0.00      2.57     0.00        1     0.00     0.00  initialize

:

		     Call graph (explanation follows)


granularity: each sample hit covers 2 byte(s) for 0.39% of 2.57 seconds

index % time    self  children    called     name
                                                 <spontaneous>
[1]    100.0    0.00    2.57                 main [1]
                1.37    0.00       1/1           thirty_thousand_loop [2]
                0.81    0.00       1/1           twenty_thousand_loop [3]
                0.40    0.00       1/1           ten_thousand_loop [4]
                0.00    0.00       1/1           initialize [5]
-----------------------------------------------
                1.37    0.00       1/1           main [1]
[2]     53.1    1.37    0.00       1         thirty_thousand_loop [2]
-----------------------------------------------
                0.81    0.00       1/1           main [1]
[3]     31.5    0.81    0.00       1         twenty_thousand_loop [3]
-----------------------------------------------
                0.40    0.00       1/1           main [1]
[4]     15.4    0.40    0.00       1         ten_thousand_loop [4]
-----------------------------------------------
                0.00    0.00       1/1           main [1]
[5]      0.0    0.00    0.00       1         initialize [5]
-----------------------------------------------

:

Index by function name

   [5] initialize              [2] thirty_thousand_loop
   [4] ten_thousand_loop       [3] twenty_thousand_loop
```


### perf

perfはパフォーマンスカウンターを使用したLinux向けの性能解析ツールです[^1]。
コマンドラインで操作することができます。

早速実行してみましょう。


```bash
# CentOS8の場合はパッケージマネージャを利用してインストールできる
$ dnf install -y perf

# カーネル解析の値を有効にしておく(/proc/sys/kernel/kptr_restrictの値を0にしておく)
$ echo 0 > /proc/sys/kernel/kptr_restrict

# 解析
$ perf record -- ./sample_app

# 結果確認
$ perf report
```

結果は降順で出力されます。
出力表示を終了したい場合は`ESC`キーで抜けることができます。

![report.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425840/2aab273d-8a00-a968-003a-a4fce8e2257f.png)


また、以下のコマンドを利用することで元のファイルの行単位まで追うことができます。

```bash
# annotateの結果をless形式で表示する
$ perf annotate -l --stdio

Sorted summary for file /home/sample_app
----------------------------------------------

   99.95 main.c:19
: # annotateの結果が続く
```

更に、コールグラフを出力することも可能です。
FlameGraph[^2]と組み合わせてSVG化し、可視化してみましょう。

```bash
# FlameGraphを取得するために必要なGitとSVG出力に必要なperl-openをインストール
$ dnf install -y git perl-open.noarch

# FlameGraphをインストール
$ cd /usr/local/
$ git clone https://github.com/brendangregg/FlameGraph.git
$ export PATH="${PATH}:/usr/local/FlameGraph/"
$ source ~/.bash_profile

# 一つ前のカレントディレクトリに戻る
$ cd -

# コールグラフの出力
$ perf record -F 99 --call-graph dwarf -g ./sample_app

# SVG化
$ perf script | stackcollapse-perf.pl | flamegraph.pl > flamegraph.svg
```

出力したflamegraph.svgをChromeなどのブラウザで表示してみましょう。

![svg.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425840/d8c7fafa-b2aa-e9fe-f764-b962f12d1e6b.png)


綺麗にSVG出力することができました。
横幅がCPU使用率を表しています。また、横軸はアルファベット順でソートされています。
赤やオレンジ等色の差に大きな意味はありません。グラフをみやすくするためのものです。
これさえあれば手軽にCPU使用率をわかりやすく共有することができますね。

以上をGUIで操作することができるhotspot[^3]なる強力なツールが存在します。
今回の説明では省きますが、直感的に操作がしたい場合は選択肢に入れない手はないでしょう。


### Valgrind

メモリエラーの検出に利用されるValgrindには、プログラムの実行における関数間の呼び出し履歴をコールグラフとして記録するCallgrindなるプロファイリングツールが付属しています。

```bash
# Valgrindのインストール
$ dnf install -y valgrind

# プロファイリング
$ valgrind --tool=callgrind --callgrind-out-file=./callgrind.out.sample_app ./sample_app
```

出力されたファイルは、KCachegrind等のGUIツールで可視化できる他、組み合わせによってはSVGのグラフに変換することも可能です。
早速SVG化してみましょう。今回は`gprof2dot`を利用します。

```bash
# gprof2dotの取得・実行に必要なPythonとSVG出力に必要なgraphvizをインストール
$ dnf install -y python36 graphviz

# gprof2dotをインストール
$ pip3 install gprof2dot

# SVGを出力
$ gprof2dot -f callgrind ./callgrind.out.sample_app | dot -Tsvg -o report.svg
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425840/b15d7a69-3522-6a38-0b09-a76efba093ee.png" width=60%>

綺麗にSVGを出力することができました。

<!--

VisualStudio

IDEとして有名なVisualStudioですが、性能解析の機能も持ち合わせています。
今回はCUIでプロファイリングしてみましょう。VSPerfCmd[^4]を利用します。

```powershell
# vs_buildtoolsの取得
$ curl -LO "https://aka.ms/vs/16/release/vs_buildtools.exe"

# VisualStudioのインストール
$ vs_buildtools.exe --quiet --wait --norestart --nocache `
    --installPath C:\BuildTools `
    --add Microsoft.VisualStudio.Workload.VCTools `
    --add Microsoft.VisualStudio.Workload.MSBuildTools `
    --add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 `
    --add Microsoft.VisualStudio.Component.Windows10SDK.17763 `
 || IF "%ERRORLEVEL%"=="3010" EXIT 0

cl .\src\icomiki.c /link /DEBUG /PROFILE

C:\"Program Files (x86)"\"Microsoft Visual Studio 16.0"\"Team Tools"\"Performance Tools"\VSPerfCmd.exe

https://stackoverflow.com/questions/3839425/vsinstr-performance-profiling
VSPerfCmd /start:trace /output:traceoutput.vsp /user:orz

Shutdown

C:\"Program Files (x86)"\"Microsoft Visual Studio 16.0"\"Team Tools"\"Performance Tools"\VSPerf /launch:icomiki.exe

VSPerfReport traceoutput.vsp

https://stackoverflow.com/questions/30127289/using-vsperf-exe-instead-of-vsperfcmd-exe

C:\"Program Files (x86)"\"Microsoft Visual Studio 16.0"\"Team Tools"\"Performance Tools"\VSPerfCmd.exe /start:SAMPLE /output:traceoutput.vsp /user:orz

VSPerfCmd /launch:icomiki


# プロファイリング
$ VSPerfCmd /start:sample_app /output: report.vsp
```

[^4] : https://docs.microsoft.com/ja-jp/visualstudio/profiling/vsperfreport?view=vs-2017 <br> https://docs.microsoft.com/en-us/visualstudio/profiling/how-to-launch-a-stand-alone-app-and-collect-application-statistics?view=vs-2017


xperfってなんだ
-->

### GDB

こちらはプロファイラというよりはデバッグツールと呼んだ方が正しいような気がしますが、手軽なので紹介しておきます。
GDBではスタック上のバックトレースを表示することができます。

```bash
# GDBのインストール
$ dnf install -y gdb

# 実行
$ gdb ./sample_app --silent
Reading symbols from ./sample_app...done.

# 実行すると対話が始まる
# 対話ではbreakpointやbacktrace等の機能を利用することができる

# 試しに19行目にbreakpointを追加してみる
(gdb) break 19

# 実行
(gdb) run

# スタック全体のバックトレースを表示
(gdb) backtrace

#0  thirty_thousand_loop (result=0x7fffffff4f30) at main.c:19
#1  0x00000000004006ab in main () at main.c:28

# 終了
(gdb) quit
```

また、対話で渡すコマンドを事前に用意しておき、実行時にGDBに読み込ませてコマンドを流すことも可能です。
下記のようなファイルを用意し、`--command=` の後にファイル名を記述することで読み込むことができます。

```php:sample.gdb
# gdb ./sample_app --command=sample.gdb --silent
set confirm off
break 19
run
backtrace
quit
```

上記を利用して、GDBの出力結果をパイプでFlameGraph[^2]のスクリプトに渡すことで、バックトレースをSVGで可視化することができます。

```bash
$ gdb ./sample_app --command=sample.gdb --silent | stackcollapse-gdb.pl | flamegraph.pl > flamegraph.svg
```

![backtrace.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425840/7527a242-00bc-16c7-2ad9-99273ac027b8.png)

単純に関数の呼び順を確認したいのであればGDBで十分かもしれませんね。


### Instruments

Instruments は Xcode の機能の一つ[^4]です。
Instruments には Template と呼ばれる様々な機能が存在しますが、今回はその中の「Time Profiler」を利用してみましょう。

```bash
# Instruments (xctrace コマンドを利用できるようにする)
$ sudo xcode-select --switch /Applications/Xcode.app/

# プロファイリング
$ xcrun xctrace record --template 'Time Profiler' --output ./result.trace --launch -- ./sample_app

# 結果を開く
$ open ./result.trace
```

うまくいけば以下のようなアプリが起動するはずです。
コールグラフの ▶︎ マークをクリックしていくと、ネストされた結果を確認することができます。

![result.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425840/48f38f96-316b-b44e-3df5-038305779d2d.png)



## 参考

[^0]: https://sourceware.org/binutils/docs/gprof/
[^1]: https://perf.wiki.kernel.org/index.php/Main_Page <br> > perf: Linux profiling with performance counters
[^2]: https://github.com/brendangregg/FlameGraph
[^3]: https://github.com/KDAB/hotspot
[^4]: https://developer.apple.com/xcode/features/