VBandi's blog : WP Performancehttp://dotneteers.net/blogs/vbandi/archive/tags/WP+Performance/default.aspxTags: WP PerformanceenCommunityServer 2008 (Build: 30417.1769)Windows Phone Performance – Part 8 of many: Lumia 620 performancehttp://dotneteers.net/blogs/vbandi/archive/2013/03/16/windows-phone-performance-part-7-of-many-lumia-620-performance.aspxSat, 16 Mar 2013 20:43:58 GMT74e06254-0e07-4c08-8611-9f55b924f030:11142vbandi1http://dotneteers.net/blogs/vbandi/rsscomments.aspx?PostID=11142http://dotneteers.net/blogs/vbandi/archive/2013/03/16/windows-phone-performance-part-7-of-many-lumia-620-performance.aspx#comments<p><em>In this post, I’ll take a look at the performance of the Nokia Lumia 620 from a developer’s point of view. This post is part of my <a href="http://dotneteers.net/blogs/vbandi/archive/tags/WP+Performance/default.aspx" target="_blank">Windows Phone Performance series</a>.</em></p> <p><em>HUGE thanks to <a href="http://dotnetbyexample.blogspot.hu/" target="_blank">Joost von Schaik</a> for performing the tests in this article. Since I don’t have access to a Lumia 620, without him, this post would not have been possible.</em></p> <h2></h2> <h2>The Nokia Lumia 620</h2> <p><a href="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/image_5F00_48693FAA.png"><img title="image" style="border-top:0px;border-right:0px;border-bottom:0px;margin:0px;border-left:0px;display:inline;" border="0" alt="image" align="right" src="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/image_5F00_thumb_5F00_4C075A87.png" width="210" height="244" /></a> The 620 is the almost-smallest member of Nokia’s Windows Phone 8 family yet. The 520 is smaller, but not yet available. The 620 is a great phone, and provides a good Windows Phone 8 experience for a fraction of the price of its bigger brothers, such as the <a href="http://dotneteers.net/blogs/vbandi/archive/2013/01/10/windows-phone-performance-part-7-of-many-lumia-820-performance.aspx" target="_blank">820</a> and the <a href="http://dotneteers.net/blogs/vbandi/archive/2012/12/27/windows-phone-performance-part-6-of-many-nokia-lumia-920-performance.aspx" target="_blank">920</a> (both of which we have tested earlier).</p> <p>The 620 has a dual core Snapdragon S4 processor. This is not the same as the ones found in the 920 (MSM8960T) and the 820 (MSM8960) though (both of which run at 1.5GHz). The 620 has an MSM8227, running at 1 GHz, and an Adreno 305 GPU. The screen has 800x480 pixels (same as the 820, but lower than the 920). Another notable difference is that the 620 has 512 MBytes of RAM onboard. While this may affect multitasking and other end-user features, our tests were not impacted by the lower amount of memory.</p> <p>Because of its low price and attractive design, the 620 is expected to sell very well in countries such as India, Chine and Eastern Europe (just like the 610 did).</p> <h2></h2> <h2>Application Loading / CPU Performance</h2> <p>For this test, I am using the same test I used for the other phones, from the second part of this series: <a title="It’s Full of Stars!" href="http://vbandi.dotneteers.net/blogs/vbandi/archive/2012/02/18/windows-phone-performance-part-2-of-many-it-s-full-of-stars.aspx">It’s Full of Stars!</a></p> <table cellspacing="0" cellpadding="0"> <tr> <td><strong>Number of Stars</strong></td> <td><strong>Lumia 620</strong></td> <td><strong>Optimus 7</strong></td> <td><strong>Lumia 800</strong></td> <td><strong>Lumia 920</strong></td> <td><strong>Lumia 820</strong></td> </tr> <tr> <td>100</td> <td>310</td> <td>399</td> <td>347</td> <td>164</td> <td>497</td> </tr> <tr> <td>1000</td> <td>727</td> <td>1133</td> <td>846</td> <td>449</td> <td>539</td> </tr> <tr> <td>2000</td> <td>1119</td> <td>1882</td> <td>1357</td> <td>711</td> <td>723</td> </tr> <tr> <td>5000</td> <td>2425</td> <td>4258</td> <td>3007</td> <td>1557</td> <td>1465</td> </tr> <tr> <td>10000</td> <td>4569</td> <td>8348</td> <td>5792</td> <td>2913</td> <td>2899</td> </tr> <tr> <td>15000</td> <td>6887</td> <td>12183</td> <td>9057</td> <td>4404</td> <td>4349</td> </tr> <tr> <td>20000</td> <td>9206</td> <td>&#160;</td> <td>11646</td> <td>5903</td> <td>5774</td> </tr> <tr> <td>25000</td> <td>11205</td> <td>&#160;</td> <td>&#160;</td> <td>7328</td> <td>7283</td> </tr> <tr> <td>30000</td> <td>13235</td> <td>&#160;</td> <td>&#160;</td> <td>8861</td> <td>8756</td> </tr> <tr> <td>35000</td> <td>15546</td> <td>&#160;</td> <td>&#160;</td> <td>10314</td> <td>10131</td> </tr> <tr> <td>40000</td> <td>17929</td> <td>&#160;</td> <td>&#160;</td> <td>11677</td> <td>11589</td> </tr> </table> <p><a href="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/image_5F00_329F574D.png"><img title="image" style="border-top:0px;border-right:0px;border-bottom:0px;border-left:0px;display:inline;" border="0" alt="image" src="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/image_5F00_thumb_5F00_673FB388.png" width="542" height="359" /></a> </p> <p>We get the expected result – the CPU clock difference between the other WP8 phones (920 and 820) clearly means slower startup and computational times. In fact, if we compensate for the CPU clock, the numbers are pretty much exactly the same. The 620 has no problem beating second generation Windows Phone 7 devices (such as the Lumia 800). The 800 has a single-core and outdated CPU, but runs at a 40% higher speed of 1.4 GHz. If we compare the 620 to the first generation WP7 devices, such as the LG Optimus 7, we get almost 100% performance gain. Moore’s Law in action here…</p> <h2>GPU Performance</h2> <p>To measure the raw CPU performance, once again I used the “Fill Rate Test Sample” from the MSDN article <a href="http://msdn.microsoft.com/en-us/library/ff967560(v=VS.92).aspx">Performance Considerations in Applications for Windows Phone</a>. This test turned out some surprising results!</p> <p>Here are the numbers in table and chart format:</p> <table cellspacing="0" cellpadding="0"> <tr> <td><strong>Rectangles</strong></td> <td><strong>Fill Rate</strong></td> <td><strong>Lumia 620 FPS</strong></td> <td><strong>Lumia 800 FPS</strong></td> <td><strong>Optimus 7 FPS</strong></td> <td><strong>Lumia 920 FPS</strong></td> <td><strong>Lumia 820</strong> FPS</td> </tr> <tr> <td>0</td> <td>0</td> <td>60</td> <td>59</td> <td>50</td> <td>59</td> <td>59</td> </tr> <tr> <td>1</td> <td>1.03</td> <td>60</td> <td>59</td> <td>50</td> <td>59</td> <td>59</td> </tr> <tr> <td>5</td> <td>1.53</td> <td>60</td> <td>59</td> <td>50</td> <td>59</td> <td>59</td> </tr> <tr> <td>10</td> <td>2.15</td> <td>60</td> <td>59</td> <td>50</td> <td>59</td> <td>59</td> </tr> <tr> <td>15</td> <td>2.78</td> <td>60</td> <td>59</td> <td>48</td> <td>59</td> <td>59</td> </tr> <tr> <td>20</td> <td>3.47</td> <td>60</td> <td>59</td> <td>38</td> <td>59</td> <td>59</td> </tr> <tr> <td>25</td> <td>4.02</td> <td>60</td> <td>59</td> <td>34</td> <td>59</td> <td>59</td> </tr> <tr> <td>30</td> <td>4.65</td> <td>60</td> <td>59</td> <td>30</td> <td>59</td> <td>59</td> </tr> <tr> <td>35</td> <td>5.28</td> <td>60</td> <td>59</td> <td>26</td> <td>55</td> <td>59</td> </tr> <tr> <td>40</td> <td>5.9</td> <td>60</td> <td>59</td> <td>23</td> <td>50</td> <td>59</td> </tr> <tr> <td>45</td> <td>6.53</td> <td>60</td> <td>59</td> <td>21</td> <td>45</td> <td>59</td> </tr> <tr> <td>50</td> <td>7.15</td> <td>60</td> <td>59</td> <td>19</td> <td>42</td> <td>59</td> </tr> <tr> <td>55</td> <td>7.78</td> <td>60</td> <td>53</td> <td>17</td> <td>40</td> <td>59</td> </tr> <tr> <td>60</td> <td>8.4</td> <td>60</td> <td>49</td> <td>16</td> <td>36</td> <td>59</td> </tr> <tr> <td>65</td> <td>0.03</td> <td>60</td> <td>45</td> <td>15</td> <td>33</td> <td>59</td> </tr> <tr> <td>70</td> <td>9.65</td> <td>60</td> <td>43</td> <td>14</td> <td>31</td> <td>59</td> </tr> <tr> <td>75</td> <td>10.28</td> <td>60</td> <td>42</td> <td>14</td> <td>30</td> <td>59</td> </tr> <tr> <td>80</td> <td>10.9</td> <td>60</td> <td>40</td> <td>13</td> <td>29</td> <td>59</td> </tr> <tr> <td>85</td> <td>11.53</td> <td>60</td> <td>37</td> <td>12</td> <td>26</td> <td>59</td> </tr> <tr> <td>90</td> <td>12.15</td> <td>58</td> <td>34</td> <td>11</td> <td>25</td> <td>57</td> </tr> <tr> <td>95</td> <td>12.775</td> <td>53</td> <td>33</td> <td>11</td> <td>24</td> <td>54</td> </tr> <tr> <td>100</td> <td>13.4</td> <td>49</td> <td>32</td> <td>10</td> <td>23</td> <td>51</td> </tr> <tr> <td>105</td> <td>14.03</td> <td>45</td> <td>30</td> <td>10</td> <td>22</td> <td>48</td> </tr> <tr> <td>110</td> <td>14.65</td> <td>44</td> <td>30</td> <td>9</td> <td>21</td> <td>47</td> </tr> <tr> <td>120</td> <td>15.9</td> <td>40</td> <td>27</td> <td>9</td> <td>20</td> <td>44</td> </tr> <tr> <td>130</td> <td>17.15</td> <td>40</td> <td>26</td> <td>8</td> <td>18</td> <td>41</td> </tr> <tr> <td>140</td> <td>18.4</td> <td>40</td> <td>24</td> <td>7</td> <td>17</td> <td>39</td> </tr> <tr> <td>150</td> <td>19.65</td> <td>36</td> <td>23</td> <td>7</td> <td>16</td> <td>36</td> </tr> <tr> <td>170</td> <td>22.15</td> <td>33</td> <td>&#160;</td> <td>&#160;</td> <td>&#160;</td> <td>&#160;</td> </tr> <tr> <td>200</td> <td>25.78</td> <td>29</td> <td>&#160;</td> <td>&#160;</td> <td>&#160;</td> <td>&#160;</td> </tr> </table> <p><a href="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/image_5F00_1218179B.png"><img title="image" style="border-top:0px;border-right:0px;border-bottom:0px;border-left:0px;display:inline;" border="0" alt="image" src="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/image_5F00_thumb_5F00_66D38093.png" width="485" height="293" /></a> </p> <p>Barring some measurement inaccuracies, the 620 performed just as good as our current champion, the 820 – even though the SoC runs at 66% speed! I’ve tried to find a reason for this difference, but I couldn’t find a definite answer. It seems like the bottleneck is elsewhere – perhaps the memory bandwidth, the graphics driver or some other architectural component. If you have an idea of why the 620 performs this much better than expected, please share it in the comments.</p> <p>Nevertheless, it seems like developers we won’t have to worry about Fill Rates with the 620. It keeps an impressive 60 fps up until the Fill Rate of 12, which should be more than enough for any application. Even at a Fill Rate of 24, the frame rate is still above the red zone of 30. </p> <h2>Summary</h2> <p>From a developer’s point of view, the 620 is noticeably slower than the other WP8 devices when it comes to raw computing power. However, this speed difference shouldn’t cause much problems if you are sticking with the performance guidelines outlined in the previous parts of this series. Even better, when it comes to Fill Rate, you have nothing to worry about. For Fill Rate optimization, you should still use the Lumia 920. If you are also targeting WP7 devices, the Lumia 610 should be your baseline. The first generation phones are finally becoming rare enough to ignore minor FPS problems on. Which is good news, since it’s often extremely hard to keep the Fill Rate above their FPS drop point of 2.5.</p><div style="clear:both;"></div><img src="http://dotneteers.net/aggbug.aspx?PostID=11142" width="1" height="1">Windows Phone 7WP PerformanceWindows Phone Performance – Part 7 of many: Lumia 820 performancehttp://dotneteers.net/blogs/vbandi/archive/2013/01/10/windows-phone-performance-part-7-of-many-lumia-820-performance.aspxThu, 10 Jan 2013 11:17:54 GMT74e06254-0e07-4c08-8611-9f55b924f030:6500vbandi4http://dotneteers.net/blogs/vbandi/rsscomments.aspx?PostID=6500http://dotneteers.net/blogs/vbandi/archive/2013/01/10/windows-phone-performance-part-7-of-many-lumia-820-performance.aspx#comments<p><em>In this post, I’ll take a look at the performance of the Nokia Lumia 820 from a developer’s point of view. </em><em>This post is part of my <a href="http://dotneteers.net/blogs/vbandi/archive/tags/WP+Performance/default.aspx">Windows Phone performance series</a>. </em></p> <p><em>HUGE thanks to <a href="http://sorokoletov.com/" target="_blank">Alex Sorokoletov</a> for performing the tests in this article. Since I didn’t have access to a Lumia 820, without him, this post would not have been possible.</em></p> <h2>The Nokia Lumia 820</h2> <p>The little brother of the flagship Nokia Lumia 920, the 820 has nothing to be ashamed of when it comes to performance. Actually, the 820 has the same dual-core Snapdragon S4 processor as the 920, running at the same 1.5GHz speed. From a developer’s perspective, the big difference is the screen – while the 920 has 1280x768 pixels, the 820 keeps the modest 800x480 pixel resolution of Windows Phone 7. Most of the differences between the 920 and the 820 have to do with how the 920 has to work with 2.5 as much pixels as the 820. </p> <p>It is worth noting that the<strike> 820 only has</strike> minimum requirement for 800x480 Windows Phone devices is 512MByte RAM, while the 920 has twice as much. This also boils down to the difference in screen pixels – apps on the the 920 need more RAM simply to decode the high resolution bitmaps and keep them in memory. <br /><strong>Update: t</strong>he Lumia 820 has 1G RAM</p> <p>Let’s see how the 820 performs in our little tests!</p> <h2>Application Loading / CPU performance</h2> <p>For this one, I am using the old artificial test from the second part of this series (<a href="http://vbandi.dotneteers.net/blogs/vbandi/archive/2012/02/18/windows-phone-performance-part-2-of-many-it-s-full-of-stars.aspx">It’s Full of Stars!</a>). </p> <p>&#160;</p> <table cellspacing="0" cellpadding="0"> <tr> <td><strong>Number of Stars</strong></td> <td><strong>Lumia 610</strong></td> <td><strong>Optimus 7</strong></td> <td><strong>Lumia 800</strong></td> <td><strong>Lumia 920</strong></td> <td><strong>Lumia 820</strong></td> </tr> <tr> <td>100</td> <td>624</td> <td>399</td> <td>347</td> <td>164</td> <td>497</td> </tr> <tr> <td>1000</td> <td>1325</td> <td>1133</td> <td>846</td> <td>449</td> <td>539</td> </tr> <tr> <td>2000</td> <td>2106</td> <td>1882</td> <td>1357</td> <td>711</td> <td>723</td> </tr> <tr> <td>5000</td> <td>4303</td> <td>4258</td> <td>3007</td> <td>1557</td> <td>1465</td> </tr> <tr> <td>10000</td> <td>8430</td> <td>8348</td> <td>5792</td> <td>2913</td> <td>2899</td> </tr> <tr> <td>15000</td> <td>12401</td> <td>12183</td> <td>9057</td> <td>4404</td> <td>4349</td> </tr> <tr> <td>20000</td> <td>17205</td> <td>&#160;</td> <td>11646</td> <td>5903</td> <td>5774</td> </tr> <tr> <td>25000</td> <td>&#160;</td> <td>&#160;</td> <td>&#160;</td> <td>7328</td> <td>7283</td> </tr> <tr> <td>30000</td> <td>&#160;</td> <td>&#160;</td> <td>&#160;</td> <td>8861</td> <td>8756</td> </tr> <tr> <td>35000</td> <td>&#160;</td> <td>&#160;</td> <td>&#160;</td> <td>10314</td> <td>10131</td> </tr> <tr> <td>40000</td> <td>&#160;</td> <td>&#160;</td> <td>&#160;</td> <td>11677</td> <td>11589</td> </tr> </table> <p><a href="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/image_5F00_2C2565E7.png"><img title="image" border="0" alt="image" src="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/image_5F00_thumb_5F00_4BD43FAF.png" width="542" height="359" /></a></p> <p>&#160;</p> <p>With Compile in the Cloud being a general Windows Phone 8 feature, the 820 should start applications just as fast as the 920. The first two launches show a bit different picture though, the reasons of which is not entirely clear. Alex performed multiple measurements for each pass, but the 100 star test consistently returned a slower startup time. Regardless of this difference, you can see that the 820 performed roughly as well as the 920 did (almost completely hiding the 920’s line in the chart), even though the later one had to render much more physical pixels.</p> <h2>GPU Performance</h2> <p>To measure the raw CPU performance, once again I used the “Fill Rate Test Sample” from the MSDN article <a href="http://msdn.microsoft.com/en-us/library/ff967560(v=VS.92).aspx">Performance Considerations in Applications for Windows Phone</a>. Here are the numbers in table and chart format:</p> <table cellspacing="0" cellpadding="0"> <tr> <td>Rectangles</td> <td>Fill Rate</td> <td>Lumia 610 FPS</td> <td>Lumia 800 FPS</td> <td>Optimus 7 FPS</td> <td>Lumia 920 FPS</td> <td>Lumia 820 FPS</td> </tr> <tr> <td>0</td> <td>0.9</td> <td>59</td> <td>59</td> <td>50</td> <td>59</td> <td>59</td> </tr> <tr> <td>1</td> <td>1.05</td> <td>59</td> <td>59</td> <td>50</td> <td>59</td> <td>59</td> </tr> <tr> <td>5</td> <td>1.56</td> <td>59</td> <td>59</td> <td>50</td> <td>59</td> <td>59</td> </tr> <tr> <td>10</td> <td>2.19</td> <td>59</td> <td>59</td> <td>50</td> <td>59</td> <td>59</td> </tr> <tr> <td>15</td> <td>2.83</td> <td>59</td> <td>59</td> <td>48</td> <td>59</td> <td>59</td> </tr> <tr> <td>20</td> <td>3.47</td> <td>59</td> <td>59</td> <td>38</td> <td>59</td> <td>59</td> </tr> <tr> <td>25</td> <td>4.1</td> <td>54</td> <td>59</td> <td>34</td> <td>59</td> <td>59</td> </tr> <tr> <td>30</td> <td>4.74</td> <td>48</td> <td>59</td> <td>30</td> <td>59</td> <td>59</td> </tr> <tr> <td>35</td> <td>5.37</td> <td>45</td> <td>59</td> <td>26</td> <td>55</td> <td>59</td> </tr> <tr> <td>40</td> <td>6.01</td> <td>41</td> <td>59</td> <td>23</td> <td>50</td> <td>59</td> </tr> <tr> <td>45</td> <td>6.65</td> <td>38</td> <td>59</td> <td>21</td> <td>45</td> <td>59</td> </tr> <tr> <td>50</td> <td>7.28</td> <td>35</td> <td>59</td> <td>19</td> <td>42</td> <td>59</td> </tr> <tr> <td>55</td> <td>7.92</td> <td>32</td> <td>53</td> <td>17</td> <td>40</td> <td>59</td> </tr> <tr> <td>60</td> <td>8.56</td> <td>29</td> <td>49</td> <td>16</td> <td>36</td> <td>59</td> </tr> <tr> <td>65</td> <td>9.19</td> <td>28</td> <td>45</td> <td>15</td> <td>33</td> <td>59</td> </tr> <tr> <td>70</td> <td>9.83</td> <td>27</td> <td>43</td> <td>14</td> <td>31</td> <td>59</td> </tr> <tr> <td>75</td> <td>10.46</td> <td>25</td> <td>42</td> <td>14</td> <td>30</td> <td>59</td> </tr> <tr> <td>80</td> <td>11.1</td> <td>24</td> <td>40</td> <td>13</td> <td>29</td> <td>59</td> </tr> <tr> <td>85</td> <td>11.74</td> <td>22</td> <td>37</td> <td>12</td> <td>26</td> <td>59</td> </tr> <tr> <td>90</td> <td>12.37</td> <td>21</td> <td>34</td> <td>11</td> <td>25</td> <td>57</td> </tr> <tr> <td>95</td> <td>13</td> <td>20</td> <td>33</td> <td>11</td> <td>24</td> <td>54</td> </tr> <tr> <td>100</td> <td>13.6</td> <td>19</td> <td>32</td> <td>10</td> <td>23</td> <td>51</td> </tr> <tr> <td>105</td> <td>14.28</td> <td>18</td> <td>30</td> <td>10</td> <td>22</td> <td>48</td> </tr> <tr> <td>110</td> <td>14.92</td> <td>17</td> <td>30</td> <td>9</td> <td>21</td> <td>47</td> </tr> <tr> <td>120</td> <td>16.19</td> <td>16</td> <td>27</td> <td>9</td> <td>20</td> <td>44</td> </tr> <tr> <td>130</td> <td>17.46</td> <td>15</td> <td>26</td> <td>8</td> <td>18</td> <td>41</td> </tr> <tr> <td>140</td> <td>18.73</td> <td>14</td> <td>24</td> <td>7</td> <td>17</td> <td>39</td> </tr> <tr> <td>150</td> <td>20</td> <td>13</td> <td>23</td> <td>7</td> <td>16</td> <td>36</td> </tr> </table> <p><a href="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/image_5F00_76ACA3C1.png"><img title="image" style="border-left-width:0px;border-right-width:0px;border-bottom-width:0px;display:inline;border-top-width:0px;" border="0" alt="image" src="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/image_5F00_thumb_5F00_4B680CBA.png" width="485" height="293" /></a> </p> <p>The Lumia 820 is clearly the top performer here – no wonder, since it has much less pixels to work with than the 920. The 820 keeps a solid 60 FPS up until a Fill Rate of 12, and still doesn’t drop below an acceptable 30 with a Fill Rate of 150. This really shows how the Snapdragon S4’s GPU may even be a bit too powerful for the phone (at least when it comes to Silverlight applications). It can compose 2.5 – 3 times as many full-screen layers as on the 920 before the first signs of lags even show. Not surprisingly, this is the same multiplier as the number of pixels there are between the two phones. Fill Rate is about number of pixels after all.</p> <h2></h2> <p></p> <h2>Summary</h2> <p>In CPU, the two Windows Phone 8 Lumia phones perform similarly. However, when it comes to the GPU, the 820 feels like a race car engine in a common vehicle. </p> <p>When developing Windows Phone 8 applications and testing on the Lumia 820, you have to keep in mind that high-resolution phones do not tolerate Fill Rates above 4.5 or so. Even though your applications may keep a consistently smooth animation at a Fill Rate of 6 on the 820, other WP phones will struggle. So, keep your <a href="http://dotneteers.net/blogs/vbandi/archive/2012/03/14/windows-phone-performance-part-3-of-many-tie-fighters-and-drunk-spaceship-captains.aspx" target="_blank">Frame Rate Counters</a> turned on. Fortunately, it is not hard to keep the Fill Rate below 5 – we are in a much better situation than what we had with the first generation Windows Phones, where the a value of 2.5 already caused problems, and a lot of time went into making sure we kept the Fill Rate below that level.</p><div style="clear:both;"></div><img src="http://dotneteers.net/aggbug.aspx?PostID=6500" width="1" height="1">WP PerformanceWindows Phone performance – Part 6 of many: Nokia Lumia 920 performancehttp://dotneteers.net/blogs/vbandi/archive/2012/12/27/windows-phone-performance-part-6-of-many-nokia-lumia-920-performance.aspxThu, 27 Dec 2012 12:37:17 GMT74e06254-0e07-4c08-8611-9f55b924f030:6483vbandi4http://dotneteers.net/blogs/vbandi/rsscomments.aspx?PostID=6483http://dotneteers.net/blogs/vbandi/archive/2012/12/27/windows-phone-performance-part-6-of-many-nokia-lumia-920-performance.aspx#comments<p><em>In this post, I’ll take a look at the performance of the Nokia Lumia 920 from a developer’s point of view. </em><em>This post is part of my <a href="http://dotneteers.net/blogs/vbandi/archive/tags/WP+Performance/default.aspx" target="_blank">Windows Phone performance series</a>. </em></p> <h2><em></em></h2> <h1>The Nokia Lumia 920</h1> <p>As Nokia’s flagship Windows Phone device, the Lumia 920 is a beast. Both in size and performance, the phone is great. In fact, the very first thing I noticed as a Windows Phone 7 user (apart from the new Start Screen) was how quickly the applications launched and how well they performed. </p> <p>The 920 has a screen resolution of 1280x768 (983,040 pixels). This is more than 2.5 times as many as the standard resolution of the Windows Phone 7 devices – 800x480 (384,000 pixels). Other Windows Phone 8 devices can have a resolution of 1280x720 (almost the same as the 920, but a different aspect ratio) or 800x480. The additional pixel count requires a faster CPU to render the textures and a faster GPU to move the textures around. Fortunately, both of these are taken care of with the dual-core 1.5GHz Snapdragon S4 SOC. Also, since images in your application should contain a bigger number of pixels to remain sharp, the screen pixels mean that more memory is used by the applications. Because of this, you won’t see an 1280p WIndows Phone 8 device with less than 1G RAM. </p> <p>In the <a href="http://dotneteers.net/blogs/vbandi/archive/2012/05/31/windows-phone-performance-part-5-of-many-a-developer-s-look-at-the-nokia-lumia-610.aspx" target="_blank">previous post of this series</a>, I compared the LG Optimus 7 (a first generation WP7 device), the Nokia Lumia 800 (a second generation WP7 device) and the Lumia 610 (a low-end second generation phone). Let’s add the 920 to the mix, and see how it fares!</p> <h1></h1> <h2>Application Loading / CPU performance</h2> <p>With Windows Phone 7, application load times were the result of two factors – the Just-In-Time Compilation of the dlls, and the calculations needed to display the first screen of your app. With the apps growing bigger as more and bigger dlls were included in the XAP, whatever you did, a lot of them had to be JIT-ted just to get the first line of your actual code executed.</p> <p>Things have dramatically changed with Windows Phone 8. Thanks to the faster, dual-core processor, but most importantly, to the cloud compilation infrastructure, Silverlight apps can now start up almost as fast as the first party native apps. Cloud Compilation happens when you deploy your app into the Store, and makes 99% of the work of the Just-in-time Compiler unnecessary. With Windows Phone 7, application load times were mostly the result of the apps growing bigger as more and bigger dlls were included in the XAP. Whatever you did, a lot of them had to be JIT-ted just to get the first screen up. You can learn more details about the Cloud Compilation in the Build talk “<a href="http://channel9.msdn.com/Events/Build/2012/3-005">Deep Dive into the Kernel of .NET on Windows Phone 8</a>”.</p> <div id="scid:5737277B-5D6D-4f48-ABFC-DD9C333F4C5D:97f00f45-f5d2-4c15-9404-31a62084b7bb" class="wlWriterEditableSmartContent" style="float:none;padding-bottom:0px;padding-top:0px;padding-left:0px;margin:0px;display:inline;padding-right:0px;"><div><object width="425" height="355"><param name="movie" value="http://www.youtube.com/v/c6LsB3XSsVs&amp;hl=en"></param><embed src="http://www.youtube.com/v/c6LsB3XSsVs&amp;hl=en" type="application/x-shockwave-flash" width="425" height="355"></embed></object></div></div> <p><em>The magic of Compile in the Cloud – rowi startup time vs the People Hub.</em></p> <p>With the JIT compilation out of the way, let’s see how the phone deals with a lot of calculations at startup. For this, I will summon my old artificial test from the second part of this series (<a href="http://vbandi.dotneteers.net/blogs/vbandi/archive/2012/02/18/windows-phone-performance-part-2-of-many-it-s-full-of-stars.aspx" target="_blank">It’s Full of Stars!</a>). Please click on the link to refresh your memory, I’ll wait here.</p> <p>Let’s look at the numbers. The first column of the table shows how many stars (small ellipses) are drawn, and the other columns show the number of milliseconds it took to launch the application. The stars are drawn on the UI thread at startup, so this drawing delays the startup time of the app.</p> <table cellspacing="0" cellpadding="0"> <tr> <td><strong>Number of Stars</strong></td> <td><strong>Lumia 610</strong></td> <td><strong>Optimus 7</strong></td> <td><strong>Lumia 800</strong></td> <td><strong>Lumia 920</strong></td> </tr> <tr> <td>100</td> <td>624</td> <td>399</td> <td>347</td> <td>164</td> </tr> <tr> <td>1000</td> <td>1325</td> <td>1133</td> <td>846</td> <td>449</td> </tr> <tr> <td>2000</td> <td>2106</td> <td>1882</td> <td>1357</td> <td>711</td> </tr> <tr> <td>5000</td> <td>4303</td> <td>4258</td> <td>3007</td> <td>1557</td> </tr> <tr> <td>10000</td> <td>8430</td> <td>8348</td> <td>5792</td> <td>2913</td> </tr> <tr> <td>15000</td> <td>12401</td> <td>12183</td> <td>9057</td> <td>4404</td> </tr> <tr> <td>20000</td> <td>17205</td> <td>&#160;</td> <td>11646</td> <td>5903</td> </tr> <tr> <td>25000</td> <td>&#160;</td> <td>&#160;</td> <td>&#160;</td> <td>7328</td> </tr> <tr> <td>30000</td> <td>&#160;</td> <td>&#160;</td> <td>&#160;</td> <td>8861</td> </tr> <tr> <td>35000</td> <td>&#160;</td> <td>&#160;</td> <td>&#160;</td> <td>10314</td> </tr> <tr> <td>40000</td> <td>&#160;</td> <td>&#160;</td> <td>&#160;</td> <td>11677</td> </tr> </table> <p></p> <p>Here is it in a chart form:</p> <p><a href="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/image_5F00_631787B2.png"><img title="image" style="border-top:0px;border-right:0px;border-bottom:0px;border-left:0px;display:inline;" border="0" alt="image" src="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/image_5F00_thumb_5F00_02C6617B.png" width="542" height="359" /></a> </p> <p>As you can see, the 920 kicks the rear end of every WP7 phone – even the fastest Lumia 800 is beat by a factor of 2, despite the much larger number of pixels to deal with. Not bad! </p> <p>You will also experience this difference when navigating between pages of the application. The layout and render cycle is much faster, resulting in a better navigation experience. </p> <h2>GPU Performance</h2> <p>To measure the raw CPU performance, I used the “Fill Rate Test Sample” from the MSDN article <a href="http://msdn.microsoft.com/en-us/library/ff967560(v=VS.92).aspx">Performance Considerations in Applications for Windows Phone</a>. This does not test things like shaders, perspective transformations, etc – but it is a good first indicator. I gradually increased the number of rectangles on the screen, which in turn increased the fill rate. As we saw in part 4 of this series, <a href="http://www.dotneteers.net/blogs/vbandi/archive/2012/03/22/windows-phone-performance-part-4-of-many-the-power-of-the-gpu.aspx">The Power of the GPU</a>, Fill Rate is an important measurement for how much work the GPU has to do, and a high Fill Rate makes the FPS (frame per seconds) drop. Without further ado, here are the results in table and chart format:</p> <table cellspacing="0" cellpadding="0"> <tr> <td><strong>Rectangles</strong></td> <td><strong>Fill Rate</strong></td> <td><strong>Lumia 610 FPS</strong></td> <td><strong>Lumia 800 FPS</strong></td> <td><strong>Optimus 7 FPS</strong></td> <td><strong>Lumia 920 FPS</strong></td> </tr> <tr> <td>0</td> <td>0.9</td> <td>59</td> <td>59</td> <td>50</td> <td>59</td> </tr> <tr> <td>1</td> <td>1.05</td> <td>59</td> <td>59</td> <td>50</td> <td>59</td> </tr> <tr> <td>5</td> <td>1.56</td> <td>59</td> <td>59</td> <td>50</td> <td>59</td> </tr> <tr> <td>10</td> <td>2.19</td> <td>59</td> <td>59</td> <td>50</td> <td>59</td> </tr> <tr> <td>15</td> <td>2.83</td> <td>59</td> <td>59</td> <td>48</td> <td>59</td> </tr> <tr> <td>20</td> <td>3.47</td> <td>59</td> <td>59</td> <td>38</td> <td>59</td> </tr> <tr> <td>25</td> <td>4.1</td> <td>54</td> <td>59</td> <td>34</td> <td>59</td> </tr> <tr> <td>30</td> <td>4.74</td> <td>48</td> <td>59</td> <td>30</td> <td>59</td> </tr> <tr> <td>35</td> <td>5.37</td> <td>45</td> <td>59</td> <td>26</td> <td>55</td> </tr> <tr> <td>40</td> <td>6.01</td> <td>41</td> <td>59</td> <td>23</td> <td>50</td> </tr> <tr> <td>45</td> <td>6.65</td> <td>38</td> <td>59</td> <td>21</td> <td>45</td> </tr> <tr> <td>50</td> <td>7.28</td> <td>35</td> <td>59</td> <td>19</td> <td>42</td> </tr> <tr> <td>55</td> <td>7.92</td> <td>32</td> <td>53</td> <td>17</td> <td>40</td> </tr> <tr> <td>60</td> <td>8.56</td> <td>29</td> <td>49</td> <td>16</td> <td>36</td> </tr> <tr> <td>65</td> <td>9.19</td> <td>28</td> <td>45</td> <td>15</td> <td>33</td> </tr> <tr> <td>70</td> <td>9.83</td> <td>27</td> <td>43</td> <td>14</td> <td>31</td> </tr> <tr> <td>75</td> <td>10.46</td> <td>25</td> <td>42</td> <td>14</td> <td>30</td> </tr> <tr> <td>80</td> <td>11.1</td> <td>24</td> <td>40</td> <td>13</td> <td>29</td> </tr> <tr> <td>85</td> <td>11.74</td> <td>22</td> <td>37</td> <td>12</td> <td>26</td> </tr> <tr> <td>90</td> <td>12.37</td> <td>21</td> <td>34</td> <td>11</td> <td>25</td> </tr> <tr> <td>95</td> <td>13</td> <td>20</td> <td>33</td> <td>11</td> <td>24</td> </tr> <tr> <td>100</td> <td>13.6</td> <td>19</td> <td>32</td> <td>10</td> <td>23</td> </tr> <tr> <td>105</td> <td>14.28</td> <td>18</td> <td>30</td> <td>10</td> <td>22</td> </tr> <tr> <td>110</td> <td>14.92</td> <td>17</td> <td>30</td> <td>9</td> <td>21</td> </tr> <tr> <td>120</td> <td>16.19</td> <td>16</td> <td>27</td> <td>9</td> <td>20</td> </tr> <tr> <td>130</td> <td>17.46</td> <td>15</td> <td>26</td> <td>8</td> <td>18</td> </tr> <tr> <td>140</td> <td>18.73</td> <td>14</td> <td>24</td> <td>7</td> <td>17</td> </tr> <tr> <td>150</td> <td>20</td> <td>13</td> <td>23</td> <td>7</td> <td>16</td> </tr> </table> <p>&#160;</p> <p><a href="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/image_5F00_5B8C1845.png"><img title="image" style="border-top:0px;border-right:0px;border-bottom:0px;border-left:0px;display:inline;" border="0" alt="image" src="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/image_5F00_thumb_5F00_1B55FECB.png" width="485" height="293" /></a></p> <p>In this test, the Lumia 800 is still better than the 920. The reason for that is the sheer number of pixels the GPU has to deal with – the 920 has 2.5 times as many pixels as the Lumia 800. On the 920, the frame rates start to drop around a fill rate of 5, while the 800 can still push pixels at 60 fps up until a fill rate of 7.5. So, what does it mean for your application? It means that as long as you have less than 5 (screen-sized) layers in your app (e.g. background picture, darkening layer, lots of text over other images, etc), you will be fine, the scrolling will not become jumpy. Frankly, it is hard to think how one would exhaust the Fill Rate of 4 in a normal Silverlight application. The low-end 610 can handle a Fill Rate of 4 easily, only the first generation devices will have problems with it.</p> <h2></h2> <h2>Summary</h2> <p>The Lumia 920 launches apps and navigates between screens much faster, and performs as smooth as we became used to with Windows Phone – despite the much higher pixel count. Overall, applications feel much more snappier, and finally performance parity between native apps and Silverlight apps can be acheved. I expect similar performance from the other HD phones, such as the HTC 8X or the Samsung Ativ. 800x480 devices may perform even better in the Fill Rate test, but I couldn’t measure it – if I get my hands on such a phone, I will write another blog post.</p><div style="clear:both;"></div><img src="http://dotneteers.net/aggbug.aspx?PostID=6483" width="1" height="1">WP PerformanceWindows Phone Performance - Part 5 of many: A Developer’s look at the Nokia Lumia 610http://dotneteers.net/blogs/vbandi/archive/2012/05/31/windows-phone-performance-part-5-of-many-a-developer-s-look-at-the-nokia-lumia-610.aspxThu, 31 May 2012 12:31:40 GMT74e06254-0e07-4c08-8611-9f55b924f030:6118vbandi11http://dotneteers.net/blogs/vbandi/rsscomments.aspx?PostID=6118http://dotneteers.net/blogs/vbandi/archive/2012/05/31/windows-phone-performance-part-5-of-many-a-developer-s-look-at-the-nokia-lumia-610.aspx#comments<p><em>The plan for part 5 was to continue my <a href="http://dotneteers.net/blogs/vbandi/archive/tags/WP+Performance/default.aspx" target="_blank">WP Performance series</a> with a discussion of List performance. However – as it usually happens - <strong>Life </strong>has came and changed the plan. First, Oren Nachman published a great article on The Windows Phone Developer Blog called “</em><a href="http://windowsteamblog.com/windows_phone/b/wpdev/archive/2012/05/16/listbox-why-art-thou-blanking.aspx" target="_blank"><em>Listbox, Why Art Thou Blanking</em></a><em>”, and I don&#39;t really have too much to add to what he wrote. But also, I happened to get a Nokia Lumia 610 phone to test some of the applications we are working on. The 610 (and other, so-called Tango devices) will have a big impact on the lives of Windows Phone developers, but most of have never seen one first hand. I cannot give you one, but I am trying to do the next best thing: I will share experiences with the device and the results of some measurements that I performed so that you can get a feel for the performance characteristics.</em></p> <h2>The Nokia Lumia 610</h2> <p>The Lumia 610 is the first “Tango” device. Tango is the codename for the Windows Phone 7.5 Refresh (build 7.10.8773.98), but you will not catch a Microsoftee call it Tango officially. As an OS update, Tango only brings a handful of small features to Windows Phone. The big change is that Tango has been optimized for phones that have as little as 256 MBytes of RAM available. And that is exactly what the Lumia 610 has. The other notable difference (from a developer’s point of view) is that the 610 has an 800 MHz CPU (the first generation devices had 1GHz, and most of the second generation phones have a 1.4-1.5 GHz CPU).</p> <p><a href="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/WP_5F00_000433_5F00_09C05986.jpg"><img style="background-image:none;border-bottom:0px;border-left:0px;margin:0px 8px 0px 0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="WP_000433" border="0" alt="WP_000433" src="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/WP_5F00_000433_5F00_thumb_5F00_3C43B6F8.jpg" width="265" height="354" /></a> <br /><em>The Nokia Lumia 610</em></p> <p>The Lumia 610 is a very good-looking device – especially the black-white combination that you can see above. It looks better than the much more capable Lumia 710. The Tango OS also performs nicely – you can barely say that the OS runs on a low-specs device, as long as you are using the native features of the operating system. The looks and low price, great in-store performance (where you mostly play with the OS) will probably make it a hit among those who are looking to enter the world of smartphones. </p> <p>Things change dramatically when you start third party applications. At this point, you will notice that some applications take forever to load, and for more complicated apps, you will experience glitchy scrollings, blankings, slow response time and even occasional freezes for a second.</p> <h2></h2> <h2>Application Loading / CPU performance</h2> <p>In the second part of this series (<a href="http://dotneteers.net/blogs/vbandi/archive/2012/02/18/windows-phone-performance-part-2-of-many-it-s-full-of-stars.aspx" target="_blank">It&#39;s Full of Stars!</a>), I dealt with application startup times. Let’s see how three phones measure up in this test: the Lumia 610, the LG Optimus 7 and the Lumia 800.</p> <p>I tested the star drawing app on all devices. The LG Optimus 7 is a decent first generation Windows Phone, with 1GHz CPU. The Lumia 800 is a second generation device, with 1.4GHz CPU. Both of these have 512 MBytes of RAM. As I mentioned before, the Lumia 610 has an 800 MHz CPU with 256Mbyte RAM. Just for kicks, I also included the values measured on the Emulator.</p> <p>The first column of the table shows how many stars (small ellipses) are drawn, and the other columns show the number of milliseconds it took to launch the application. The stars are drawn on the UI thread at startup, so this drawing delays the startup time of the app.</p> <p>&#160;</p> <p><a href="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/image_5F00_2679CE9B.png"><img style="background-image:none;border-bottom:0px;border-left:0px;margin:0px 8px 0px 0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/image_5F00_thumb_5F00_2D2CD81E.png" width="395" height="180" /></a> <br /><a href="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/image_5F00_1A77DE67.png"><img style="background-image:none;border-bottom:0px;border-left:0px;margin:0px 8px 0px 0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/image_5F00_thumb_5F00_3A26B82F.png" width="417" height="249" /></a><em> <br />Silverlight Layout and Ellipse rendering performance on the Nokia Lumia 610, Nokia Lumia 800 and the LG Optimus 7.</em></p> <p>&#160;</p> <p>The results are surprising, but clearly show how efficient the CPU in the Lumia 610 is. Despite the 20% lower CPU clock, the Lumia 610 could easily match the performance of the LG Optimus 7. It could even draw 20,000 stars, which the Optimus 7 couldn’t finish in 20 seconds, so the OS killed the app!</p> <p>This is of course by no means a comprehensive test of the CPU. But it is a fairly good indicator on what you can expect from the Lumia 610 in Silverlight – the test app exercises the layout and rendering subsystems of Silverlight, which are key to any application.</p> <h2>GPU Performance</h2> <p>To measure the raw CPU performance, I used the “Fill Rate Test Sample” from the MSDN article <a href="http://msdn.microsoft.com/en-us/library/ff967560(v=VS.92).aspx" target="_blank">Performance Considerations in Applications for Windows Phone</a>. This does not test things like shaders, perspective transformations, etc – but it is a good first indicator. I gradually increased the number of rectangles on the screen, which in turn increased the fill rate. As we saw in part 4 of this series, <a href="http://www.dotneteers.net/blogs/vbandi/archive/2012/03/22/windows-phone-performance-part-4-of-many-the-power-of-the-gpu.aspx" target="_blank">The Power of the GPU</a>, Fill Rate is an important measurement for how much work the GPU has to do, and a high Fill Rate makes the FPS (frame per seconds) drop. Without further ado, here are the results in table and chart format:</p> <p><a href="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/image_5F00_322F15CD.png"><img style="background-image:none;border-bottom:0px;border-left:0px;margin:0px 8px 0px 0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/image_5F00_thumb_5F00_17EEACA9.png" width="526" height="667" /></a></p> <p><a href="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/image_5F00_490DE749.png"><img style="background-image:none;border-bottom:0px;border-left:0px;margin:0px 8px 0px 0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/image_5F00_thumb_5F00_21D39E14.png" width="524" height="315" /></a></p> <p><em>Fill Rate vs FPS on the Nokia Lumia 610, Nokia Lumia 800 and the LG Optimus 7</em></p> <p>As you can see, the Lumia 610 not just matches, but seriously outperforms the first generation Optimus 7, delivering almost twice as many frames per second under heavy load! The Lumia 800 has 75% higher CPU and GPU speed than the 610, and it performs accordingly. </p> <p><strong>The FPS starts to drop at the Fill Rate of only 2.5 for the Optimus 7</strong> (which is tuned to a maximum frame rate of 50 instead of the usual 60). At this point, the list scrolling becomes somewhat choppy – it begins to jump a little bit every second or so, while remaining completely smooth in between. This is a very low value – it barely gives you enough space to put a background image and a full screen of information on top of it. E.g. if you have a Panorama app where you want to put a semi-transparent background behind your content, you are already at the edge.<strong> The first cutoff points are much further for the 610 – at a Fill Rate of 4</strong>. This means that the 610 can manipulate 1.5 more screens worth of pixels without any visible glitch. Of course, <strong>the Lumia 800 wins here again, which can almost go up until a Fill Rate of 8</strong> before the first signs of strain start to show.</p> <p><strong>The pain point (where the frame rate drops below 30 FPS) comes way too early on the Optimus 7 – at a Fill Rate of 5</strong>, we are already in the red zone. The 610 can handle 70% more pixels before dropping below 30 FPS, at a Fill Rate of 8.5, while the 800 can soar up to a Fill Rate of 15. </p> <h2>Memory</h2> <p>So, the Lumia 610 CPU is on par with first generation devices, and the GPU is much better. Why did I say then that the performance of the Lumia 610 is not perfect? It all comes down to lack of memory.</p> <p>Microsoft has done an awesome job shoehorning the Windows Phone 7.5 Mango OS into 256Mbytes. The only feature they had to remove are the background tasks, and some media codecs (see the details at <a href="http://windowsteamblog.com/windows_phone/b/wpdev/archive/2012/04/17/handle-feature-reductions.aspx" target="_blank">Handle Feature Reductions</a>). But while apps on 512Mbyte phones have a lot of memory to play with, apps on 256 MByte phones only get 60 MBytes. Tango improved virtual memory (paging), which means that your application still can use up to 90 MBytes of memory, only the data above 60 MBytes gets swapped out. When this happens between two screens, all the user sees is some delay between the screens. But when it happens while you are still on one screen, the app seems to freeze and does not react to user input. This usually takes about a second, which is more than enough to cause frustration in the user. </p> <p>There are some great posts by Mike Battista on <a href="http://windowsteamblog.com/windows_phone/b/wpdev/archive/2012/03/07/optimizing-apps-for-lower-cost-devices.aspx" target="_blank">Optimizing Apps for Lower Cost Devices</a> that cover what you can do to help this situation. You can get to a fairly decently performing app following his directions. However, if you are using things like the WebBrowserControl or the BingMaps control (and can’t replace them with a call to the appropriate OS task), you are out of luck. No matter what you do, these controls take up too much memory. For example, a simple app only with only a WebBrowserControl can easily consume as much as 50-52 MBytes of RAM, which doesn’t leave much space until the swapping starts to happen.</p> <p><a href="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/WP_5F00_000441_5F00_754A6E2D.jpg"><img style="background-image:none;border-bottom:0px;border-left:0px;margin:0px 8px 0px 0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="WP_000441" border="0" alt="WP_000441" src="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/WP_5F00_000441_5F00_thumb_5F00_1D99A082.jpg" width="290" height="387" /></a><em> <br />Lumia 610 loading a complicated web page in a simple app, occupying 56 MBytes of RAM (which later goes down to 42) out of the available 60.</em></p> <p>To see what the low memory means for a more complex app that uses the WebBrowserControl, check out this video. Note, that I do not load anything beyond a basic text file into the browser – if I did, the 610 would load up unbearably slow.</p> <div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;" id="scid:5737277B-5D6D-4f48-ABFC-DD9C333F4C5D:d354a50e-e410-465d-b5f1-87918f95cb92" class="wlWriterEditableSmartContent"><div><object width="448" height="252"><param name="movie" value="http://www.youtube.com/v/bNmV_rmxn3I?hl=en&amp;hd=1"></param><embed src="http://www.youtube.com/v/bNmV_rmxn3I?hl=en&amp;hd=1" type="application/x-shockwave-flash" width="448" height="252"></embed></object></div><div style="width:448px;clear:both;font-size:.8em;">Launching SurfCube on LG Optimus 7 and Nokia Lumia 610</div></div> <h2>Summary</h2> <p>The Lumia 610 is a surprisingly powerful device that easily matches the first generation Windows Phones and even outperforms them when it comes to graphics. However, the lack of memory kills the joy – a slightly more complicated app can easily find itself being swapped out, resulting in slow app launches, responsivity issues and temporary freezes due to paging. Despite the fairly powerful GPU and CPU, it takes significant developer effort to match the user experience of apps when compared to first generation devices – if at all possible.</p><div style="clear:both;"></div><img src="http://dotneteers.net/aggbug.aspx?PostID=6118" width="1" height="1">Windows Phone 7WP PerformanceWindows Phone Performance Part 4 of many– The Power of the GPUhttp://dotneteers.net/blogs/vbandi/archive/2012/03/22/windows-phone-performance-part-4-of-many-the-power-of-the-gpu.aspxThu, 22 Mar 2012 13:53:43 GMT74e06254-0e07-4c08-8611-9f55b924f030:6060vbandi4http://dotneteers.net/blogs/vbandi/rsscomments.aspx?PostID=6060http://dotneteers.net/blogs/vbandi/archive/2012/03/22/windows-phone-performance-part-4-of-many-the-power-of-the-gpu.aspx#comments<p><em>This is Part 3 of the translation of the performance chapter of the </em><a href="https://devportal.hu/wp7/konyv"><em>Windows Phone developer book</em></a><em> I co-authored with many of my Hungarian peers. Other parts of this series can be </em><a href="http://dotneteers.net/blogs/vbandi/archive/tags/WP+Performance/default.aspx"><em>found here</em></a><em>.</em></p> <p>The last time we saw our drunk Vuvrian hero, he was buzzed by a couple of procedurally animated Tie Fighters, but something just wasn’t right: the animations were choppy. So, let’s turn on the GPU in the application!</p> <p>Clicking the Enable GPU Acceleration button changes the situation dramatically. The Redraw Regions stop the crazy flashing, indicating that there is no more rasterizing happening. The phone animates 3 fighers smoothly – and it can handle 10 fighters without dropping the frame rate below 20. At the same time, the emulator can handle ten fighters without any noticeable slowdown, but the desktop GPU is designed to handle Call of Duty MW3, so it is not a fair fight…</p> <p>What is happening when the Enable GPU Acceleration button is clicked?</p> <pre class="csharpcode"><span class="kwrd">private</span> <span class="kwrd">void</span> enableGPU_Click(<span class="kwrd">object</span> sender, RoutedEventArgs e)
{
<span class="kwrd">foreach</span> (var fighter <span class="kwrd">in</span> Ties)
fighter.CacheMode = GetTIECacheMode();
}
<span class="kwrd">private</span> CacheMode GetTIECacheMode()
{
<span class="kwrd">bool</span> enabled = enableGPU.IsChecked.Value;
<span class="kwrd">return</span> enabled ? <span class="kwrd">new</span> BitmapCache() : <span class="kwrd">null</span>;
}</pre>
<p><style>
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, &quot;Courier New&quot;, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>We change the <strong>CacheMode </strong>property of the <strong>TIEFighter </strong>controls depending on whether the GPU acceleration has been turned on or off. When off, it is set to null, while turning the GPU on creates a <strong>BitmapCache </strong>object for every control. The name <strong>‘BitmapCache’ </strong>describes precisely what GPU acceleration means: the pixels of the rasterized <strong>UIElement </strong>is cached in the GPU. The GPU can manipulate this texture: move it, change its opacity, rotate it, resize it, perform a perspective distortion on itm blend it with the other textures or do a rectangular clipping. If the texture of such a cached element is changed (for example, the color changes), the Silverlight runtime automatically refreshes the texture in the GPU’s memory.</p>
<p>All of this means that some animations perform better than others. For example, the CPU is doing the non-rectangular clippings, the color animations, the changes in layouts, gradients, etc. If we are using these kind of animations, do it in small sizes – thus the CPU doesn’t have to calculate too many pixels and the high FPS values can be kept.</p>
<p>There is one more option that helps understanding the GPU’s work: </p>
<h2>Cache Visualization</h2>
<p>If you turn on Cache Visualization, you get this result:</p>
<p><a href="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/image_5F00_2533BAD9.png"><img style="background-image:none;border-bottom:0px;border-left:0px;margin:0px 8px 0px 0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/image_5F00_thumb_5F00_2B0E5E72.png" width="213" height="354" /></a></p>
<p>Cache Visualization makes every GPU texture semi transparent, and tinted with blue color. This allows us to see which textures are composited by the GPU. </p>
<p>Now is a good time to look at the Frame Rate Counters of the above screenshot:</p>
<p><strong>UI and Composition Thread FPS: </strong>these are much higher than what you can expect on a first generation phone, since the screenshot is created with the Emulator</p>
<p><strong>Texture memory used: </strong>8 MByte, it’s OK.</p>
<p><strong>Number of surfaces: </strong>The GPU works with 12 textures. 10 of then belong to the TIE Fighters (one for each), one to the background, and one to the controls. Note that while we have not specified a <strong>BitmapCache </strong>value for the background or the controls, they are also cached on the GPU, because there are textures in front of them and behind them. These are called implicit surfaces, and they are indicated by the number counter with the 002 value.</p>
<p><strong>Fill Rate: </strong>The problem is here, and the phone was kind enough to nicely make it red to attract attention. The 11.6 value of the Fill Rate means that in every frame, the GPU is drawing 11.6 screens worth of pixels. This is a very high number! On first generation phones, the frame rate begins to degrade at 2.5, and the animation becomes hurtfully jerky above 3.5. The high fill rate is caused by the many (and increasingly bigger sized) TIE fighters, but in our case, the fact that they are going outside the screen helps a lot. The second generation phones have a much higher Fill Rate tolerance (my Lumia 800 can handle 16 fighters without any frame rate drop, and only drop below 20 FPS at 46 fighters). However, we still have to optimize for first generation devices for a long time, so we cannot allow much laziness.</p>
<h2></h2>
<h2></h2>
<h2>StoryBoard animations and the GPU</h2>
<p>So far, we have been working with procedural animations. It is much easier to create a similar animation in Blend, using StoryBoards. You can find the result in the StoryBoardAnim.xaml file – and some added Easings make the movement of the fighters much more natural. To run this version, again change the DefaultTask in WMAppManifest.xml:&quot;</p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">DefaultTask</span> <span class="attr">Name</span> <span class="kwrd">=&quot;_default&quot;</span> <span class="attr">NavigationPage</span><span class="kwrd">=&quot;StoryBoardAnim.xaml&quot;</span><span class="kwrd">/&gt;</span></pre>
<style>
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, &quot;Courier New&quot;, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>&#160;</p>
<p>Launching the application now gives us a perfectly smooth animation, even with five TIE Fighters! We can easily verify the usage of GPU by turning on the GPU Visualization: every fighter has its own GPU surface. This is only possible by taking advantage of the GPU – which we haven’t turned on anywhere. It was the Silverlight runtime that turns on the GPU acceleration every time we use a StoryBoard animation, and only do things that the GPU can handle (see above). Quite convenient!</p>
<h2>UI, Compositor and Input threads</h2>
<p>The StoryBoardAnim.xaml page does not contain any stars. However, there is an “Add 6000 stars” button on the screen. If you press this, a few seconds later the 6000 stars are shown. Examining the code, you can see that the event handler for this button simply calls the CreateStarField method with an argument of 6000. There are no background threads or any other black magic around. Based on what I wrote about in <a href="http://dotneteers.net/blogs/vbandi/archive/2012/02/18/windows-phone-performance-part-2-of-many-it-s-full-of-stars.aspx" target="_blank">Part 2 of this series</a>, we know that this must occupy the UI thread. And yes, the UI thread is completely busy: the button is kept “pressed” long after your finger has been lift off from the screen (it is the UI thread that would redraw the button in a “non-pressed” state). </p>
<p><a href="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/image_5F00_2AA22B7D.png"><img style="background-image:none;border-bottom:0px;border-left:0px;margin:0px 8px 0px 0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/image_5F00_thumb_5F00_14D84320.png" width="221" height="366" /></a></p>
<p>At the same time, the animation has not slowed down a bit during the drawing of the stars! The reason for this is that the animations are running on a separate Compositor thread (and are drawn on the GPU). This is valid as long as the animations we are using do not require rasterization, or a change in the layout does not cause the recalculation of the visual tree. Movement, scaling and rotation are implemented through a RenderTransform, which is applied after the layout, and does not effect it).</p>
<p>Windows Phone Mango introduced a new thread to handle Input. This change, along with some other finetuning solves most of the responsiveness issues in the first release of Windows Phone 7. The most painful issue happened when scrolling through lists – the animation of the list was smooth, but if you touched a moving list, it only reacted after a considerable delay (often as much as a second). The reason for this was that the UI thread (which handled input before Mango) was busy rasterizing the new list items, and couldn’t handle the touch event in time. Needless to say, this resulted in a very uncomfortable user experience – fortunately, with Mango’s separate Input thread, this problem is now history.</p>
<p>In the next part of <a href="http://dotneteers.net/blogs/vbandi/archive/tags/WP+Performance/default.aspx" target="_blank">this blog series</a>, I will give some general advice on handling bad responsiveness, List performance. We will discuss the importance of subjective performance and related techniques. Finally, we will talk about memory optimization, and some tools that can help pinpointing problem areas in our apps. Tune in next time!</p>
<style>
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, &quot;Courier New&quot;, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style><div style="clear:both;"></div><img src="http://dotneteers.net/aggbug.aspx?PostID=6060" width="1" height="1">Windows Phone 7WP PerformanceWindows Phone Performance – Part 3 of Many: Tie Fighters and Drunk Spaceship Captainshttp://dotneteers.net/blogs/vbandi/archive/2012/03/14/windows-phone-performance-part-3-of-many-tie-fighters-and-drunk-spaceship-captains.aspxTue, 13 Mar 2012 23:50:30 GMT74e06254-0e07-4c08-8611-9f55b924f030:6035vbandi3http://dotneteers.net/blogs/vbandi/rsscomments.aspx?PostID=6035http://dotneteers.net/blogs/vbandi/archive/2012/03/14/windows-phone-performance-part-3-of-many-tie-fighters-and-drunk-spaceship-captains.aspx#comments<p><em>This is Part 3 of the translation of the performance chapter of the </em><a href="https://devportal.hu/wp7/konyv"><em>Windows Phone developer book</em></a><em> I co-authored with many of my Hungarian peers. Other parts of this series can be </em><a href="http://dotneteers.net/blogs/vbandi/archive/tags/WP+Performance/default.aspx"><em>found here</em></a><em>.</em></p> <p>There are a number of ways to create animation on Windows Phone. Let’s start with the one that is used the less frequently – <strong>procedural animation</strong>.</p> <p>Let’s take a 12-eyed <a href="http://starwars.wikia.com/wiki/Vuvrian" target="_blank">Vuvrian</a> spaceship captain, and get him really drunk:</p> <p><a href="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/image_5F00_7EB35AE9.png"><img style="background-image:none;border-bottom:0px;border-left:0px;margin:0px 8px 0px 0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/image_5F00_thumb_5F00_01E542D2.png" width="216" height="145" /></a></p> <p>Imagine that his ship is buzzed by a Tie Fighter. Our little app will simulate what the drunk Vuvrian is seeing as he’s desperately trying to open his eyes while the Tie Fighter is buzzing him with the starry space in the background.</p> <p>To do this, we will have to create a TIEFighter.xaml user control. I won’t copy its code here, you can download it together with the solution later. But here is what it looks like:</p> <p><a href="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/image_5F00_36859F0D.png"><img style="background-image:none;border-bottom:0px;border-left:0px;margin:0px 8px 0px 0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/image_5F00_thumb_5F00_3D38A890.png" width="215" height="223" /></a></p> <p>The essence of procedural animation is to recalculate the position of every object, in every frame. Again, the full code will be available, I would only like to emphasize the key parts here.</p> <p>In order to launch the <strong>ProceduralAnim </strong>sample, a little modification has to be made in the <strong>Properties/WMAppManifest.xml</strong> file:</p> <pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">DefaultTask</span> <span class="attr">Name</span> <span class="kwrd">=&quot;_default&quot;</span> <span class="attr">NavigationPage</span><span class="kwrd">=&quot;ProceduralAnim.xaml&quot;</span><span class="kwrd">/&gt;</span></pre>
<p><style>
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, &quot;Courier New&quot;, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>The animator code itself can be found in the <strong>ProceduralAnim.xaml.cs </strong>file, in the <strong>CompositionTargetOnRendering </strong>event handler. This is the <a href="http://msdn.microsoft.com/en-us/library/system.windows.media.compositiontarget.rendering(v=vs.95).aspx" target="_blank"><strong>Rendering</strong></a> event of the <strong>CompositionTarget </strong>class, called every time the UI thread is preparing to draw a new frame. Here is what the event handler looks like:</p>
<p>&#160;</p>
<pre class="csharpcode"><span class="kwrd">private</span> <span class="kwrd">int</span> frameCount = 0;
<span class="kwrd">private</span> <span class="kwrd">void</span> CompositionTargetOnRendering(<span class="kwrd">object</span> sender, EventArgs eventArgs)
{
<span class="kwrd">if</span> (frameCount &gt;= 100)
frameCount = 0;
<span class="kwrd">for</span> (<span class="kwrd">int</span> i = 0; i &lt; Ties.Count; i++)
{
var tieFighter = Ties[i];
CompositeTransform tr = (CompositeTransform) tieFighter.RenderTransform;
tieFighter.Opacity = frameCount/100.0;
<span class="kwrd">double</span> scale = 1 + frameCount/100.0;
tr.ScaleX = scale;
tr.ScaleY = scale;
tr.Rotation = frameCount / (i+1.0);
}
frameCount++;
}</pre>
<p><style>
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, &quot;Courier New&quot;, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style></p>
<p><strong>Ties </strong>is a list of TIEFighter objects. The above code simply iterates through every Tie Fighter, and changes their opacity, size and rotation based on where we are in the animation. If there are three Tie Fighters shown (indicating that the drunk Vuvrian has three eyes open), here is the result:</p>
<p><a href="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/image_5F00_15FE5F5B.png"><img style="background-image:none;border-bottom:0px;border-left:0px;margin:0px 8px 0px 0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/image_5F00_thumb_5F00_64434205.png" width="330" height="276" /></a></p>
<p>The little numbers on the right side of the screens are the Frame Rate Counters. It is worth a detour to investigate them at this point.</p>
<h2>Frame Rate Counters</h2>
<p>The constructor in <strong>App.xaml.cs </strong>has the following lines:</p>
<p>&#160;</p>
<div class="csharpcode">
<pre><span class="lnum"> 1: </span><span class="rem">// Show graphics profiling information while debugging.</span></pre>
<pre><span class="lnum"> 2: </span><span class="kwrd">if</span> (System.Diagnostics.Debugger.IsAttached)</pre>
<pre><span class="lnum"> 3: </span>{</pre>
<pre><span class="lnum"> 4: </span> <span class="rem">// Display the current frame rate counters.</span></pre>
<pre><span class="lnum"> 5: </span> Application.Current.Host.Settings.EnableFrameRateCounter = <span class="kwrd">true</span>;</pre>
<pre><span class="lnum"> 6: </span> </pre>
<pre><span class="lnum"> 7: </span> <span class="rem">// Show the areas of the app that are being redrawn in each frame.</span></pre>
<pre><span class="lnum"> 8: </span> <span class="rem">//Application.Current.Host.Settings.EnableRedrawRegions = true;</span></pre>
<pre><span class="lnum"> 9: </span> </pre>
<pre><span class="lnum"> 10: </span> <span class="rem">// Enable non-production analysis visualization mode, </span></pre>
<pre><span class="lnum"> 11: </span> <span class="rem">// which shows areas of a page that are handed off to GPU with a colored overlay.</span></pre>
<pre><span class="lnum"> 12: </span> <span class="rem">//Application.Current.Host.Settings.EnableCacheVisualization = true;</span></pre>
<pre><span class="lnum"> 13: </span> </pre>
<pre><span class="lnum"> 14: </span> <span class="rem">// Disable the application idle detection by setting the UserIdleDetectionMode property of the</span></pre>
<pre><span class="lnum"> 15: </span> <span class="rem">// application&#39;s PhoneApplicationService object to Disabled.</span></pre>
<pre><span class="lnum"> 16: </span> <span class="rem">// Caution:- Use this under debug mode only. Application that disables user idle detection will continue to run</span></pre>
<pre><span class="lnum"> 17: </span> <span class="rem">// and consume battery power when the user is not using the phone.</span></pre>
<pre><span class="lnum"> 18: </span> PhoneApplicationService.Current.UserIdleDetectionMode = IdleDetectionMode.Disabled;</pre>
<pre><span class="lnum"> 19: </span>}</pre>
</div>
<style>
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, &quot;Courier New&quot;, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>Line 5 makes the application show the frame rate counters, if the application is started with a debugger attached (F5). Here is a closer look:</p>
<p><a href="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/image_5F00_7C66AC60.png"><img style="background-image:none;border-bottom:0px;border-left:0px;margin:0px 8px 0px 0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/image_5F00_thumb_5F00_0319B5E4.png" width="508" height="195" /></a></p>
<p>What do these numbers mean? Here is a summary from left to right:</p>
<table cellspacing="0" cellpadding="2">
<tr>
<td><strong>Counter</strong></td>
<td><strong>Description</strong></td>
</tr>
<tr>
<td>Composition thread frame rate</td>
<td>Indicates how many times the screen is refreshed per second. If this number is smaller than 60 (50 on some devices), the animations lose their fluidity. If it decreases below 30, even less keen-eyed users will start to notice the problem, and the number turns red</td>
</tr>
<tr>
<td>UI thread frame rate</td>
<td>The UI thread is where the rendering (rasterizing) happens, and where our code runs by default (unless we start a new thread). A slow UI thread frame rate usually means that the application will not be responsive. Animations can still be fluid on the Composition thread, and utilizing the GPU – but the user experience will definitely suffer if the UI thread is overloaded.</td>
</tr>
<tr>
<td>Texture memory usage</td>
<td>Indicates the amount of video- and system memory used by the textures</td>
</tr>
<tr>
<td>Number of Explicit Surfaces</td>
<td>Shows the number of Explicit Surfaces used by the GPU. If a <strong>FrameworkElement</strong> object has its <strong>CacheMode </strong>property set to <strong>BitmapCache</strong>, this counter increases.</td>
</tr>
<tr>
<td>Number of Implicit Surfaces</td>
<td>The number of Implicit Surfaces used by the GPU. (this will be explained later, I promise)</td>
</tr>
<tr>
<td>Fill Rate</td>
<td>One of the most important performance indicator of the GPU. GPUs can only draw so much pixels per second. In the case of Windows Phone 7, the display consists of 480*800 pixels, and the GPU of a first generation phone can fill this about 2.5 times per frame.
<br />A Fill Rate of 1 means that the GPU is drawing 1 screen worth of pixels per frame. If this number is increased above 2.5, the GPU becomes the bottleneck. If the numbers grow beyond 3, it turns red, because the animations lose their fluidity. Pay attention that seemingly innocent actions, like setting a background color for the application increases the Fill Rate by 1, since the GPU has to draw this background first. It is a good practice to keep the background transparent, if we are using the system theme.</td>
</tr>
</table>
<p>&#160;</p>
<p>The above screenshots indicate that the emulator can run the UI thread with 15 fps (frame per second). My first generation phone shows 12-13 fps. The problem is not caused by the high Fill Rate, since it is a constant 1. Even with one Tie Fighter, the phone is only able to animate at 20-30 fps. What can be the reason for this?</p>
<h2>Redraw Regions</h2>
<p>Turning the Redraw Regions option on, an adept eye can immediately see the problem. Here is what you can see on the screen:</p>
<p><a href="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/image_5F00_09608C72.png"><img style="background-image:none;border-bottom:0px;border-left:0px;margin:0px 8px 0px 0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/image_5F00_thumb_5F00_4DC07DB1.png" width="227" height="362" /></a></p>
<p>The SIlverlight runtime tries to optimize drawing speed by only redrawing the areas that change between two frames. The Redraw Regions option tints these areas with a different color for every frame. (this does tax the CPU, so don’t perform performance measurements while this option is on).</p>
<p>The picture above shows that a significant part of the screen has to be re-rendered as the Tie Fighter moves above the stars and below the controls. Also, the Tie Fighter itself gets redrawn for every single frame, since its size and rotation are continuously changing. This rasterizing / rendering work is performed by the CPU – no wonder that it cannot do better than 20-25 frames per second.</p>
<p>In <a href="http://www.dotneteers.net/blogs/vbandi/archive/2012/02/15/windows-phone-performance-part-1-of-many.aspx" target="_blank">Part 1</a> of this series, I mentioned that the GPU is especially optimized for tasks like rotating and scaling textures (and many more). So, isn’t it time to take advantage of the GPU? Yes – but stay tuned, the GPU will be the topic of the next blog post.</p><div style="clear:both;"></div><img src="http://dotneteers.net/aggbug.aspx?PostID=6035" width="1" height="1">Windows Phone 7WP PerformanceWindows Phone Performance – Part 2 of many – It’s Full of Stars!http://dotneteers.net/blogs/vbandi/archive/2012/02/18/windows-phone-performance-part-2-of-many-it-s-full-of-stars.aspxSat, 18 Feb 2012 11:06:53 GMT74e06254-0e07-4c08-8611-9f55b924f030:6008vbandi3http://dotneteers.net/blogs/vbandi/rsscomments.aspx?PostID=6008http://dotneteers.net/blogs/vbandi/archive/2012/02/18/windows-phone-performance-part-2-of-many-it-s-full-of-stars.aspx#comments<p><em>This is Part 2 of the translation of the performance chapter of the </em><a href="https://devportal.hu/wp7/konyv" target="_blank"><em>Windows Phone developer book</em></a><em> I co-authored with many of my Hungarian peers. Other parts of this series can be </em><a href="http://dotneteers.net/blogs/vbandi/archive/tags/WP+Performance/default.aspx" target="_blank"><em>found here</em></a><em>.</em></p> <p>We finished the <a href="http://www.dotneteers.net/blogs/vbandi/archive/2012/02/15/windows-phone-performance-part-1-of-many.aspx" target="_blank">previous part</a> discussing the roles of the CPU and the GPU in the phone. Let’s see an example of the CPU’s task!</p> <h2><em>It’s Full of Stars!</em></h2> <p>Let’s create a simple application – an application we will use to examine the performance problems and ways to fix them. In the first step, this program displays a star field. Let’s create a new C# Windows Phone application, call it <strong>CpuAndGpu</strong>, and enter the following into <strong>MainPage.xaml.cs</strong>:</p> <p>&#160;</p> <pre class="csharpcode"><span class="kwrd">using</span> System;
<span class="kwrd">using</span> System.Diagnostics;
<span class="kwrd">using</span> System.Windows;
<span class="kwrd">using</span> System.Windows.Media;
<span class="kwrd">using</span> System.Windows.Shapes;
<span class="kwrd">using</span> Microsoft.Phone.Controls;
<span class="kwrd">namespace</span> CpuAndGpu
{
<span class="kwrd">public</span> <span class="kwrd">partial</span> <span class="kwrd">class</span> MainPage : PhoneApplicationPage
{
<span class="kwrd">private</span> Stopwatch stopwatch;
<span class="rem">// Constructor</span>
<span class="kwrd">public</span> MainPage()
{
stopwatch = <span class="kwrd">new</span> Stopwatch();
stopwatch.Start();
InitializeComponent();
CreateStarField(100);
Loaded += OnLoaded;
}
<span class="kwrd">private</span> <span class="kwrd">void</span> OnLoaded(<span class="kwrd">object</span> sender, RoutedEventArgs routedEventArgs)
{
MessageBox.Show(<span class="str">&quot;Startup time: &quot;</span> +
stopwatch.ElapsedMilliseconds + <span class="str">&quot; ms&quot;</span>);
}
<span class="kwrd">public</span> <span class="kwrd">void</span> CreateStarField(<span class="kwrd">int</span> numOfStars)
{
Random x = <span class="kwrd">new</span> Random();
<span class="kwrd">for</span> (<span class="kwrd">int</span> i = 0; i &lt; numOfStars; i++)
{
Ellipse ellipse = <span class="kwrd">new</span> Ellipse();
<span class="kwrd">double</span> size = x.NextDouble()*3;
ellipse.Width = size;
ellipse.Height = ellipse.Width;
ellipse.Fill = <span class="kwrd">new</span> SolidColorBrush(Colors.White);
ellipse.Margin = <span class="kwrd">new</span> Thickness(x.Next(456), x.Next(607), 0, 0);
ellipse.HorizontalAlignment = HorizontalAlignment.Left;
ellipse.VerticalAlignment = VerticalAlignment.Top;
ContentPanel.Children.Add(ellipse);
}
}
}
}</pre>
<p><style>
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, &quot;Courier New&quot;, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style></p>
<p>Let’s also remove the <strong>SplashScreen.jpg </strong>file from the project using the Solution Explorer.</p>
<p>The above program is very simple. In the constructor of the <strong>MainPage </strong>class, we start a stopwatch that measures the time spent since launch. In the <strong>Loaded</strong> event handler (which is invoked after the <strong>MainPage </strong>is displayed), we use a <strong>MessageBox </strong>to display the time it took for the app to launch. After starting the stopwatch, the <strong>InitializeComponent </strong>method is interpreting the page’s XAML, and then the <strong>CreateStarField </strong>method is called. This method draws randomly placed and sized stars – as many as specified in the <strong>numOfStars </strong>parameter.</p>
<p>If we launch the application in the emulator, we get the following result:</p>
<p><a href="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/image_5F00_375DFA60.png"><img style="background-image:none;border-bottom:0px;border-left:0px;margin:0px 8px 0px 0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/image_5F00_thumb_5F00_3DA4D0EE.png" width="275" height="484" /></a></p>
<p>So, the application launches in 388 ms. But the app will ultimately have to run on the phone, so let’s start it there, too! On a first generation LG Optimus 7 device, the app starts in 558 ms. But what happens if we want to show more stars – thousands of them? The result of the measurements can be seen in this graph:</p>
<p><a href="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/image_5F00_243CCDB4.png"><img style="background-image:none;border-bottom:0px;border-left:0px;margin:0px 8px 0px 0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/image_5F00_thumb_5F00_03B58E02.png" width="421" height="254" /></a></p>
<p>We could not even measure 20,000 stars on the phone, since it took more than 20 seconds to launch, and the OS has killed the app.</p>
<p>Experienced developers may spot that there is some room to make the drawing of the stars faster. We are setting the height and the width of the ellipse to the same random value (stars look like circles after all) – but we are doing this with the line</p>
<pre class="csharpcode">ellipse.Height = ellipse.Width; </pre>
<p><style>
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, &quot;Courier New&quot;, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style></p>
<p>If we replace the above to </p>
<pre class="csharpcode">ellipse.Height = size;</pre>
<p><style>
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, &quot;Courier New&quot;, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style></p>
<p>and repeat the measurements of 5000 stars, it will be displayed in 4202 ms instead of the old 4300 on the phone. This is because we execute a Dependency Property get for every star. Maybe this 0,2 ms per star doesn’t seem like much – but in the core of a loop executed thousands of times, even small things like this matter.</p>
<p>The above experiment teaches us two important lessons:</p>
<ul>
<li>The performance-characteristics of the emulator are totally different than that of the real phones. We shouldn’t make assumptions of the application’s performance based on its behavior in the emulator! Although the emulator is very precise, and is executing the same OS as the phone itself, it is still doing that on the processor and graphics card of a desktop computer. <strong>Always verify the application on a real device, and tune the performance on a phone, not in the emulator!</strong></li>
<li><strong>Common sense and the traditional .NET optimization techniques </strong>are still useful on the phone.</li>
</ul>
<h3></h3>
<h3>Dealing with Slow Application Launch </h3>
<p>The above application obviously has a big problem – it is very slow to launch. Let’s see how it can be improved!</p>
<h4>Decreasing Layout Costs</h4>
<p>Looking more carefully at MainPage.xaml, we can see that the stars are placed in a <strong>Grid</strong>. The <strong>Grid</strong> is very flexible, adopts to the changes in available size – but all this flexibility comes at a price. Let’s replace the Grid with a much simpler Canvas:</p>
<pre class="csharpcode">&lt;!--&lt;Grid x:Name=<span class="str">&quot;ContentPanel&quot;</span> Grid.Row=<span class="str">&quot;1&quot;</span> Margin=<span class="str">&quot;12,0,12,0&quot;</span>&gt;&lt;/Grid&gt;--&gt;
&lt;Canvas x:Name=<span class="str">&quot;ContentPanel&quot;</span> Grid.Row=<span class="str">&quot;1&quot;</span> Margin=<span class="str">&quot;12,0,12,0&quot;</span>&gt;&lt;/Canvas&gt;</pre>
<p><style>
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, &quot;Courier New&quot;, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style></p>
<p>We will also have to modify the code so that it uses the Canvas.Top and Canvas.Left attached properties to place the stars instead of the margins:</p>
<p>&#160;</p>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">void</span> CreateStarField(<span class="kwrd">int</span> numOfStars)
{
Random x = <span class="kwrd">new</span> Random(numOfStars);
<span class="kwrd">for</span> (<span class="kwrd">int</span> i = 0; i &lt; numOfStars; i++)
{
Ellipse ellipse = <span class="kwrd">new</span> Ellipse();
<span class="kwrd">double</span> size = x.NextDouble()*3;
ellipse.Width = size;
ellipse.Height = size;
ellipse.Fill = <span class="kwrd">new</span> SolidColorBrush(Colors.White);
ellipse.SetValue(Canvas.LeftProperty, (<span class="kwrd">double</span>)x.Next(456));
ellipse.SetValue(Canvas.TopProperty, (<span class="kwrd">double</span>)x.Next(607));
<span class="rem">// ellipse.Margin = new Thickness(x.Next(456), x.Next(607), 0, 0);</span>
<span class="rem">// ellipse.HorizontalAlignment = HorizontalAlignment.Left;</span>
<span class="rem">// ellipse.VerticalAlignment = VerticalAlignment.Top;</span>
ContentPanel.Children.Add(ellipse);
}
}</pre>
<p><style>
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, &quot;Courier New&quot;, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style></p>
<p>Running this version with 5000 stars, the app launches in 3093ms instead of the previously measured 4100ms! </p>
<p>In general, we can conclude that we should only use complicated layout systems when needed. Every resizing, change in the number of children results in a partial or full measurement cycle of the visual tree – and the less such work the CPU has to perform, the faster the application will be.</p>
<h4></h4>
<h4><font style="font-weight:bold;">The Splash Screen</font></h4>
<p>The Splash Screen is the full screen picture shown right after launching the application. The Splash Screen does not make launching the app faster – but if we can’t decrease the launch time below 1 or 2 seconds, the user will prefer watching a tasteful graphics than the empty screen. A bit of warning though – the SplashSceen.jpg image found in the default WP7 application template does not belong into the tasteful category! </p>
<p>The Marketplace regulations are also requiring the use of a Splash Screen if the application launches slower than 5 seconds. The Splash Screen is visible until the first screen is rendered.</p>
<p>Another advantage of the Splash Screen is that the user – in the absence of a stopwatch – will feel that the application loads faster, because something is happening on the screen. This feeling is called “subjective performance”. Expert use of such tricks can significantly enhance the user experience as we will discuss it later.</p>
<p>It is very easy to implement a Splash Screen in your app – just place an image called <strong>SplashScreen.jpg </strong>in the root directory of the Windows Phone project, and set its <strong>Build Action </strong>to <strong>Content</strong>.</p>
<h4><font style="font-weight:bold;">Delaying the Initialization </font></h4>
<p>In the sample app above, the launch of the application is significantly slower due to the time it takes to draw all the stars. What if we would only draw these stars after the app has loaded? Let’s move the call to the CreateStarField method from the constructor into the <strong>OnLoaded </strong>event handler:</p>
<pre class="csharpcode"><span class="kwrd">private</span> <span class="kwrd">void</span> OnLoaded(<span class="kwrd">object</span> sender, RoutedEventArgs routedEventArgs)
{
CreateStarField(5000);
MessageBox.Show(<span class="str">&quot;Startup time: &quot;</span> + stopwatch.ElapsedMilliseconds + <span class="str">&quot; ms&quot;</span>);
}</pre>
<style>
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, &quot;Courier New&quot;, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>If we launch this app on the phone, we can observe two important things. One of them is that when the <strong>MessageBox </strong>is displayed, the stars are not visible, and the number has decreased to 2876 ms from the original 3093 ms. The reason for this is that the actual drawing of the ellipses has not yet happened at this stage – it will only be performed after closing the <strong>MessageBox</strong>.</p>
<p>The other phenomenon is that the application launches fast, and the header text is displayed almost immediately. But this shouldn’t deceive us – the application will not react to user input while the stars are being added, since the UI thread is busy. We can easily verify this by adding a button to the <strong>MainPage.xaml.cs</strong>:</p>
<pre class="csharpcode">&lt;Canvas x:Name=<span class="str">&quot;ContentPanel&quot;</span> Grid.Row=<span class="str">&quot;1&quot;</span> Margin=<span class="str">&quot;12,0,12,0&quot;</span>&gt;
&lt;Button Canvas.ZIndex=<span class="str">&quot;1&quot;</span>&gt;I am not doing anything...&lt;/Button&gt;
&lt;/Canvas&gt;</pre>
<p><style>
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, &quot;Courier New&quot;, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>Pressing the button will switch its colors to inverse: a black button with white text becomes a white button with black text. But rendering these changes is happening on the UI thread, which is busy with drawing the stars. The result is that the button will only react to the touch after all the drawing is done.</p>
<h4><font style="font-weight:bold;">Background Threads to the Rescue</font></h4>
<p>So, if the <strong>UI thread is so important for keeping interactivity alive, </strong>let’s move the drawing of the stars to a another thread! We have to modify the <strong>OnLoaded </strong>event handler and create a new method called <strong>BGCreateStars </strong>for this one:</p>
<p>&#160;</p>
<pre class="csharpcode"><span class="kwrd">private</span> <span class="kwrd">void</span> OnLoaded(<span class="kwrd">object</span> sender, RoutedEventArgs routedEventArgs)
{
Thread t = <span class="kwrd">new</span> Thread(BGCreateStars);
t.Name = <span class="str">&quot;Stars&quot;</span>;
t.Start();
<span class="rem">// CreateStarField(5000); </span>
<span class="rem">// MessageBox.Show(&quot;Startup time: &quot; + stopwatch.ElapsedMilliseconds + &quot; ms&quot;);</span>
}
<span class="kwrd">private</span> <span class="kwrd">void</span> BGCreateStars()
{
<span class="kwrd">for</span> (<span class="kwrd">int</span> i = 0; i &lt; 500; i++)
{
UIDispatcher.BeginInvoke(() =&gt; CreateStarField(10));
Thread.Sleep(30);
}
}</pre>
<p>The BGCreateStars executes the CreateStarField method 500 times – and each call will draw 10 stars. CreateStarField has to run on the UI thread, because it manipulates the UI. So, we launch it through the UIDispatcher.BeginInvoke method. The BGCreateStars is also careful not to overload the UI thread by resting 30 ms after each call. We have also removed the MessageBox, since it would be shown before the application stars, and wouldn’t be too useful this way. </p>
<p>Running this application, the user experience is much better: launch time is minimal, and the application immediately reacts to button presses. Stars are being drawn slowly, it looks like the app draws them one at a time.</p>
<h4><style>
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, &quot;Courier New&quot;, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style></h4>
<h4><font style="font-weight:bold;">Being Prepared is Always Good </font></h4>
<p>This is all great and all – but what if we need the whole starfield, right after launch? There is a simple solution for this case, too: create a screenshot of the starfield, and set it as the background image of the <strong>ContentPanel</strong>. We have to place a file in the project (call it starsBG.png), and change its properties so that <strong>Build Action is Content</strong>, and <strong>Copy to Output Directory </strong>is <strong>Copy if newer</strong>. The <strong>MainPage.xaml.cs </strong>can be reset to the original (keeping only an <strong>InitializeComponent </strong>call in the constructor). Here is what the starsBG.png can look like:</p>
<p><a href="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/image_5F00_236467CA.png"><img style="background-image:none;border-bottom:0px;border-left:0px;margin:0px 8px 0px 0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://dotneteers.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vbandi/image_5F00_thumb_5F00_69E157D2.png" width="254" height="336" /></a></p>
<p>And change the ContentPanel in MainPage.xaml.cs to this:</p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">Canvas</span> <span class="attr">x:Name</span><span class="kwrd">=&quot;ContentPanel&quot;</span> <span class="attr">Grid</span>.<span class="attr">Row</span><span class="kwrd">=&quot;1&quot;</span> <span class="attr">Margin</span><span class="kwrd">=&quot;12,0,12,0&quot;</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;</span><span class="html">Canvas.Background</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;</span><span class="html">ImageBrush</span> <span class="attr">Stretch</span><span class="kwrd">=&quot;None&quot;</span> <span class="attr">ImageSource</span><span class="kwrd">=&quot;/starsBG.png&quot;</span><span class="kwrd">/&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">Canvas.Background</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;</span><span class="html">Button</span> <span class="attr">Canvas</span>.<span class="attr">ZIndex</span><span class="kwrd">=&quot;1&quot;</span><span class="kwrd">&gt;</span>I am not doing anything...<span class="kwrd">&lt;/</span><span class="html">Button</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">Canvas</span><span class="kwrd">&gt;</span></pre>
<p><style>
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, &quot;Courier New&quot;, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style></p>
<p>And we’ve done it! The app starts within half a second, even with 5000 stars! If you still need a random starfield, simply prepare 10 different images, and set one of them as a background from code.</p>
<h3>The Story So Far…</h3>
<p>Naturally, the principles outlined above can be used in “real” apps as well. A good example for delayed initialization is our <a href="http://www.facebook.com/SurfCube3D" target="_blank">SurfCube 3D Browser</a> app. Since the launch time of the application slowly grew beyond 5-6 seconds, we had more and more users complaining. Some of them even thought that the splash screen is only there since we loved the logo. He would have accepted this, but was outraged that the splash screen was still visible after buying the app!</p>
<p>To help ease this pain, starting with V4.0 of SurfCube, we are loading the sides of the cube with <strong>Visibility </strong>set to <strong>Collapsed</strong>. We only switch to <strong>Visible </strong>at the first rotation. This may be a little bit inconvenient, but we managed to reduce the application’s launch time to 3.5 seconds.</p>
<p>Another thing that may help a lot is moving rarely used modules into separate assemblies. This way, the runtime won’t load these assemblies until they are referenced.</p>
<p>An example for preparing data is my Hungarian nameday app, “Névnap”, which is currently the #1 free reference app in the Hungarian Marketplace. An SQL CE database is used to store and query the namedays, which is filled from a text file during the first run of the app. Further executions only use the SQL CE database, saving the time to parse the text file. An even better solution for this is to place the SQL database in the XAP during development, so that even the first launch can be fast.</p>
<p><em>Coming up: in the next post, I will discuss animations, the GPU and we will meet a ten-eyed drunken spaceship captain who is being buzzed by a TIE Fighter! Don’t miss it – and please keep the feedbacks coming!</em></p><div style="clear:both;"></div><img src="http://dotneteers.net/aggbug.aspx?PostID=6008" width="1" height="1">Windows Phone 7WP PerformanceWindows Phone Performance–Part 1 of manyhttp://dotneteers.net/blogs/vbandi/archive/2012/02/15/windows-phone-performance-part-1-of-many.aspxWed, 15 Feb 2012 22:02:00 GMT74e06254-0e07-4c08-8611-9f55b924f030:6002vbandi5http://dotneteers.net/blogs/vbandi/rsscomments.aspx?PostID=6002http://dotneteers.net/blogs/vbandi/archive/2012/02/15/windows-phone-performance-part-1-of-many.aspx#comments<p><em>This post series is the translation of the performance chapter of the Windows Phone developer book I co-authored with many of my Hungarian peers. If you read Hungarian, I suggest you get the book &ndash; either online or in a paper format. There are also some seriously good videos that come with it, if you are more of a session watcher kind. I think that this information would be useful for other WP developers, too, who do not speak Hungarian. Therefore I started this blog post series, translating my Performance chapter. This post series also acts as a draft &ndash; if the feedback is good, I will clean it up and publish the performance chapters as an e-book. So, please do provide feedback, even if it is just a grammar mistake on my part! </em></p>
<h1></h1>
<h2>1. The Big Challenge</h2>
<p>If you compare the computing power of a desktop pc or even a laptop to a phone, the numbers are pretty disappointing. The battery of a phone could only deliver a few minutes of power to a desktop computer. The CPU of a Windows Phone has only one core, and even though it runs at 1 GHz, it is about the equivalent of a 600 MHz Pentium III from 1999. A two year old Core 2 processor is about 30 times more powerful. As for the GPU, the Snapdragon has approximately the performance of a graphics card from the same era.</p>
<p>What do we do with all this amazing computing power? Well, mostly we are using it to make user experience better. As computers became faster, they can serve us better &ndash; with shorter waiting times, more help for our work, richer graphics, bigger resolutions, and animations that turned out to be useful even for line of business applications. Users expect a certain level of user experience today &ndash; the UX from 2000 just won&rsquo;t cut it in 2012.</p>
<p>The arrival of touch screens have increased these expectations even further. While the mouse has an indirect interaction model, on a touch screen you activate and move the things on the screen directly. This is all great, but these things have to react just like real world objects. And in the real world, the objects don&rsquo;t move with 5-10 fps (frame per second). When you push a physical object, it doesn&rsquo;t sit around and wait a few hundred milliseconds before starting to move. On a desktop computer you probably won&rsquo;t even notice a delay of a third of a second between clicking the mouse and the software&rsquo;s reaction &ndash; but on a touch screen, this can be really disturbing.</p>
<p>The developer experience has gone through a lot of changes, especially in the Microsoft world. We are using the fourth generation of the .NET framework, and we expect to have the same productivity during mobile development as when creating desktop or web applications. The increased performance allows us to use more advanced, higher level tools during development &ndash; most of the time we don&rsquo;t even think about bits, bytes, memory management. Often we define databases and even control schemes using graphical tools. The client-server communication is now part of the framework itself, we don&rsquo;t have to reinvent the wheel with every project. We, developers are just as surely don&rsquo;t want to step back ten years in time as our users.</p>
<p>It is a small miracle to have the hardware of a ten year old desktop computer in our pockets. But if you think about how we have to satisfy the increased needs of our users, the power of the phone seems to be rather inadequate. This is the big challenge of mobile development. Let&rsquo;s see how a Silverlight on Windows Phone 7 can help us face this problem!</p>
<h2>2. Typical Performance Problems</h2>
<p>While Average Joe can only say &ldquo;erm&hellip; slow&rdquo;, developers have to know the symptoms better in order to handle the problems. Let&rsquo;s see what kind of performance problems we can encounter:</p>
<ul>
<li><strong>Lagging animations: </strong>everybody has different tolerance levels with regards to when an animation becomes disturbingly jerky. But one thing for sure: Windows Phone users have extraordinarily high expectations in this regard. One of the most striking and most often mentioned advantage of the platform in how silky smooth animations users are being pampered with.</li>
<li><strong>Slow loading applications: </strong>no one likes to wait a long time for an application to be usable after launching it. If loading takes more than five seconds and there is no splash screen, even the OS will kill it. (This timeout is set to 20 seconds if we use a splash screen.) </li>
<li><strong>Long wait times</strong> <strong>(responsiveness): </strong>how much time does it take for the application to give an answer after pressing a button? If there is no feedback, the user will probably press the button again and again, thinking that the phone has not registered the touch.</li>
<li><strong>Empty area appears while scrolling (blanking): </strong>scrolling through a long list, the user sees empty, blank areas, since drawing cannot keep up with the scrolling.</li>
<li><strong>Running out of memory: </strong>as a developer, we mostly meet this symptom at the latest during Marketplace digestion &ndash; Microsoft simply rejects apps that use too much memory. </li>
</ul>
<h2>3. The Task of the CPU and the GPU</h2>
<p>The CPU is a general purpose processor &ndash; it can perform mathematical operations, execute commands and algorithms. The app we write runs on the CPU. The CPU is a neat and essential component, but there are certain tasks it is not ideal for &ndash; such as graphic operations and video decoding.</p>
<p>Because of this, phones are also equipped with a GPU &ndash; a Graphical Processing Unit. This GPU works much like its big brother in desktop computers &ndash; it can place display triangles in space, millions per second. Fortunately, as a Windows Phone developer, we don&rsquo;t have to deal with the GPU at such a low level &ndash; most of the time we don&rsquo;t even realize that the Silverlight engine uses the GPU. But it is still very useful to know some things about the GPU if we want to solve performance issues. The GPU helps the CPU by bearing the burden of the following operations:</p>
<ul>
<li><strong>Composition</strong> &ndash; placing two or more textures (bitmaps) on the screen that cover each other and/or are semi-transparent. Moving things on the screen also happens with composition &ndash; after changing the position of an element, the composition restarts in the next frame.</li>
<li><strong>Rotation &ndash; </strong>rotating a bitmap</li>
<li><strong>Resizing &ndash; </strong>increasing or decreasing the size of a texture. The GPU can also smooth the edges of a texture, thus help with pixelating or aliasing.</li>
<li><strong>Perspective transforms &ndash; </strong>rotating a texture in 3D. This is not a real 3D, more like 2.5D, since we are only talking about flat textures and not 3D bodies. However, using perspective transforms properly can still provide the illusion of full 3D, just as it happened in <a target="_blank" href="http://www.windowsphone.com/en-us/apps/881f623a-fc0e-e011-9264-00237de2db9e">SurfCube 3D Browser</a>. </li>
<li><strong>Rectangular cropping &ndash; </strong>the GPU can be used to crop a texture, as long as the clipping geometry is rectangular.</li>
<li><strong>Video decoding and encoding</strong> &ndash; on Windows Phone, the video encoding, decoding, resizing is performed by a dedicated hardware &ndash; which is great news because the CPU wouldn&rsquo;t be able to play HD videos on its own. This way it is free to do other tasks, such as displaying subtitles, a seek bar, handling input, and so on.</li>
</ul>
<p>Mindful readers may have realized that the GPU is all about manipulating textures or bitmaps. But how is a texture of a control (such as a Button) created? This process is called rendering or rasterizing, and is performed by the CPU. The CPU is also tasked with interpreting XAML, creating controls, calculating layout, and of course &ndash; running our application.</p>
<p><em>In the next post, I will introduce our first sample application, examine the performance characteristics of the emulator, and show some techniques to decrease the app&rsquo;s launch time. Later on, we will examine the reasons of jerky animations, the performance diagnostic tools. We will talk about lists, subjective performance, memory optimizations, and even <strong>meet a ten-eyed drunk space-captain buzzed by a TIE Fighter</strong>! Let me know what you think in the comments and follow me on twitter at <a href="http://www.twitter.com/vbandi">www.twitter.com/vbandi</a>. </em></p><div style="clear:both;"></div><img src="http://dotneteers.net/aggbug.aspx?PostID=6002" width="1" height="1">Windows Phone 7WP Performance