tag:blogger.com,1999:blog-195058532024-03-20T23:02:39.113-07:00Code::Net::WavesThoughts on the trail.... Mobile Application Development, Cloud NetworkingVincehttp://www.blogger.com/profile/03061125501848592602noreply@blogger.comBlogger9125tag:blogger.com,1999:blog-19505853.post-3026356299321076942012-09-26T18:20:00.000-07:002012-09-26T18:42:05.411-07:00Change a View to a ScrollView in Xcode Interface Builder<span style="font-family: Verdana, sans-serif;">I recently needed to change UIView to a UIScrollView, then embed that ScrollView into a View. I won't go into the underlying code required to manipulate scrollViews. I am interested here in getting the UI correct with InterfaceBuilder.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">First, with Xcode IB, open the storyboard and locate the View you want to change. With the Utilities View (the rightmost button of the View group on the Xcode Toolbar), show the Identity Inspector.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">Change the Class under Custom Class from UIView to UIScrollView.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGkjOxqHPvgDcyUT3CGSDsR6DfDcxupBj_tJHcUHrcaQqzZKu_ZM8DZCCEOgHo1X86XAQKs5PukSUM7x7unTv5O2oFtoI9ml_BOCMNi8KtmsHzJYFV9nRCCWXlqjP32xmDHIqW/s1600/Screen+Shot+2012-09-26+at+6.14.36+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGkjOxqHPvgDcyUT3CGSDsR6DfDcxupBj_tJHcUHrcaQqzZKu_ZM8DZCCEOgHo1X86XAQKs5PukSUM7x7unTv5O2oFtoI9ml_BOCMNi8KtmsHzJYFV9nRCCWXlqjP32xmDHIqW/s1600/Screen+Shot+2012-09-26+at+6.14.36+PM.png" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5VqQQdwnop3Hf7ZuPk1hFe0KuoZaQCiJ9CTmYc3r8cqs6Zny-G-HTFlhPL26XmmLH7rB0MioKt8Gm-NQ1TFHDDPSABc8ha6tZklrG8534z0rWd_YNWH7Ym_AyFv57mck94vb6/s1600/Screen+Shot+2012-09-26+at+6.15.05+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5VqQQdwnop3Hf7ZuPk1hFe0KuoZaQCiJ9CTmYc3r8cqs6Zny-G-HTFlhPL26XmmLH7rB0MioKt8Gm-NQ1TFHDDPSABc8ha6tZklrG8534z0rWd_YNWH7Ym_AyFv57mck94vb6/s1600/Screen+Shot+2012-09-26+at+6.15.05+PM.png" /></a></div>
<br />
<span style="font-family: Verdana, sans-serif;">Since you need to embed the scrollView into a View, you can manually add a View under into the parent View Controller visual object or wait and use the Xcode Menu > Editor > Embed In > View command later. If you do it now, you will need to adjust the ScrollView position in the View window.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">The "View" is now a scrollView but the Attribute Inspector still indicates it is a View.</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjO1RovZ4lb6LSdJDsIpPwMNBpKMuhT_Ftrse5gREl27OlDbrD-zSJDINNN8ozHx3Rx57K5Bq4P71MaMueDHnmlyxefrx5teijNZSEHznhVVm9MzWGWh6CFPmISQWsmhATDVV9p/s1600/Screen+Shot+2012-09-26+at+6.01.38+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjO1RovZ4lb6LSdJDsIpPwMNBpKMuhT_Ftrse5gREl27OlDbrD-zSJDINNN8ozHx3Rx57K5Bq4P71MaMueDHnmlyxefrx5teijNZSEHznhVVm9MzWGWh6CFPmISQWsmhATDVV9p/s320/Screen+Shot+2012-09-26+at+6.01.38+PM.png" width="243" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: Verdana, sans-serif;">We want the Attribute Inspector to look like this:</span></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZhLiTnWRIJWRUlHZJuHZLXCTdK-C0IN8Dc8eAzMZvvfd6uyI8rbVW9b1J6e0NA2iD0sxTRO1RONfKsd0I56ixYhCtWD_Zz6A2FVyFC8-yIC2kREdnn7MLFw5vo5EnGmpwKACG/s1600/Screen+Shot+2012-09-26+at+6.03.09+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZhLiTnWRIJWRUlHZJuHZLXCTdK-C0IN8Dc8eAzMZvvfd6uyI8rbVW9b1J6e0NA2iD0sxTRO1RONfKsd0I56ixYhCtWD_Zz6A2FVyFC8-yIC2kREdnn7MLFw5vo5EnGmpwKACG/s640/Screen+Shot+2012-09-26+at+6.03.09+PM.png" width="256" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: Verdana, sans-serif;">To get this, in Xcode, use right-click on the storyboard, and Open As > Source Code. </span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSn0B1m3V-Foj67H5B2YDfgFgw6K-Zb3zYIehyJ1lxOeugIjqCGKRjm_4PQTT8DGPuTeX0Uv3gxfL7Jjfu6ElR079k4auDud3CgSQkZTDZano_m0uBxQC9twtcmYw3gIvW0UJx/s1600/Screen+Shot+2012-09-26+at+6.16.37+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="110" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSn0B1m3V-Foj67H5B2YDfgFgw6K-Zb3zYIehyJ1lxOeugIjqCGKRjm_4PQTT8DGPuTeX0Uv3gxfL7Jjfu6ElR079k4auDud3CgSQkZTDZano_m0uBxQC9twtcmYw3gIvW0UJx/s320/Screen+Shot+2012-09-26+at+6.16.37+PM.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: Verdana, sans-serif;">Now, in the XML source, search for UIScrollView. You will find something like this: </span><span style="font-family: Verdana, sans-serif;">(the !-- and -- are XML comments that I added)</span></div>
<div class="p1">
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhsvx9LReskb1rzXNg-oEaI1s1azgLD4hf7CvHRuQRf_s4Y6Krp3MtkHxrRZjfu0OPR_U_n-m1zQDExu492tMqttDmj9lUYF7677ORpOStaKK5-wAOxxWoNHd3GlPcTEyiC4uAz/s1600/Screen+Shot+2012-09-26+at+6.35.50+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhsvx9LReskb1rzXNg-oEaI1s1azgLD4hf7CvHRuQRf_s4Y6Krp3MtkHxrRZjfu0OPR_U_n-m1zQDExu492tMqttDmj9lUYF7677ORpOStaKK5-wAOxxWoNHd3GlPcTEyiC4uAz/s1600/Screen+Shot+2012-09-26+at+6.35.50+PM.png" /></a></div>
</div>
<div class="p1">
<br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">Change that to the following: (the !-- and -- are XML comments that I added)</span><br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidUWIgFHXun0E2w7TXfrHPa_jJCayk4Ap2abK_vJXlxkoBZarVh8nLy6BOSoHLMLT5LBlrm_H5oLIKSTjyaMKmxijvpGkF1kDDVNT9EX8_kwMTLco5xRyIyocr4ejodVwxhVo7/s1600/Screen+Shot+2012-09-26+at+6.31.45+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidUWIgFHXun0E2w7TXfrHPa_jJCayk4Ap2abK_vJXlxkoBZarVh8nLy6BOSoHLMLT5LBlrm_H5oLIKSTjyaMKmxijvpGkF1kDDVNT9EX8_kwMTLco5xRyIyocr4ejodVwxhVo7/s1600/Screen+Shot+2012-09-26+at+6.31.45+PM.png" /></a></div>
<br /></div>
<div class="p1">
<span style="font-family: Verdana, sans-serif;">Note that the id is the same.</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div class="p1">
<span style="font-family: Verdana, sans-serif;">Also, change the associated </span><span style="font-family: Courier New, Courier, monospace;">/view </span><span style="font-family: Verdana, sans-serif;">to </span><span style="font-family: Courier New, Courier, monospace;">/scrollView </span> <span style="font-family: Verdana, sans-serif;">at the bottom of this XML clause.</span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div class="p1">
<span style="font-family: Verdana, sans-serif;">That's it.</span></div>
<div class="p1">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="p1">
<span style="font-family: Verdana, sans-serif;">If you want to now , use the Embed In command to embed the ScrollView in a View.</span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<br />
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<br />Vincehttp://www.blogger.com/profile/03061125501848592602noreply@blogger.com5tag:blogger.com,1999:blog-19505853.post-57679875583165666312012-02-27T17:58:00.001-08:002012-02-27T17:58:43.776-08:00Using a Custom Prototype tableViewCell with an IOS StoryboardI was having all sorts of issues (disappearing data, incorrect data showing up in table view cells) attempting to use a custom, prototype cell from a Storyboard in a sub-classed UITableViewController that pulls from Core Data. Using a technique found at <a href="http://stackoverflow.com/questions/8574188/prototype-cells-in-a-nib-instead-of-a-storyboard">StackOverflow</a> and the following works:<br /><br />1) Create a subclass of UITableViewCell, call it <span style="font-size: xx-small;"><span style="font-family: "Courier New",Courier,monospace;">MyCustomTVCell</span></span><br /><br />2) Create the custom xib (<span style="font-size: xx-small;"><span style="font-family: "Courier New",Courier,monospace;">MyCustomTVCellXibFile</span></span>) file, pull in a tableViewCell. Make it custom, and make sure to use a unique Reuse Identifier (<span style="font-size: xx-small;"><span style="font-family: "Courier New",Courier,monospace;">My Unique Reuse ID</span>).</span><br /><br />3) In the Identity Inspector, assign it the <span style="font-size: xx-small;"><span style="font-family: "Courier New",Courier,monospace;">MyCustomTVCell</span></span> class<br /><br />4) Pull in a label on the tableViewCell.<br /><br />5) Control-drag from the label to the <span style="font-size: xx-small;"><span style="font-family: "Courier New",Courier,monospace;">MyCustomTVCell</span></span>.h file<br />to IBOutlets. (call it <span style="font-size: xx-small;">label01</span>)<br /><br />6) Use the method <span style="font-family: "Courier New",Courier,monospace; font-size: xx-small;">registerNib:forCellReuseIdentifier:</span> in <span style="font-family: "Courier New",Courier,monospace; font-size: xx-small;">tableView:cellForRowAtIndexPath:</span> (thanks <a href="http://stackoverflow.com/users/456366/richard-venable">@richard-venable</a>)<br />
<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">
<span style="font-size: xx-small;">static NSString *CellIdentifier = @"My Unique Reuse ID";</span></div>
<br />
<span style="font-family: "Courier New",Courier,monospace; font-size: x-small;"><span style="font-size: xx-small;">[tableView registerNib:[UINib nibWithNibName:@"</span></span><span style="font-size: xx-small;"><span style="font-family: "Courier New",Courier,monospace;">MyCustomTVCellXibFile</span></span><span style="font-family: "Courier New",Courier,monospace; font-size: x-small;"><span style="font-size: xx-small;">" bundle:nil] forCellReuseIdentifier:CellIdentifier]; </span></span><br />
<br />
<br />
7) Create a cell with the MyCustomTVCell subclass:<br />
<br />
<span style="font-size: xx-small;"><span style="font-family: "Courier New",Courier,monospace;">MyCustomTVCell *cell = (</span></span><span style="font-size: xx-small;"><span style="font-family: "Courier New",Courier,monospace;">MyCustomTVCell</span></span><span style="font-size: xx-small;"><span style="font-family: "Courier New",Courier,monospace;"> *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> </span></span><br />
<span style="font-size: xx-small;"><span style="font-family: "Courier New",Courier,monospace;">if (cell == nil) {</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> cell = [[</span></span><span style="font-size: xx-small;"><span style="font-family: "Courier New",Courier,monospace;">MyCustomTVCell</span></span><span style="font-size: xx-small;"><span style="font-family: "Courier New",Courier,monospace;"> alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> }</span></span><br />
<br />
8) Assign CD data to the now extended properties of the cell, i.e.<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">
<span style="font-size: xx-small;">cell.label01.text = "fetched data from CoreData";</span></div>
<br />
It works.Vincehttp://www.blogger.com/profile/03061125501848592602noreply@blogger.com1tag:blogger.com,1999:blog-19505853.post-26427247520973476432011-10-02T05:39:00.000-07:002012-03-09T19:30:48.931-08:00I am interested in learning more and more about the evolving field of software development and engineering, especially Mobile Applications and Cloud Networking. So I am always on the lookout for upcoming meetups and events. Have you heard about Silicon Valley Code Camp. This is one that is all about engineer to engineer exchange, developers teaching developers, and it's an all volunteer setting. There is even an iPhone app for it.<br />
<br />
I'll be there:<br />
<br />
<a href="http://www.siliconvalley-codecamp.com/" target="_new" title="CodeCamp at FootHill College. Click Here for Details and Registration"><img alt="CodeCamp at FootHill College." longdesc="" src="http://www.siliconvalley-codecamp.com/DisplayAd.ashx?ImageType=2" /></a><br />
<br />
I<span style="font-family: Arial,Helvetica,sans-serif;"> am volunteering for a slot and also attending the following sessions:</span><br />
<ul style="font-family: Arial,Helvetica,sans-serif;">
<li><h2 style="font-weight: normal;">
<span style="font-size: small;">iOS Application Architecture</span></h2>
</li>
<li><h2 style="font-weight: normal;">
<span style="font-size: small;">TurboCharge your iPhone project with Three20 (an open-source Objective-C library)</span></h2>
</li>
<li><h2 style="font-weight: normal;">
<span style="font-size: small;">iPhone Development Kickstart</span></h2>
</li>
<li><h2 style="font-weight: normal;">
<span style="font-size: small;">Hands on BlackBerry Playbook, iOS and Android Development</span></h2>
</li>
<li><h2 style="font-weight: normal;">
<span style="font-size: small;">What is Google App Engine?</span></h2>
</li>
<li><h2 style="font-weight: normal;">
<span style="font-size: small;">Google App Engine workshop</span></h2>
</li>
<li><h2 style="font-family: Arial,Helvetica,sans-serif; font-weight: normal;">
<span style="font-size: small;">Automated GUI Testing on Mac using ATOMac</span></h2>
<h2 style="font-family: Arial,Helvetica,sans-serif; font-weight: normal;">
<span style="font-size: small;">There is a lot to choose from. Hope to see you there!</span></h2>
</li>
</ul>
<h2 style="font-family: Arial,Helvetica,sans-serif;">
<span style="font-size: small;"><span style="font-weight: normal;">Vince</span></span></h2>
<h2>
</h2>
<h2>
</h2>Vincehttp://www.blogger.com/profile/03061125501848592602noreply@blogger.com0tag:blogger.com,1999:blog-19505853.post-49772692576983283442011-10-01T18:20:00.000-07:002011-10-01T22:56:14.667-07:00Xcode Profiling for Fun and EfficiencyIf you are like me, you enjoy discovering new ways to gain insight into what is happening with your code. Especially, when it comes to performance and scalability. And making things as tight and as efficient as possible.<br />
<br />
Writing and executing graphics programs for simulations and games can be quite taxing on CPU resources. I say that because I got real concerned with a recent program I wrote called Life which simulates digital cellular life forms that grow, prosper or perish in a colony of peers based on some simple growth rules (for more information, google: game of life wiki conway). Here are sample graphics of a few time slices of an animated "snowflake". Other shapes and life forms are possible.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiStf3K1zhl97re_2iOMJc_psNsYT1Jp_aT1tz2pa6Ec41rWTygEzY4NdM34A0alKMYuhsYi40FiM8T5qGy_arlW4dHk_OzM3zZFTzsTVh8QLkF18avhHk-y3JeMi_Xex2M9JK7/s1600/snowflake1.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="122" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiStf3K1zhl97re_2iOMJc_psNsYT1Jp_aT1tz2pa6Ec41rWTygEzY4NdM34A0alKMYuhsYi40FiM8T5qGy_arlW4dHk_OzM3zZFTzsTVh8QLkF18avhHk-y3JeMi_Xex2M9JK7/s200/snowflake1.png" width="200" /></a></div>
<br />
<br />
On my first iteration of the code, I wanted to understand why my
program was taxing the CPU at what appeared to be a steady 15%
utilization in the OSX Activity Monitor. I wanted more details on
what was happening. <br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSQrUyT6aHyaKoqJO_T6zd75d7o7saqy2n7Ga0nqCEt7dsYZj1l2bHTFRi7ATgQ9kbA-SuiyUO1GyD8_AyH8bEOvXR5edVDo_T3wPzwW45mq1WvL1jUfAyreTLhEU9wVDBBS30/s1600/snowflake2.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="123" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSQrUyT6aHyaKoqJO_T6zd75d7o7saqy2n7Ga0nqCEt7dsYZj1l2bHTFRi7ATgQ9kbA-SuiyUO1GyD8_AyH8bEOvXR5edVDo_T3wPzwW45mq1WvL1jUfAyreTLhEU9wVDBBS30/s200/snowflake2.png" width="200" /></a></div>
<br />
<br />
In the code, I also made the main simulation loop as tight as possible, eliminating any extraneous calls or
assignments, and passing any large data structures to functions by
reference only.<br />
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJSOQmzLoew6dkqaYKGbOOrAR5XMWgkhsjJtYlEVCJX5OSbWMpC25se5A8DAMRFKricpfezhXdCOK25CXMBQ6ur2u-zcf6VWM__LYgBL9dVRG1f2Z30LU-VGKjZ-3fOsZ7BTcV/s1600/snowflake3.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="122" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJSOQmzLoew6dkqaYKGbOOrAR5XMWgkhsjJtYlEVCJX5OSbWMpC25se5A8DAMRFKricpfezhXdCOK25CXMBQ6ur2u-zcf6VWM__LYgBL9dVRG1f2Z30LU-VGKjZ-3fOsZ7BTcV/s200/snowflake3.png" width="200" /></a></div>
<br />
<br />
With that accomplished, my investigations led to parts of the code that
were called most often. From there, I would be able to "see" which
routines or calls were taking the most time to execute.<br />
<br />
<br />
<br />
To cut to the chase, I intuited that the call that writes pixels to the graphics palette was exhibiting the most influence on the time profile. In fact, the code, prior to performance enhancement, looked like this:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOQADFHPPg0mPfz8aY14Nu249gVIzv_mH3gTOgKRU8WX7WS-v-o-5zoj4PD_NuIxNXkeg_BNBfJvtWbGoDr4P3pKnwmeloCt6qj_kH2MLQ1Pwte_9ZtDYyIlR6h11sng7ZwW6z/s1600/DrawGrid1.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="108" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOQADFHPPg0mPfz8aY14Nu249gVIzv_mH3gTOgKRU8WX7WS-v-o-5zoj4PD_NuIxNXkeg_BNBfJvtWbGoDr4P3pKnwmeloCt6qj_kH2MLQ1Pwte_9ZtDYyIlR6h11sng7ZwW6z/s320/DrawGrid1.png" width="320" /></a></div>
Obviously, DrawCellAt() is called the most. This is a "free" library function (not a class) (I have access to the source for further inspection).<br />
<br />
<br />
<br />
<br />
So what's happening? Prior to this, the grid is continually inspected and updated based on the Life growth rules. After that, the next generation of life is determined and stored in the gridLife variable, then DrawCellAt is called for every cell in the grid.... every cell in the grid.... ouch! Even for cells that are now empty due to a life form that recently died and even for cells that are basically serving background, DrawCellAt() is called. Hmmm... that's expensive, CPU-wise.<br />
<br />
So again, what's happening? Well, Here's one way to answer this. I know that the graphics palette is 21 rows x 30 columns or 630 cells and the snowflake is on average 50 cells. Assuming on the next generation, it is also 50 cells, then on average, about ~10-20% of the cells will need updating, either alive or dead, to keep the animation moving.
But if the code is blindly updating all 630 cells, whether it had or has life or
not, there are slim chances to achieve any efficiency. What is needed is some
way to "compress" the data that is written to the graphics palette. <br />
<br />
So I rewrote the routine to flush the graphics palette and tighten the loop to only call DrawCellAt() when there is "life" in the next-generation cell:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2d35i_WGkKrpzQ5zAjZB6vAFn_1q2Wc48HGM5rZWNfuT_cEQCN0BOG5nWjzd_O1OYtVU9FnjKuQTrwPgjY0BKwfi7ihDan7FuD_1HZbcCcitzGJXB66dB7YZ_PCrgZGaSu5Fb/s1600/DrawGrid2.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="145" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2d35i_WGkKrpzQ5zAjZB6vAFn_1q2Wc48HGM5rZWNfuT_cEQCN0BOG5nWjzd_O1OYtVU9FnjKuQTrwPgjY0BKwfi7ihDan7FuD_1HZbcCcitzGJXB66dB7YZ_PCrgZGaSu5Fb/s400/DrawGrid2.png" width="400" /></a></div>
<br />
The result? A 5x to 7x improvement in CPU % utilization (down to ~3%). That's pretty good.<br />
<br />
<br />
<br />
<br />
<br />
So what's really happening? <br />
<br />
<span style="font-size: large;"><i><b>Enter Xcode Profiling!</b></i></span><br />
<br />
Profiling is an Xcode compiler option can be invoked while developing, executing and testing code. In this case, I want to "see" the difference between versions 1 and 2 of DrawGrid in terms of CPU resource utilization within the code itself.<br />
<br />
Here is the quick HOW-TO procedure:<br />
<br />
If you want to follow along: you can get the source here and load into Xcode:<br />
<br />
<b><span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;">https://github.com/vincemansel/Life</span></span></b><br />
<br />
(Or just git the repo and open the <span style="font-family: "Courier New",Courier,monospace;">Instruments4.trace</span> file. You will need to change Search Paths in Preferences to point to where the source files live.)<br />
<ul>
<li> In Xcode, select the Profile command (Hold the mouse down momentarily on the Run command and several options will appear. Select Profile. </li>
</ul>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQWk-PoEVXibbJOqgd6o9ucpe7CJXvImuglqBzPjFSxj-1CD8qL7vTFf7V53vAeouZxT5SYqoVUAWE519RufJ30rTOvgL2s4htyu7j125RaTXuIVEOpDgnMb_cbl9gjvgQHtDT/s1600/XCode_Run.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQWk-PoEVXibbJOqgd6o9ucpe7CJXvImuglqBzPjFSxj-1CD8qL7vTFf7V53vAeouZxT5SYqoVUAWE519RufJ30rTOvgL2s4htyu7j125RaTXuIVEOpDgnMb_cbl9gjvgQHtDT/s1600/XCode_Run.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuBL01yS4JtrBKa29M9JSTxA0u8kfaf8coQ4aFK3qC5jw6DER8TJbmbiD4bz-FWJYc7kT5fCHBk17OYa_sIAAn6BmYe1ZojMWmhzf-z2niSJOGf5m15YJ3_hL93Q-hCMAF_IQ9/s1600/Xcode_Profile.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuBL01yS4JtrBKa29M9JSTxA0u8kfaf8coQ4aFK3qC5jw6DER8TJbmbiD4bz-FWJYc7kT5fCHBk17OYa_sIAAn6BmYe1ZojMWmhzf-z2niSJOGf5m15YJ3_hL93Q-hCMAF_IQ9/s1600/Xcode_Profile.png" /></a></div>
<br />
<ul>
<li>This launches "Instruments" which provides profile options. Choose Time Profiler.</li>
</ul>
<ol>
</ol>
<ul>
<li>This starts "Life", the program to profile. Enter parameters into Life to execute the simulation. (I simulated the snowflake file on level 2, Plateau mode). </li>
</ul>
<ul>
<li>I am interested in writes to the graphics palette. Capture about 10 seconds of data and kill the process, or stop Recording data.</li>
</ul>
<ol>
</ol>
<ul>
<li>Do this for both versions of the program (i.e. one with DrawGrid1 and one with DrawGrid2)</li>
</ul>
<ol>
</ol>
<ul>
<li>Analyze the data as follows: </li>
</ul>
<ol>
</ol>
The Instrument will show a time graph of the program CPU usage by default. The time graph is 100ms/pixel.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_ZQONnyT1OAgH-da-Ee2l4XasLt90-46KZmEKOsBTULpTyqqdIWZuIE6CUMIE_fBx87CNgDtFH6FUGGbfOfd-Q8YU5ywcJXJsyomAVer4FsBdm-jncjh8guxyiODU1ADkrOxp/s1600/Instruments1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="244" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_ZQONnyT1OAgH-da-Ee2l4XasLt90-46KZmEKOsBTULpTyqqdIWZuIE6CUMIE_fBx87CNgDtFH6FUGGbfOfd-Q8YU5ywcJXJsyomAVer4FsBdm-jncjh8guxyiODU1ADkrOxp/s640/Instruments1.png" width="640" /></a></div>
<br />
<br />
I can also open up the Extended Detail panel on the right side of the window. This shows a stack trace for DrawGrid() and beyond.<br />
<br />
Since Time Profiler is compressing the time line, expand it so it looks like this (~500us/pixel).<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUGJyi9npVVdBZqxFdQG-jDSnrHKlQdnM3t-ONoShoCS0_giwfMFrVCklj_FKUVtf3VQcDpJXV0Ag197dX9FO3J3fgUfMphyphenhyphenVUBrWlwIKZy7-0tlrh4ZYMVLpPK4_z1Q5BN03S/s1600/Instruments2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="305" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUGJyi9npVVdBZqxFdQG-jDSnrHKlQdnM3t-ONoShoCS0_giwfMFrVCklj_FKUVtf3VQcDpJXV0Ag197dX9FO3J3fgUfMphyphenhyphenVUBrWlwIKZy7-0tlrh4ZYMVLpPK4_z1Q5BN03S/s640/Instruments2.png" width="640" /></a></div>
<br />
<br />
In the Sample List, select a sample to hightlight. Note it is highlighted where the "scrubber" or time-marker is currently placed. Use the up or down arrow to scroll through the timeline, jumping from sample to sample. Any sample will do that indicates the code is currently running in the Life process.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJ3TxjnZ7NrR4cGdrzCnoUZzAxbdCBrOdQcDFe_8xz5oQKZuJzxb7oUcxHuUf6b8xWCwjRujRplCWqp_uRPFRFAIVrwMySZFLMVDJxLuqbK2ZHvOEmeNR2tA7NTWQLSvZFbRNq/s1600/Instruments_SampleList1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="80" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJ3TxjnZ7NrR4cGdrzCnoUZzAxbdCBrOdQcDFe_8xz5oQKZuJzxb7oUcxHuUf6b8xWCwjRujRplCWqp_uRPFRFAIVrwMySZFLMVDJxLuqbK2ZHvOEmeNR2tA7NTWQLSvZFbRNq/s640/Instruments_SampleList1.png" width="640" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_qC8DyQTapMc37hDP9sNmeD7tjZL1m8UgDK1PCUhl_OTKfkp3AqpwWg2tt8bQQrHnoLIcvPQrbWa6o-JGFhkXtTXpAJyidf7Erw1P8Mdy2o9FTzmCnPlY_4pIUfNmgY_ElhKv/s1600/Instruments_ExtendedDetail1.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_qC8DyQTapMc37hDP9sNmeD7tjZL1m8UgDK1PCUhl_OTKfkp3AqpwWg2tt8bQQrHnoLIcvPQrbWa6o-JGFhkXtTXpAJyidf7Erw1P8Mdy2o9FTzmCnPlY_4pIUfNmgY_ElhKv/s200/Instruments_ExtendedDetail1.png" width="121" /></a></div>
<br />
<br />
<br />
In the Extended Detail panel, I see the call list that I am
interested in. So I first double-click RunLifeSim() to determine how much
"time" the program is spending in DrawGrid().<br />
<br />
This opens a window directly into the code:<br />
<br />
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNquV_VX0LvFuCz7DHSsYc5YTDTN53RUjPoe6layh0ppOa_gJGcqD5u7kb4cOw-qssHQDkFnSGiZxhgfqI2UWwxBwmt_oG-x-0-SXDqjaASpSoixl5S_IACQ4sbI86kvH9pC_f/s1600/Instruments_RunLifeSIm1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="603" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNquV_VX0LvFuCz7DHSsYc5YTDTN53RUjPoe6layh0ppOa_gJGcqD5u7kb4cOw-qssHQDkFnSGiZxhgfqI2UWwxBwmt_oG-x-0-SXDqjaASpSoixl5S_IACQ4sbI86kvH9pC_f/s640/Instruments_RunLifeSIm1.png" width="640" /></a></div>
<br />
<br />
I see that DrawGrid occupies over 99% of the resources in this function.<br />
<br />
I can go further.... click back to the SampleList.... double-click on DrawGrid() in the Extended Detail panel.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrUNLYxCMfHS5DkmZVRuqO2xd88qyaYYdco8ON6gKvIOufJ7b2a7wHLgWI5OAKZlB35lrnIqvMYmWs_XLo8dejYvWlumPBKHADaZehBNHFIJ-oRV6HigPL04btK0az4cSM-jS4/s1600/Instruments_DrawGrid1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="176" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrUNLYxCMfHS5DkmZVRuqO2xd88qyaYYdco8ON6gKvIOufJ7b2a7wHLgWI5OAKZlB35lrnIqvMYmWs_XLo8dejYvWlumPBKHADaZehBNHFIJ-oRV6HigPL04btK0az4cSM-jS4/s640/Instruments_DrawGrid1.png" width="640" /></a></div>
<br />
<br />
Aha, 100%. This is making sense. But I want to go further.... open DrawCellAt()... open DrawFilledCircle()... <br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7GCx00Zuwksm-q42dGbcc1V54vUjxxwY7__7h_079Q-uaoBek06VdlWX4cMU2F7G9q4TrNcaIdWKR95ahqCkmZuklDxtunYBR6zDF6AAG03ewZx4S5a9niL9WcRIZfVo41rPL/s1600/Instruments_DrawCellAt1.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="130" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7GCx00Zuwksm-q42dGbcc1V54vUjxxwY7__7h_079Q-uaoBek06VdlWX4cMU2F7G9q4TrNcaIdWKR95ahqCkmZuklDxtunYBR6zDF6AAG03ewZx4S5a9niL9WcRIZfVo41rPL/s640/Instruments_DrawCellAt1.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><i><span style="font-size: small;">DrawCellAt() - Hmmm...</span></i></td></tr>
</tbody></table>
<br />
<br />
This gives me an indication of what is taking up time to do the work. It does not tell me how or what to fix but insight is gained into the inner workings of the code...<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8-3UccDpYJjtRgHHiMSTZdQMDZdNPUpzx_bVwFtNQQW5Kn8CvuNaXO-bFxD39PKnHU5C_l2VvOqIy64FWYIyGhI8AwBKgalO4OlVghX73aovBYRM27wcUUc4wHQJV3Vu4DLdD/s1600/Insert+Instruments_DrawFilledCircle1.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="140" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8-3UccDpYJjtRgHHiMSTZdQMDZdNPUpzx_bVwFtNQQW5Kn8CvuNaXO-bFxD39PKnHU5C_l2VvOqIy64FWYIyGhI8AwBKgalO4OlVghX73aovBYRM27wcUUc4wHQJV3Vu4DLdD/s640/Insert+Instruments_DrawFilledCircle1.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><i><span style="font-size: small;">DrawFilledCircle() - Too deep, but interesting...</span></i></td></tr>
</tbody></table>
<br />
Now, what about DrawGrid2. Where is the improvement? I want to "see" it. Check it out:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPOKOz_YMeMcskmND_hSuaO1U1CssL8hI_ffaZaDD-G1MJHHdIPyWMbQvW5AuMdMEu1-vjOtSfA7-ZWi4EjnZaJ-E422bYEXTZjiKbghMcJLPR4gg9oEHA8Gm9UFcJrjnergVC/s1600/Instruments3.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="299" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPOKOz_YMeMcskmND_hSuaO1U1CssL8hI_ffaZaDD-G1MJHHdIPyWMbQvW5AuMdMEu1-vjOtSfA7-ZWi4EjnZaJ-E422bYEXTZjiKbghMcJLPR4gg9oEHA8Gm9UFcJrjnergVC/s640/Instruments3.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><i><span style="font-size: small;">Every update interval results in a smaller burst of CPU usage.</span></i></td></tr>
</tbody></table>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLqKL8b0_AdnuLQCsfG9rPKvv9RW3FHQrRM5Fx-7rpyhuI49ZgENUPyd6swjzLWgM0ZilmwB-pLGl6st3U3hYnWSiIBgIBl2bb3GJyGAw0pdq2GVFhhgtxoIo_HlomdcZ5zImQ/s1600/Instruments_RunLifeSIm2.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="600" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLqKL8b0_AdnuLQCsfG9rPKvv9RW3FHQrRM5Fx-7rpyhuI49ZgENUPyd6swjzLWgM0ZilmwB-pLGl6st3U3hYnWSiIBgIBl2bb3GJyGAw0pdq2GVFhhgtxoIo_HlomdcZ5zImQ/s640/Instruments_RunLifeSIm2.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><i><span style="font-size: small;">RunLifeSim() - I see improvement!!!</span></i></td></tr>
</tbody></table>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRG-YmGVYUIm05MSYcdANXiJijvSlJbKkF_8VLyUu-BPQ-VUYb6u9ZS83mplgpCNbJCzM-41-uYdAh08tUIWHsyP1XJ1iyzVg2khMrBdnfNs6OtfhLqOHK9GnbPADk2EUM-YbW/s1600/Instruments_DrawGrid2.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRG-YmGVYUIm05MSYcdANXiJijvSlJbKkF_8VLyUu-BPQ-VUYb6u9ZS83mplgpCNbJCzM-41-uYdAh08tUIWHsyP1XJ1iyzVg2khMrBdnfNs6OtfhLqOHK9GnbPADk2EUM-YbW/s640/Instruments_DrawGrid2.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-size: small;"><i>DrawGrid() - I see a little bit here too!</i></span></td></tr>
</tbody></table>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhp_AAulKJibKxRIPkprBRELO0KUpjDyJftGY9OLTL_rLi9QFpPJpUzSXCcY7AfpAGvxurkZi34uCCvtsLk-04lSZMAKacjbiCqUQ_eqnN5C24lo_6tcXQ7vfR5f3FDRbYToYWK/s1600/Instruments_DrawCellAt2.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="176" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhp_AAulKJibKxRIPkprBRELO0KUpjDyJftGY9OLTL_rLi9QFpPJpUzSXCcY7AfpAGvxurkZi34uCCvtsLk-04lSZMAKacjbiCqUQ_eqnN5C24lo_6tcXQ7vfR5f3FDRbYToYWK/s640/Instruments_DrawCellAt2.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-size: small;"><i>DrawCellAt2() - This works on a cell by cell basis. No improvement here.</i></span></td></tr>
</tbody></table>
<br />
Reducing the number of calls to DrawCellAt() (or compressing the amount of graphics data written) reduces the amount of
resources that DrawGrid() is taking as a percentage of the overall program. <br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwmsD_MWLLtyi9opAFNYsVmJJbgOswsxH4M9Rl2oQLVmgFssQc_-2ijZGksEkZIq5wGrmyq04zncVCjBQYQ6wzrj0lj4IDrKoKBTf41s6UTuEufoXecRExFbwCn-_QByj9f8iu/s1600/Instruments_DrawGridTime1.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="177" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwmsD_MWLLtyi9opAFNYsVmJJbgOswsxH4M9Rl2oQLVmgFssQc_-2ijZGksEkZIq5wGrmyq04zncVCjBQYQ6wzrj0lj4IDrKoKBTf41s6UTuEufoXecRExFbwCn-_QByj9f8iu/s320/Instruments_DrawGridTime1.png" width="320" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNuirUOtdzswSF1CcqFKil1SK7mCmK0I8PIVkddONFmiS8dpOkn-JQfl5S23ufQLBHeOIS86CTLtIDs0gEmKz_mGvN3acnnko4HrT-_eH6uymxlo5E2EJj4T70rVNQIs0-UvRj/s1600/Instruments_DrawGridTime2.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="169" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNuirUOtdzswSF1CcqFKil1SK7mCmK0I8PIVkddONFmiS8dpOkn-JQfl5S23ufQLBHeOIS86CTLtIDs0gEmKz_mGvN3acnnko4HrT-_eH6uymxlo5E2EJj4T70rVNQIs0-UvRj/s320/Instruments_DrawGridTime2.png" width="320" /></a></div>
<br />
<br />
Also note the reduction in time that the code is taking every update interval (0.5 seconds). I reduced the time scale down to 50 us/pixel, For DrawGrid1, the "time burst" is 14.160 msec.<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
For DrawGrid2, it is 0.954 msec!<br />
<b>A 14x improvement!!! </b><br />
Awesome!<br />
<br />
<br />
<br />
<br />
Recap: 14x improvement in the code. 5x - 7x improvement at the process level. Done.<br />
<br />
That was fun!<br />
<br />
Code for Life and the Instruments trace file is available here:<br />
<br />
<b><span style="font-family: "Courier New",Courier,monospace;">https://github.com/vincemansel/Life</span></b><br />
<br />
Life was developed and executed on a MacPro, 2 x 2.8 GHz Quad-Core Intel Xeon with 8GB 800MHz DDR2 F8-DIMM and OSX Version 10.7.1 with Xcode Version 4.1 Build 4B110.<br />
<br />
Acknowledgements to the folks over at Stanford Computer Science (SEE) for the LIfeGraphics resources and the underlying utility programs. You can find them on ItunesU.<br />
<br />
Send me a comment. Or follow my links to get in touch.<br />
<br />
Thanks, Vince <br />
<br />Vincehttp://www.blogger.com/profile/03061125501848592602noreply@blogger.com0tag:blogger.com,1999:blog-19505853.post-16965811544131708092011-09-27T20:19:00.000-07:002011-09-27T21:34:05.662-07:00Chaos Games and Fractals<div style="font-family: Verdana,sans-serif;">
I just attended the HTML5 Developer's Conference in San Francisco. I learned a handful of things about HTML5, JavaScript, Node.js and a checked out a few companies that are doing cool things to allow devs to create apps and port to various mobile platforms.</div>
<div style="font-family: Verdana,sans-serif;">
<br /></div>
<div style="font-family: Verdana,sans-serif;">
During lunch break, I continued working on Chaos game (see <a href="http://en.wikipedia.org/wiki/Chaos_game"><span style="font-family: "Courier New",Courier,monospace;">http://en.wikipedia.org/wiki/Chaos_game</span></a> for more information). Basically, I finished the specification for 3 vertices and discovered, yes, it creates a cool fractalized, coherent graphics image:</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKDIFWeQFE0cVGKRpnwkla9fCoCDivCbth5T2mT3UDssGtgA-OuTplmhCU7YskrTPAKz3VanDUrbeBgMRb17GW3Au0dNrQqutLvOvAIeAhRa63lNFCI_qOyTOdZuCyCBCVhI30/s1600/chaos_3_2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="269" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKDIFWeQFE0cVGKRpnwkla9fCoCDivCbth5T2mT3UDssGtgA-OuTplmhCU7YskrTPAKz3VanDUrbeBgMRb17GW3Au0dNrQqutLvOvAIeAhRa63lNFCI_qOyTOdZuCyCBCVhI30/s400/chaos_3_2.png" width="400" /></a></div>
<div style="font-family: Verdana,sans-serif;">
The algorithm is basically this:</div>
<div style="font-family: Verdana,sans-serif;">
1) Ask the user to click three points in the window. These become the 3 vertices of a triangle. Draw lines between the 3 points. Choose one vertex at random.</div>
<div style="font-family: Verdana,sans-serif;">
2) Draw a small circle at that point.</div>
<div style="font-family: Verdana,sans-serif;">
3) Choose another vertex and move the current point 1/2 the distance towards that vertex.</div>
<div style="font-family: Verdana,sans-serif;">
4) Repeat steps 2 and 3 until the user clicks the mouse again.</div>
<div style="font-family: Verdana,sans-serif;">
<br /></div>
<div style="font-family: Verdana,sans-serif;">
Walla! Nice result.</div>
<div style="font-family: Verdana,sans-serif;">
</div>
<div style="font-family: Verdana,sans-serif;">
I decided to extend this a bit to add more vertices. The results were not so spectacular. Then, I decided to change the rendering algorithm every so slightly by changing the divisor to 3. Something interesting occured. A shadow image appears outside the original bounds of the figure drawn out by the user. A run with 6 vertices and a divider of 6 yeilds the following:</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9i2GMvjywoY8LbeoruDuve-erU9Yo9dRilc9DHoWkz5KDWnLR9XQA231uLaIPtRaM3hEs0vQ2xn_1sDZAbK54qX0lyYRfV41KkndsBgNTU7P8EECjB1jBG-A6lcjcJK4EiFP5/s1600/chaos_6_6.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="325" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9i2GMvjywoY8LbeoruDuve-erU9Yo9dRilc9DHoWkz5KDWnLR9XQA231uLaIPtRaM3hEs0vQ2xn_1sDZAbK54qX0lyYRfV41KkndsBgNTU7P8EECjB1jBG-A6lcjcJK4EiFP5/s400/chaos_6_6.png" width="400" /></a></div>
<span style="font-family: Verdana,sans-serif;">Try it out. The C++ source and Xcode project are parked at github. Also, you can just run the app on your Mac. It will prompt you for the number of vertices and dividers so you can experiment with shapes of your own. Fractal away! </span><br />
<br />
<pre></pre>
<pre><span style="font-size: large;"><a href="https://github.com/vincemansel/ChaosGame2"><span style="font-size: large;">https://github.com/vincemansel/ChaosGame2</span></a> </span></pre>
<pre><span style="font-size: large;"> </span></pre>
<pre style="font-family: Verdana,sans-serif;"><span style="font-size: small;">Vince</span></pre>
<pre><span style="font-size: large;"> </span></pre>
<pre><span style="font-size: large;"><span style="font-family: Verdana,sans-serif; font-size: x-small;">p.s. Thanks to eroberts at Stanford for the utility libraries. </span></span></pre>
<br />
<br />
<br />
<br />Vincehttp://www.blogger.com/profile/03061125501848592602noreply@blogger.com0tag:blogger.com,1999:blog-19505853.post-20598125950698966002009-05-20T11:31:00.000-07:002009-05-20T12:08:11.935-07:00Obtaining a CCNP in Four MonthsOK... you first have to have some prior <span class="blsp-spelling-error" id="SPELLING_ERROR_0">IP</span> networking experience to be able to understand the language and the concepts. But, if you are focused and dedicated, you can obtain the <span class="blsp-spelling-error" id="SPELLING_ERROR_1">CCNA</span> in a month and the <span class="blsp-spelling-error" id="SPELLING_ERROR_2">CCNP</span> in four months, full-time and probably, one year part-time, through a course of self-study, reading and hands-on lab work. I just obtained the <span class="blsp-spelling-error" id="SPELLING_ERROR_3">CCNP</span> certification last week and the <span class="blsp-spelling-error" id="SPELLING_ERROR_4">CCNA</span> in January.<br /><br />Basically, get copies of the <span class="blsp-spelling-error" id="SPELLING_ERROR_5">Cisco</span> Exam Certification Guides for the <span class="blsp-spelling-error" id="SPELLING_ERROR_6">CCNA</span> and <span class="blsp-spelling-error" id="SPELLING_ERROR_7">CCNP</span>. Check out the <span class="blsp-spelling-error" id="SPELLING_ERROR_8">Cisco</span> Learning Center, especially for Also, obtain a good Video course, like <span class="blsp-spelling-error" id="SPELLING_ERROR_9">CBTNuggets</span> or <span class="blsp-spelling-error" id="SPELLING_ERROR_10">TrainSignal</span>, to introduce the topics and get a broad level perspective.<br /><br />To build your lab, you can find real equipment on <span class="blsp-spelling-error" id="SPELLING_ERROR_11">ebay</span>. But I would suggest purchasing a powerful PC and porting <span class="blsp-spelling-error" id="SPELLING_ERROR_12">GNS</span>3/<span class="blsp-spelling-error" id="SPELLING_ERROR_13">Dynamips</span>, a <span class="blsp-spelling-error" id="SPELLING_ERROR_14">cisco</span> router emulation environment (do a google search). This provides emulated testbed of routers for the <span class="blsp-spelling-error" id="SPELLING_ERROR_15">Cisco</span> 17xx, 26xx, 36xx and 72xx etc, with real <span class="blsp-spelling-error" id="SPELLING_ERROR_16">IOS</span> capabilities. There is also enough coverage for <span class="blsp-spelling-error" id="SPELLING_ERROR_17">VLANs</span>, Layer 3 switching and trunking with the <span class="blsp-spelling-error" id="SPELLING_ERROR_18">NSM</span> module on some of the routers. I was able to emulate up to 9 routers on Windows <span class="blsp-spelling-error" id="SPELLING_ERROR_19">XP</span> running over OS-X 10.5.x <span class="blsp-spelling-error" id="SPELLING_ERROR_20">bootcamp</span> on a 2.8 GHz Quad Core <span class="blsp-spelling-error" id="SPELLING_ERROR_21">MacPro</span>.<br /><br />Here are some of the areas that I enjoyed studying and a have very strong knowledge.<br />Most of these of these topics are covered with hands-on labs.<br /><br /><span style="font-family:Verdana;">• Routing: <span class="blsp-spelling-error" id="SPELLING_ERROR_22">OSPF</span>/<span class="blsp-spelling-error" id="SPELLING_ERROR_23">EIGRP</span>/<span class="blsp-spelling-error" id="SPELLING_ERROR_24">BGP</span>/IS-IS, <span class="blsp-spelling-error" id="SPELLING_ERROR_25">MPLS</span>, <span class="blsp-spelling-error" id="SPELLING_ERROR_26">IP</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_27">Multicast</span>, <span class="blsp-spelling-error" id="SPELLING_ERROR_28">PIM</span>, <span class="blsp-spelling-error" id="SPELLING_ERROR_29">IGMP</span>, Frame Relay, NAT<br />• Layer 2/3 Switching: <span class="blsp-spelling-error" id="SPELLING_ERROR_30">VLANs</span>, 802.1Q, <span class="blsp-spelling-error" id="SPELLING_ERROR_31">RSTP</span>, <span class="blsp-spelling-error" id="SPELLING_ERROR_32">HSRP</span>, <span class="blsp-spelling-error" id="SPELLING_ERROR_33">PPPoE</span>, <span class="blsp-spelling-error" id="SPELLING_ERROR_34">PPPoA</span><br />• Security and Services: <span class="blsp-spelling-error" id="SPELLING_ERROR_35">IPSec</span>, <span class="blsp-spelling-error" id="SPELLING_ERROR_36">GRE</span>, Radius/AAA, <span class="blsp-spelling-error" id="SPELLING_ERROR_37">VPNs</span>, SSH, 802.1X, <span class="blsp-spelling-error" id="SPELLING_ERROR_38">VoIP</span>, Wireless</span><br /><span style="font-family:Verdana;">• <span class="blsp-spelling-error" id="SPELLING_ERROR_39">QoS</span>: Queuing, <span class="blsp-spelling-error" id="SPELLING_ERROR_40">DSCP</span>, Congestion Management/Avoidance, Traffic Shaping/Policing, <span class="blsp-spelling-error" id="SPELLING_ERROR_41">NBAR</span> </span><br /><br />Wireless and <span class="blsp-spelling-error" id="SPELLING_ERROR_42">VoIP</span> require additional hardware, and you will also need to obtain a copy<br />a copy of the <span class="blsp-spelling-error" id="SPELLING_ERROR_43">Cisco</span> <span class="blsp-spelling-error" id="SPELLING_ERROR_44">SDM</span> for some labs.<br /><br />Plan on 6-8 hours per day, 5 to 6 days per week.<br />I took the two test route for the <span class="blsp-spelling-error" id="SPELLING_ERROR_45">CCNA</span>. The <span class="blsp-spelling-error" id="SPELLING_ERROR_46">CCNP</span> consists of four exams, about 1 per month.<br />Add a week additional time in case you fail and exam and need to re-take (like I did on the <span class="blsp-spelling-error" id="SPELLING_ERROR_47">BSCI</span>). I needed to pace myself with the <span class="blsp-spelling-error" id="SPELLING_ERROR_48">BSCI</span> lab work because of the amount of fun I had doing the configurations and debug. The <span class="blsp-spelling-error" id="SPELLING_ERROR_49">BSCI</span> was the hardest and most people, I hear, opt to take<br />it last. I took it first and it provided a solid foundation for all the other exams. Here is a <span class="blsp-spelling-error" id="SPELLING_ERROR_50">BGP</span> lab layout from a configuration lab.<br /><br /><br /><div style="text-align: center;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMslRo_Jrwyb84tcY1gp-lj7PF8jPnljI-4STj5c-eJNBKuFUqayr0kb5CKV_zne-IC7UDftZ6pswFI7rkpE9UfhhYKfm5WiAjVW6DGdEeSHzyEqztg4Ll4hpaRl3-VkWznB_X/s1600-h/BSCI_BGP.png"><img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 320px; height: 254px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMslRo_Jrwyb84tcY1gp-lj7PF8jPnljI-4STj5c-eJNBKuFUqayr0kb5CKV_zne-IC7UDftZ6pswFI7rkpE9UfhhYKfm5WiAjVW6DGdEeSHzyEqztg4Ll4hpaRl3-VkWznB_X/s320/BSCI_BGP.png" alt="" id="BLOGGER_PHOTO_ID_5337984484535124178" border="0" /></a><br /></div><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />Go for it! You can do it!Vincehttp://www.blogger.com/profile/03061125501848592602noreply@blogger.com7tag:blogger.com,1999:blog-19505853.post-13772566283576702642009-02-12T02:04:00.001-08:002009-02-12T03:05:39.751-08:00Filter a RIP route with Distribute ListThis one seems worthy of a blog post. Previously, I discovered some esoterically cool stuff about auto-summarization and how in RIPv2, it is possible to create routing "blackholes" when certain routes are auto-summarized across classful boundaries then fed back to the originator of the route. The originator of the route then point back to the routers that auto-summarized the route. The network is a circular so eventually split-horizon stops the route update madness. Bottom line, pings to anything unknown address in the 10.0.0.0/8 network will loop between two routers until the TTL expires. This came about in my final lab ICND2 lab studies. Check out the ICND2 Certification Guide, Appendix F, last question and check the output of the show ip route command. Turns out, EIGRP stops this kind of thing cold with the clever Null0 bit bucket.<br /><br />But on to the subject of the day.<br /><br />I discovered how to use a distribute-list to filter a RIPv2 update. The whole exercise was a prelude to how to summarize (there's that word again) external RIP routes into a OSPF network across an Autonomous System Boundary Router (ASBR). The problem became how to start with a clean network where none of the OSPF networks were leaking into the RIP domain and none of the RIP routes were spilling into the OSPF domain. I use those words because I lack the technical-speak for the situation. Suffice it to say, my studies and meanderings have paid off with a nice solution.<br /><br /><br />Check out the diagram.<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhipfNX2XSaRMfpKg5BmcibgUZTkQu8bsrd5GurX_vRUf_k1kvZZR_x6GQxKBZCanMy5YrXnl3bU33eGJBFmCk7TCvc61p5MosB6Wd29V6z2OfAT4FpaQEvKOld3-zGdvBN6_a-/s1600-h/BSCI_OSPF_ASBR_Filter.png"><img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 400px; height: 342px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhipfNX2XSaRMfpKg5BmcibgUZTkQu8bsrd5GurX_vRUf_k1kvZZR_x6GQxKBZCanMy5YrXnl3bU33eGJBFmCk7TCvc61p5MosB6Wd29V6z2OfAT4FpaQEvKOld3-zGdvBN6_a-/s400/BSCI_OSPF_ASBR_Filter.png" alt="" id="BLOGGER_PHOTO_ID_5301865174313859058" border="0" /></a> The ASBR, R4, is running RIPv2 and OSPF. Each serial interface is in the 10.0.0.0/8 network. Since the network command in RIP only accepts classful networks, both S1/0 and S1/1 are included in the RIP process. So a <span style="font-weight: bold;">passive-interface Serial 1/1</span> prevents the RIP advertisement leakage into the OSPF side of the R4.<br /><br />Looking at the route table on R5, the 10.1.34.0/30 network is advertised since it is a connected interface on R4. That is really not desired because it exposes a part of the OSPF backbone network to the external network. Plus a ping from R5 to R3's S1/0 interface would go unanswered anyway. Investigating the <span style="font-weight: bold;">distribute-list</span> command allows for filtering routes based on an access-list. Creating an access-list that denies the subnet address (source address) and attaching itto the outgoing side of R4's Serial 1/0 interface filters the route. In fact, running <span style="font-weight: bold;">debug ip rip</span> displays "suppressing null update" for the update going out Serial 1/0. The configuration is listed in the diagram.<br /><br />Using a<span style="font-weight: bold;"> passive-interface</span> command on Serial1/0 would also work to suppress the RIP update, but it would defeat redistributing any learned routes to the external RIP domain from R4. That does not seem desirable since the next step in this investigation will be how to get networks in Area 1 (192.168.x.x/16) to talk to networks in the RIP domain (172.16.x.x/16) without using a static route and not exposing any details about Area 0 to RIP. Neat trick... later.Vincehttp://www.blogger.com/profile/03061125501848592602noreply@blogger.com0tag:blogger.com,1999:blog-19505853.post-36729900168184398742009-01-31T10:42:00.001-08:002009-01-31T11:29:30.882-08:00EIGRP: Say Hello to your Neighbors before UpdatingI ran across this issue in my CCNA Frame Relay configuration lab studies. After creating a full mesh network in one IP subnet between R1 (Mayberry), R2 (Mount Pilot) and R3 (Raleigh) (see CCNA-ICND2 Exam Cert. Guide, Odom, page 489), and having that work (no big deal, all defaults work just fine), I moved on to testing the requirement of having R3 simulate a non-Cisco router which used ietf encapsulation between the LAPF headers and payload (RFC 1490/2474). No big deal. The encapsulation works just fine. The crux of this issue lies elsewhere.<br /><br />The exercise, on page 491, states that R1 (a Cisco router) must accommodate R3 by using ietf encapsulation on a frame relay map command. Here is the tricky part. The specific command of interest in Example 14-4 is replaced by a correction in the errata. The errata states the line should be "frame-relay map ip 199.1.1.3 53 ietf". Therein lies the problem. The "authoritative" errata needs an errata!!!<br /><br />Here are the full configs:<br /><br />R1:<br />interface serial0/0/0<br />encapsulation frame-relay<br />frame-relay lmi-type ansi<br />frame-relay interface-dlci 53 ietf !!!!! <--- watch out<br />ip address 199.1.1.1 255.255.255.0<br /><br />interface fastethernet 0/0<br />ip address 199.1.10.1 255.255.255.0<br />!<br />router eigrp 1<br />network 199.1.1.0<br />network 199.1.10.0<br /><br /><br />R3:<br />interface serial0/0/0<br />encapsulation frame-relay ietf<br />ip address 199.1.1.3 255.255.255.0<br /><br />interface fastethernet 0/0<br />ip address 199.1.12.3 255.255.255.0<br />!<br />router eigrp 1<br />network 199.1.1.0<br />network 199.1.12.0<br /><br />Both routers are configured for EIGRP on the their networks. As soon as both links come up, both routers send EIGRP Hellos to each other. R1 quickly creates an adjacency with R3 and immediately sends Update packets. R3 does not do the same.<br /><br />Hmmm. Inspecting "show ip eigrp neighbors" on R1 displays R3 but a "1" is showing up under the Q column. This means it has sent a message and is awaiting an acknowledgement (I surmise this is a function of RTP - Reliable Transport Protocol). After a time, R1 gives up due to too many retransmissions of it original update. R3's serial interface can be ping'd but that is it.<br /><br />Meanwhile, on R3, it is receiving updates but not forming neighbors with R1. Why? Because it never hears a Hello from R1. Inspecting "debug eigrp packets", an Update is received from R1 but EIGRP indicates "Neighbor (199.1.1.1) not yet found". What!? Can't you hear it talking to you?<br /><br />Turns out R1 is not forwarding broadcast (or multicast) over the PVC to R3. EIGRP Hellos are multicast on 224.0.0.10. And the authoritative frame-relay map command was not set with the broadcast option.<br /><br />So here is the correct config for R1:<br /><br />R1:<br />interface serial0/0/0<br />encapsulation frame-relay<br />frame-relay lmi-type ansi<br />frame-relay interface-dlci 53 ietf broadcast !!!!! <--- Aha!!!<br />ip address 199.1.1.1 255.255.255.0<br /><br />Neighbor relations form, updates are exchanged, routing tables filled. Ahhh! Life is good! Also, all of this was confirmed via Wireshark for good measure.<br /><br />Interesting... a router in OSPF will not even start sending updates unless it receives back a Hello with it's IP address in it. But that a different story for<br /><br />Moral: Say Hello to your neighbors! And make sure they have heard you before giving them the latest news update.Vincehttp://www.blogger.com/profile/03061125501848592602noreply@blogger.com1tag:blogger.com,1999:blog-19505853.post-1133498920980822542005-12-01T20:39:00.000-08:002005-12-02T01:15:33.446-08:00Kudos on a GTK2-Perl/GladeXML Article<pre style="font-family:verdana;"><span style="font-size:100%;">Before I move on to another task, just<br />wanted to ack Grant McLean for the great article:<br /><br /><a href="http://live.gnome.org/GTK2-Perl/GladeXML/Tutorial" target="_blank">http://live.gnome.org/GTK2-Perl/GladeXML/Tutorial</a><br /><br />It served up the right amount of information and depth<br />to get going. Nice insights to move me from basic command<br />line based code to OO and GUI ... I know, I know...<br />it's still a long road.<br /><br />A couple of goodies that I figured out:<br /><br />1. Where to go to get Class::Accessor::Fast (CPAN)<br />2. This snippet of code in the init method implied by Figure 7:<br /><br /></span></pre> <div style="text-align: left;"><span style=";font-family:courier new;font-size:100%;" >if($self->auto_sounds->get_active) {</span><br /><span style=";font-family:courier new;font-size:100%;" > $self->enable_auto_sounds;</span><br /><span style=";font-family:courier new;font-size:100%;" > }</span><br /><span style=";font-family:courier new;font-size:100%;" >else {</span><br /><span style=";font-family:courier new;font-size:100%;" > $self->disable_auto_sounds;</span><br /><span style=";font-family:courier new;font-size:100%;" > }</span><br /></div> <pre style="font-family:verdana;"><span style="font-size:100%;"><br />I extended the timer app per Grant's suggestion.<br />The only thing I did not do was the packaging, but I am sure<br />I will return to that paragraph for advice...<br /><br />Cheers, Vince</span></pre>Vincehttp://www.blogger.com/profile/03061125501848592602noreply@blogger.com0