{"id":32720,"date":"2023-11-17T17:06:32","date_gmt":"2023-11-17T17:06:32","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/cppblog\/?p=32720"},"modified":"2023-11-17T17:06:32","modified_gmt":"2023-11-17T17:06:32","slug":"functions-view-for-build-insights-in-visual-studio-2022-17-8","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/cppblog\/functions-view-for-build-insights-in-visual-studio-2022-17-8\/","title":{"rendered":"Functions View for Build Insights in Visual Studio 2022 17.8"},"content":{"rendered":"<h3><strong>Introduction<\/strong><\/h3>\n<p>We are excited to unveil a new feature in Build Insights for Visual Studio: Functions View! This feature is available in Visual Studio 2022 version 17.8. Functions View offers essential insights into functions and forceinlines within your codebases.<\/p>\n<p><a href=\"https:\/\/visualstudio.microsoft.com\/downloads\/\">Download Visual Studio 2022 17.8<\/a><\/p>\n<p>We extend our sincere thanks thanks to the developer community, especially our game studio partners, for actively providing feedback. Your contributions are invaluable in shaping this new feature.<\/p>\n<p>For more details about Build Insights and to explore other features like Included Files and Include Tree Views, please visit our <a href=\"https:\/\/devblogs.microsoft.com\/cppblog\/build-insights-now-available-in-visual-studio-2022\/#getting-started\">initial announcement blogpost<\/a>.<\/p>\n<h3><strong>Code Generation Insights with Functions View<\/strong><\/h3>\n<p>Functions View is a powerful tool that displays the impact of each function on the total build time by analyzing code generation times and forceinlines. Forceinlines, commonly used to boost runtime efficiency, can also influence build times.<\/p>\n<p><span style=\"font-size: 12pt;\">The following sample code is based on a public code sample by <a href=\"https:\/\/aras-p.info\/blog\/2017\/10\/09\/Forced-Inlining-Might-Be-Slow\/\">Aras Pranckevi\u010dius<\/a>. We will use it to show you how you can optimize your builds with <\/span><span style=\"font-size: 12pt;\">Functions View. To setup your project, create a C++ Console application and copy the following sample code:<\/span><\/p>\n<pre class=\"prettyprint language-cpp\"><code class=\"language-cpp\">#include &lt;emmintrin.h&gt;\r\n\r\n\r\nstruct float4\r\n{\r\n    __m128 val;\r\n    float4() { val = _mm_setzero_ps(); }\r\n    float4(float x) { val = _mm_set1_ps(x); }\r\n    float4(float x, float y) { val = _mm_set_ps(y, x, y, x); }\r\n    float4(float x, float y, float z) { val = _mm_set_ps(0.f, z, y, x); }\r\n    float4(float x, float y, float z, float w) { val = _mm_set_ps(w, z, y, x); }\r\n    float4(__m128 v) { val = v; }\r\n};\r\n\r\n\r\nstatic __forceinline float4 operator+(const float4&amp; a, const float4&amp; b) { return float4(_mm_add_ps(a.val, b.val)); }\r\nstatic __forceinline float4 operator-(const float4&amp; a, const float4&amp; b) { return float4(_mm_sub_ps(a.val, b.val)); }\r\nstatic __forceinline float4 operator*(const float4&amp; a, const float4&amp; b) { return float4(_mm_mul_ps(a.val, b.val)); }\r\nstatic __forceinline float4 operator\/(const float4&amp; a, const float4&amp; b) { return float4(_mm_div_ps(a.val, b.val)); }\r\nstatic __forceinline float4 csum(const float4&amp; p)\r\n{\r\n    __m128 r = _mm_add_ps(p.val, _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(p.val), _MM_SHUFFLE(0, 3, 2, 1))));\r\n    return _mm_add_ps(r, _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(r), _MM_SHUFFLE(1, 0, 3, 2))));\r\n}\r\nstatic __forceinline float4 dot(const float4&amp; p0, const float4&amp; p1) { return csum(p0 * p1); }\r\nstatic __forceinline float4 dot(const float4&amp; p) { return dot(p, p); }\r\nstatic __forceinline float4 rsqrt(const float4&amp; x)\r\n{\r\n#define C0  9.999998e-01f\r\n#define C1  3.0000002e+00f\r\n#define C2  .5f\r\n#define C3  340282346638528859811704183484516925440.f\r\n    __m128 e = _mm_mul_ps(_mm_rsqrt_ps((__m128) x.val), _mm_set_ps(C0, C0, C0, C0));\r\n    e = _mm_min_ps(e, _mm_set_ps(C3, C3, C3, C3));\r\n    return _mm_mul_ps(_mm_mul_ps(e, _mm_set_ps(C2, C2, C2, C2)), _mm_sub_ps(_mm_set_ps(C1, C1, C1, C1), _mm_mul_ps(_mm_mul_ps(x.val, e), e)));\r\n}\r\nstatic __forceinline float4 normalize(const float4&amp; v)\r\n{\r\n    return v * rsqrt(dot(v));\r\n}\r\n\r\nstatic __forceinline float4 ident() { return float4(0.f, 0.f, 0.f, 1.f); }\r\nstatic __forceinline float4 sampleFun1(const float4&amp; x, const float4&amp; y)\r\n{\r\n    return csum(x) \/ x + y;\r\n}\r\nstatic __forceinline float4 sampleFun2(const float4&amp; q1, const float4&amp; q2)\r\n{\r\n    return sampleFun1(q1 * q2, q2 - q1) * (q1 + q2);\r\n}\r\nstatic float4 sampleFun3(const float4&amp; pq, const float4&amp; mask)\r\n{\r\n    const float c8 = 0.923879532511287f;\r\n    const float s8 = 0.38268343236509f;\r\n    const float g = 5.82842712474619f;\r\n\r\n\r\n    float4 ch = float4(2) * (normalize(pq) - normalize(mask));\r\n    float4 sh = pq * normalize(ch);\r\n    float4 r = ((g * sh * sh - ch * ch) + sh \/ float4(s8, s8, s8, c8)) * mask;\r\n    return normalize(r);\r\n}\r\nstruct matrix\r\n{\r\n    float4 m0, m1, m2;\r\n};\r\nstatic __forceinline float4 sampleFunIteration(matrix&amp; s, int count = 5)\r\n{\r\n    matrix qm;\r\n    float4 q, v = ident();\r\n    for (int iter = 0; iter &lt; count; iter++)\r\n    {\r\n        q = sampleFun3(s.m0, float4(0, 0, 1, 1));\r\n        v = sampleFun2(v, q);\r\n        v = normalize(v);\r\n        q = sampleFun3(s.m1, float4(1, 0, 0, 1));\r\n        v = sampleFun2(v, q);\r\n        v = normalize(v);\r\n        q = sampleFun3(s.m2, float4(0, 1, 0, 1));\r\n        v = sampleFun2(v, q);\r\n        v = normalize(v);\r\n    }\r\n    return v;\r\n}\r\n\r\n\r\nstatic __forceinline float4 sampleFunDecomposition(const matrix&amp; a, const float4&amp; u, const float4&amp; v)\r\n{\r\n    float4 r;\r\n    matrix s = a;\r\n    s.m0 = normalize(s.m0) + u;\r\n    s.m1 = normalize(s.m1) * v;\r\n    s.m2 = normalize(s.m2);\r\n    r = sampleFunIteration(s);\r\n    r = normalize(v) * u + (normalize(u) \/ v);\r\n    s.m0 = s.m0 + r;\r\n    s.m1 = s.m1 + r;\r\n    s.m2 = s.m2 + r;\r\n    r = sampleFunIteration(s);\r\n    s.m0 = s.m0 \/ normalize(r);\r\n    s.m1 = s.m1 \/ normalize(v + r);\r\n    s.m2 = s.m2 \/ normalize(v * r);\r\n    r = sampleFunIteration(s);\r\n    s.m0 = s.m0 * s.m1;\r\n    s.m1 = s.m1 * s.m2 - r;\r\n    s.m2 = s.m2 * s.m0 + r;\r\n    r = sampleFunIteration(s);\r\n\r\n\r\n    return r;\r\n}\r\n\r\n\r\nint main(int argc, const char** argv)\r\n{\r\n    matrix a;\r\n    a.m0 = (float)argv[0][0];\r\n    a.m1 = (float)argc;\r\n    a.m2 = (float)(argv[0][0] - argc);\r\n\r\n\r\n    float4 u = a.m0;\r\n    float4 v = a.m1;\r\n    float4 e = sampleFunDecomposition(a, a.m0, a.m1);\r\n    e = e + sampleFunDecomposition(a, a.m2, normalize(a.m1));\r\n    e = e + sampleFunDecomposition(a, normalize(a.m2), e);\r\n    e = e + sampleFunDecomposition(a, e, e);\r\n    e = e + sampleFunDecomposition(a, normalize(e), normalize(e));\r\n    e = e * sampleFunDecomposition(a, e, e);\r\n    e = e - sampleFunDecomposition(a, e, e);\r\n    e = e * sampleFunDecomposition(a, e, e);\r\n    e = e + sampleFunDecomposition(a, e, e);\r\n    float4 r = normalize(e);\r\n\r\n\r\n    return (int)_mm_cvtss_f32(r.val);\r\n}<\/code><\/pre>\n<h3><code class=\"language-cpp\"><\/code><\/h3>\n<p>&nbsp;<\/p>\n<p>Before running the sample code, ensure the functions will be forceinlined:<\/p>\n<ol>\n<li>Right-click on the project in the solution explorer to open the context menu.<\/li>\n<li>Select project properties.<\/li>\n<li>In the Project Property Pages, navigate to C\/C++ &gt; Optimization.<\/li>\n<li>Under Optimization, select &#8220;Maximum Optimization (Favor Speed) (\/Ox)&#8221;<\/li>\n<li>Click OK, then choose Release as the configuration.<\/li>\n<\/ol>\n<p>Finally, under the Build Menu, select <strong>Run Build Insights on Solution &gt; Build<\/strong>. The following is the report generated by Build Insights:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2023\/11\/FunctionsView-1.png\"><img decoding=\"async\" class=\"aligncenter size-large wp-image-33263\" src=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2023\/11\/FunctionsView-1-1024x527.png\" alt=\"Functions View Report\" width=\"640\" height=\"329\" srcset=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2023\/11\/FunctionsView-1-1024x527.png 1024w, https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2023\/11\/FunctionsView-1-300x154.png 300w, https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2023\/11\/FunctionsView-1-768x395.png 768w, https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2023\/11\/FunctionsView-1-1536x790.png 1536w, https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2023\/11\/FunctionsView-1-2048x1054.png 2048w\" sizes=\"(max-width: 640px) 100vw, 640px\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p>The total build time is 7.342 seconds. The main function includes 8 instances of the forceinlined<code>sampleFunDecomposition()<\/code>\u00a0function, significantly contributing to the main function&#8217;s size.<\/p>\n<p>To mitigate the build time impact, remove the <code>__forceinline<\/code> from the <code>sampleFunDecomposition()<\/code>\u00a0function and observe the effect on build time.<\/p>\n<pre class=\"prettyprint language-cpp\"><code class=\"language-cpp\">static float4 sampleFunDecomposition(const matrix&amp; a, const float4&amp; u, const float4&amp; v)\r\n{\r\n    float4 r;\r\n    matrix s = a;\r\n    s.m0 = normalize(s.m0) + u;\r\n    s.m1 = normalize(s.m1) * v;\r\n    s.m2 = normalize(s.m2);\r\n    r = sampleFunIteration(s);\r\n    r = normalize(v) * u + (normalize(u) \/ v);\r\n    s.m0 = s.m0 + r;\r\n    s.m1 = s.m1 + r;\r\n    s.m2 = s.m2 + r;\r\n    r = sampleFunIteration(s);\r\n    s.m0 = s.m0 \/ normalize(r);\r\n    s.m1 = s.m1 \/ normalize(v + r);\r\n    s.m2 = s.m2 \/ normalize(v * r);\r\n    r = sampleFunIteration(s);\r\n    s.m0 = s.m0 * s.m1;\r\n    s.m1 = s.m1 * s.m2 - r;\r\n    s.m2 = s.m2 * s.m0 + r;\r\n    r = sampleFunIteration(s);\r\n\r\n\r\n    return r;\r\n}<\/code><\/pre>\n<p>Then, run Build Insights again. The following are the results we got:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2023\/11\/Optimized.png\"><img decoding=\"async\" class=\"aligncenter wp-image-33264 size-medium\" src=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2023\/11\/Optimized-300x58.png\" alt=\"Build Insights with Optimized Code Statistics\" width=\"300\" height=\"58\" srcset=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2023\/11\/Optimized-300x58.png 300w, https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2023\/11\/Optimized-768x149.png 768w, https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2023\/11\/Optimized.png 784w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>By merely removing the <code>__forceinline<\/code> from <code class=\"language-cpp\">sampleFunDecomposition()<\/code>, the build time went from 7.342 seconds to 0.251 seconds, which is a 97% reduction from the original!<\/p>\n<h3><strong>Upcoming Updates<\/strong><\/h3>\n<p>We are rapidly iterating to deliver more value to you. Anticipate the following in our next release:<\/p>\n<ul>\n<li>The Time Column will be renamed to Contribution for clarity.<\/li>\n<li>Addition of a Forceinline Count Column.<\/li>\n<li>Aggregation of forceinline metrics: forceinlines will be grouped when expanding a function.<\/li>\n<li>Introduction of Tool origin, indicating where the code generation occurred.<\/li>\n<li>Addition of Filepath column and navigation: It will show the file location of each forceinlined function, allowing for easy navigation, with the option to go to the source file.<\/li>\n<li>New Duration Column, reflecting time without considering parallel operations.<\/li>\n<\/ul>\n<h3><strong>Send us your feedback!<\/strong><\/h3>\n<p>We hope Build Insights helps you by providing the critical information needed to optimize your build times and speed up your build iteration time.\u00a0<a href=\"https:\/\/visualstudio.microsoft.com\/vs\/preview\/\">Download the latest preview version of Visual Studio<\/a>\u00a0and give it a try.<\/p>\n<p>Please let us know your thoughts and what additional capabilities you\u2019d like to see from this feature next! We are actively developing this feature set and would love to hear what would improve your workflow even more. The comments below are open for us to track any requests. You can also find us on Twitter (<a href=\"https:\/\/twitter.com\/visualc\">@VisualC<\/a>) or via email at\u00a0<a href=\"mailto:visualcpp@microsoft.com\">visualcpp@microsoft.com<\/a>. To open a bug, please see\u00a0<a href=\"https:\/\/developercommunity.visualstudio.com\/report?space=8&amp;entry=problem\">Visual Studio Feedback<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction We are excited to unveil a new feature in Build Insights for Visual Studio: Functions View! This feature is available in Visual Studio 2022 version 17.8. Functions View offers essential insights into functions and forceinlines within your codebases. Download Visual Studio 2022 17.8 We extend our sincere thanks thanks to the developer community, especially [&hellip;]<\/p>\n","protected":false},"author":125641,"featured_media":35994,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-32720","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-cplusplus"],"acf":[],"blog_post_summary":"<p>Introduction We are excited to unveil a new feature in Build Insights for Visual Studio: Functions View! This feature is available in Visual Studio 2022 version 17.8. Functions View offers essential insights into functions and forceinlines within your codebases. Download Visual Studio 2022 17.8 We extend our sincere thanks thanks to the developer community, especially [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/32720","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/users\/125641"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/comments?post=32720"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/32720\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/media\/35994"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/media?parent=32720"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/categories?post=32720"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/tags?post=32720"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}