<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Olivier Coudert&#039;s Blog</title>
	<atom:link href="http://www.ocoudert.com/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.ocoudert.com/blog</link>
	<description>My take on tech --and other topics</description>
	<lastBuildDate>Sat, 21 Jan 2012 20:30:18 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Why Synopsys buying Magma is good</title>
		<link>http://www.ocoudert.com/blog/2011/12/18/why-synopsys-buying-magma-is-good/</link>
		<comments>http://www.ocoudert.com/blog/2011/12/18/why-synopsys-buying-magma-is-good/#comments</comments>
		<pubDate>Mon, 19 Dec 2011 02:41:16 +0000</pubDate>
		<dc:creator>Olivier Coudert</dc:creator>
				<category><![CDATA[EDA]]></category>

		<guid isPermaLink="false">http://www.ocoudert.com/blog/?p=1397</guid>
		<description><![CDATA[Synopsys recently announced they reached an agreement to acquire Magma. The natural questions are then “why”, and “is it a good thing”. Here are my two cents. The “why” first. For Synopsys, I can think of a few good reasons: &#160; Magma’s Talus Vortex is still a disruption for many P&#38;R Synopsys deals. Magma’s FineSim [...] [...]<p>Continue reading <a href="http://www.ocoudert.com/blog/2011/12/18/why-synopsys-buying-magma-is-good/">Why Synopsys buying Magma is good</a></p>
Related posts:<ol>
<li><a href='http://www.ocoudert.com/blog/2011/03/29/synopsys-getting-into-the-cloud/' rel='bookmark' title='Synopsys is getting into the cloud'>Synopsys is getting into the cloud</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>Synopsys recently <a href="http://www.prnewswire.com/news-releases/synopsys-to-acquire-magma-design-automation-134779323.html">announced</a> they reached an agreement to acquire Magma. The natural questions are then “why”, and “is it a good thing”. Here are my two cents.</p>
<p><a href="http://www.ocoudert.com/blog/wp-content/uploads/2011/12/synopsys_logo2-300x65.jpg"><img class="alignright size-full wp-image-1406" title="synopsys_logo2-300x65" src="http://www.ocoudert.com/blog/wp-content/uploads/2011/12/synopsys_logo2-300x65.jpg" alt="Synopsys logo" width="230" height="50" /></a></p>
<p>The “why” first. For Synopsys, I can think of a few good reasons:</p>
<p>&nbsp;</p>
<ol>
<li>Magma’s Talus Vortex is still a disruption for many P&amp;R Synopsys deals.<a href="http://www.ocoudert.com/blog/wp-content/uploads/2011/12/MAGMA-LOGO.png"><img class="alignright size-full wp-image-1405" title="MAGMA-LOGO" src="http://www.ocoudert.com/blog/wp-content/uploads/2011/12/MAGMA-LOGO.png" alt="Magma logo" width="230" height="63" /></a></li>
<li>Magma’s FineSim started to make a significant dent into Synopsys’ SPICE market share.</li>
<li>Magma’s Titan is a viable solution against Cadence’s solution for analog and mixed signal design, unlike Synopsys’ in-house tool.</li>
<li>Magma’s Tekton showed how Synopsys’ PrimeTime has been lacking innovations to bring distributed timing signoff to the customers.</li>
</ol>
<p>For Magma, a good answer to “why “is a 30% premium on its stock price, which Rajeev Madhavan, the CEO of Magma, has been working very hard to push up. Also maybe Rajeev realized that Magma would never realize one of his ambitions, beating Synopsys at his own game, RTL synthesis. Or maybe he finally acknowledged that you cannot grow if you keep discounting your own products, and keep trimming talents for cost reasons. Regardless of the motivations, I am sure that Rajeev leaves with a good deal in his hands.</p>
<p>What about Magma’s employees? For them, the premium on the stock price is good news. But what will happen to their jobs is more of a mixed bag. In such acquisition, sales and marketing are the first to go. Synopsys will certainly retain the R&amp;D talents they care about –FineSim, Titan, Tekton, and possibly a handful of people in the backend. I hear a lot of people in Magma India that wonder what will happen of them. Not to worry. I think it would be foolish for Synopsys not to leverage Magma’s R&amp;D facilities in India. Both Noida and Bangalore’s Magma offices are made of strong, committed, talented people. They can easily be reassigned to other projects.</p>
<p>What about the users? Their reaction is likely to be negative. The reason: Magma out means less competition, thus less innovation and possibly higher prices. Also many users are reluctant to deal with Synopsys sales people that are often perceived as arrogant.</p>
<p>However Magma has been cutting down the price of its tools to a point that it has been hurting the EDA industry as a whole. Being aggressive on price to gain market share is good, but cutting down the price to stay in business is bad. Investing in new tools is good, but dispersing scares resources on too many projects results in unfocused strategies that fail to deliver. My take is that for the longer term, the disappearance of Magma will benefit the user as well.</p>
<p>What about the EDA industry? This is clearly good news. This consolidation is an opportunity for Synopsys to be ambitious. Also Magma’s acquisition will free talents, and will make some startups look like a decent alternative for the customers that want to balance Synopsys’ hold on the industry. Change is good. Thank you Magma for shaking the industry, and welcome to the future movers.</p>
<p>Related posts:<ol>
<li><a href='http://www.ocoudert.com/blog/2011/03/29/synopsys-getting-into-the-cloud/' rel='bookmark' title='Synopsys is getting into the cloud'>Synopsys is getting into the cloud</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.ocoudert.com/blog/2011/12/18/why-synopsys-buying-magma-is-good/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Cloud computing is not grid computing</title>
		<link>http://www.ocoudert.com/blog/2011/11/28/cloud-computing-is-not-grid-computing/</link>
		<comments>http://www.ocoudert.com/blog/2011/11/28/cloud-computing-is-not-grid-computing/#comments</comments>
		<pubDate>Mon, 28 Nov 2011 17:56:40 +0000</pubDate>
		<dc:creator>Olivier Coudert</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[cloud computing]]></category>

		<guid isPermaLink="false">http://www.ocoudert.com/blog/?p=1387</guid>
		<description><![CDATA[Recently I had a few discussions with people looking at leveraging the cloud. They were looking at extending their own compute farm by establishing a VPN to a public cloud and borrowing computing resources as needed. With a compute farm, you have a fixed amount of computing resources. You rely on an engine like LSF [...] [...]<p>Continue reading <a href="http://www.ocoudert.com/blog/2011/11/28/cloud-computing-is-not-grid-computing/">Cloud computing is not grid computing</a></p>
Related posts:<ol>
<li><a href='http://www.ocoudert.com/blog/2011/03/16/cloud-computing-an-opportunity-for-eda/' rel='bookmark' title='Cloud computing: an opportunity for EDA'>Cloud computing: an opportunity for EDA</a></li>
<li><a href='http://www.ocoudert.com/blog/2011/03/29/synopsys-getting-into-the-cloud/' rel='bookmark' title='Synopsys is getting into the cloud'>Synopsys is getting into the cloud</a></li>
<li><a href='http://www.ocoudert.com/blog/2011/10/11/why-eda-in-the-cloud-will-come-from-startups/' rel='bookmark' title='Why EDA in the cloud will come from startups'>Why EDA in the cloud will come from startups</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.ocoudert.com/blog/wp-content/uploads/2011/11/facebook-prinevilleopencompute.jpg"><img class="alignright size-full wp-image-1391" title="facebook-prinevilleopencompute" src="http://www.ocoudert.com/blog/wp-content/uploads/2011/11/facebook-prinevilleopencompute.jpg" alt="Facebook datacenter" width="350" /></a>Recently I had a few discussions with people looking at leveraging the cloud. They were looking at extending their own compute farm by establishing a VPN to a public cloud and borrowing computing resources as needed.</p>
<p>With a compute farm, you have a fixed amount of computing resources. You rely on an engine like <a href="http://en.wikipedia.org/wiki/Platform_LSF">LSF</a> (Load Sharing Facility) or <a href="http://en.wikipedia.org/wiki/Oracle_Grid_Engine">SGE</a> (Sun Grid Engine) to schedule and prioritize jobs to best use these fixed computing resources. The rule of the game is to keep the queue as short as possible, or better, to keep the relative processing time increase as small as possible.</p>
<p>Clearly having access to hundreds of compute nodes (or instances, to use the cloud terminology) on demand changes the game of parallel computing entirely. In the word of cloud computing, using 100 instances for 1 hour costs the same as using 1 instance for 100 hours (a bit more than 4 days). Assuming you can borrow as much as you want and that you can keep all the instances busy, there is no point in limiting the computing resources: the cost will be the same, but the wall time will be reduced.</p>
<p>Of course, this is more complicated in practice. You are billed by the hour. Thus starting a new instance to process jobs is wasteful if that instance is not fully utilized during a whole hour. Also starting or shutting down an instance takes a few minutes, during which that instance is unavailable. Thus you must be able to anticipate the upcoming job distribution and have a clear pictures of the instances’ load and how long they have before their hour expire to decide whether you should:</p>
<ul>
<li>Start a new instance to process jobs;</li>
<li>Shut down an instance before being charged another hour;</li>
<li>Queue a job.</li>
</ul>
<p>You also want to account for hardware failures, which is more likely to happen if you have many instances for a long time. Also inter-instance communication, if needed, can become a major bottleneck in scaling up –unless there is a 10Gb network available.</p>
<p>The cloud has an appealing message –borrow when you need it. It is a paradigm shift for parallel computing. This means moving from “managing resources” in a compute farm to “managing cost” in the cloud. As explained above, managing cost in the cloud is substantially more complicated that scheduling jobs on a compute farm. Yet cloud computing gives the flexibility to design strategies that reduces wall time and keeps costs low. It will only benefit customers: borrow more for less time, pay the same, and get the result faster.</p>
<p>&nbsp;</p>
<p>Related posts:<ol>
<li><a href='http://www.ocoudert.com/blog/2011/03/16/cloud-computing-an-opportunity-for-eda/' rel='bookmark' title='Cloud computing: an opportunity for EDA'>Cloud computing: an opportunity for EDA</a></li>
<li><a href='http://www.ocoudert.com/blog/2011/03/29/synopsys-getting-into-the-cloud/' rel='bookmark' title='Synopsys is getting into the cloud'>Synopsys is getting into the cloud</a></li>
<li><a href='http://www.ocoudert.com/blog/2011/10/11/why-eda-in-the-cloud-will-come-from-startups/' rel='bookmark' title='Why EDA in the cloud will come from startups'>Why EDA in the cloud will come from startups</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.ocoudert.com/blog/2011/11/28/cloud-computing-is-not-grid-computing/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Why EDA in the cloud will come from startups</title>
		<link>http://www.ocoudert.com/blog/2011/10/11/why-eda-in-the-cloud-will-come-from-startups/</link>
		<comments>http://www.ocoudert.com/blog/2011/10/11/why-eda-in-the-cloud-will-come-from-startups/#comments</comments>
		<pubDate>Tue, 11 Oct 2011 15:03:50 +0000</pubDate>
		<dc:creator>Olivier Coudert</dc:creator>
				<category><![CDATA[EDA]]></category>
		<category><![CDATA[cloud computing]]></category>

		<guid isPermaLink="false">http://www.ocoudert.com/blog/?p=1368</guid>
		<description><![CDATA[By now the EDA community should know that cloud computing in the industry is inevitable. Most CPU-time hungry tasks (e.g., logic simulation, extraction, physical verification) in the design flow cannot substantially be improved at the algorithmic level. Thus we must rely on massive parallelism to reduce wall time to acceptable levels. And since nobody wants [...] [...]<p>Continue reading <a href="http://www.ocoudert.com/blog/2011/10/11/why-eda-in-the-cloud-will-come-from-startups/">Why EDA in the cloud will come from startups</a></p>
Related posts:<ol>
<li><a href='http://www.ocoudert.com/blog/2011/03/29/synopsys-getting-into-the-cloud/' rel='bookmark' title='Synopsys is getting into the cloud'>Synopsys is getting into the cloud</a></li>
<li><a href='http://www.ocoudert.com/blog/2011/03/22/eda-in-the-cloud-shall-we-be-scared/' rel='bookmark' title='EDA in the cloud: shall we be scared?'>EDA in the cloud: shall we be scared?</a></li>
<li><a href='http://www.ocoudert.com/blog/2011/03/16/cloud-computing-an-opportunity-for-eda/' rel='bookmark' title='Cloud computing: an opportunity for EDA'>Cloud computing: an opportunity for EDA</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.ocoudert.com/blog/2011/10/11/why-eda-in-the-cloud-will-come-from-startups/cloud1/" rel="attachment wp-att-1372"><img class="alignright size-full wp-image-1372" title="cloud1" src="http://www.ocoudert.com/blog/wp-content/uploads/2011/10/cloud1.jpg" alt="EDA in the cloud" width="250" /></a>By now the EDA community should know that cloud computing in the industry is inevitable. Most CPU-time hungry tasks (e.g., logic simulation, extraction, physical verification) in the design flow cannot substantially be improved at the algorithmic level. Thus we must rely on massive parallelism to reduce wall time to acceptable levels. And since nobody wants to buy and manage compute farms of thousands of nodes for peak usage, using a public cloud is the next natural step.</p>
<p>But this is a hard step. There are many obstructions to viable cloud-backed EDA solutions:</p>
<ul>
<li>Both customers and providers of EDA are conservative communities. They are usually slow to adopt new technologies. The semiconductor industry is reluctant to invest in new design frameworks, as its wants to preserve its investment in working flows.</li>
<li>Security remains a hot issue. EDA vendors want to control the usage of their tools, and they are uncomfortable making them available in a public cloud. And the EDA customers are paranoid about their designs slipping out in the wild.</li>
<li>Massive parallelism is great, but data transfer via Internet is slow. Because some tasks require moving huge amount of data to and from applications, it is better to host the design data in the cloud for the whole design lifetime. This requires a drastic different mindset for project managers.</li>
<li>The current TBL (Time-Based License) model makes no sense with massive parallelism. We need new business models based on actual usage (per hour, day, or week) to unlock the flexibility and scalability offered by cloud computing.</li>
</ul>
<p>The big EDA companies have been slowly espousing the idea of making their tools available in the cloud. Cadence set up a (private) cloud offering a while back, but it has never been successful. Synopsys announced in March that it would provide a cloud computing solution for VCS simulation with AWS (Amazon Web Services). We will see how it unfolds.</p>
<p>Meanwhile, startups have been testing the water. <a href="http://www.xuropa.com/" target="_blank">Xuropa</a> hosts demos and a CRM platform in the cloud, and counts Cadence and Synopsys as customers. <a title="Plunify" href="//www.plunify.com" target="_blank">Plunify</a> proposes FPGA synthesis with multiple runs in the cloud. <a href="http://www.nimbic.com/" target="_blank">Nimbic</a> (formerly known as Physware) uses the cloud to develop and deploy its tool. Same for <a href="http://www.tabula.com/">Tabula</a> (although in a private cloud). Xuropa, Plunify, and Nimbic are now making claims about moving other EDA applications in the cloud. And more stealth startups are working on their own solutions.</p>
<p><a href="http://www.ocoudert.com/blog/2011/10/11/why-eda-in-the-cloud-will-come-from-startups/xuropa-2/" rel="attachment wp-att-1378"><img class="size-full wp-image-1378 alignleft" title="xuropa" src="http://www.ocoudert.com/blog/wp-content/uploads/2011/10/xuropa1.png" alt="" width="190" /></a><a href="http://www.ocoudert.com/blog/2011/10/11/why-eda-in-the-cloud-will-come-from-startups/nimbic/" rel="attachment wp-att-1379"><img class="size-full wp-image-1379 alignleft" style="margin-left: 40px; margin-right: 40px;" title="Nimbic" src="http://www.ocoudert.com/blog/wp-content/uploads/2011/10/nimbic.png" alt="Nimbic" width="170" /></a><a href="http://www.ocoudert.com/blog/wp-content/uploads/2011/10/plunify.png"><img class="alignleft size-full wp-image-1380" title="plunify" src="http://www.ocoudert.com/blog/wp-content/uploads/2011/10/plunify.png" alt="" width="180" /></a></p>
<p>&nbsp;</p>
<p>This is good news. Big EDA companies encounter many internal resistances to moving to the cloud: “this requires costly technical expertise”; “we cannot secure the usage of our tools”; “this is not our core competency”; “we will cannibalize our traditional TBL business and loose money”; “no customer is willing to put his data in the cloud”; etc.</p>
<p>These concerns are legitimate. Transitioning a +20 year old business to a pay-as-you-go model is a daunting, if not scary, proposition for well-established players. Also using cloud technology is much more than high-octane IT. This makes startups the best apt to answer the challenge, evangelize the solutions, and educate the customers. Parting from the TBL business model will take at least that much.</p>
<p>&nbsp;</p>
<p>Related posts:<ol>
<li><a href='http://www.ocoudert.com/blog/2011/03/29/synopsys-getting-into-the-cloud/' rel='bookmark' title='Synopsys is getting into the cloud'>Synopsys is getting into the cloud</a></li>
<li><a href='http://www.ocoudert.com/blog/2011/03/22/eda-in-the-cloud-shall-we-be-scared/' rel='bookmark' title='EDA in the cloud: shall we be scared?'>EDA in the cloud: shall we be scared?</a></li>
<li><a href='http://www.ocoudert.com/blog/2011/03/16/cloud-computing-an-opportunity-for-eda/' rel='bookmark' title='Cloud computing: an opportunity for EDA'>Cloud computing: an opportunity for EDA</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.ocoudert.com/blog/2011/10/11/why-eda-in-the-cloud-will-come-from-startups/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Time for me to move to the cloud</title>
		<link>http://www.ocoudert.com/blog/2011/09/17/time-for-me-to-move-to-the-cloud/</link>
		<comments>http://www.ocoudert.com/blog/2011/09/17/time-for-me-to-move-to-the-cloud/#comments</comments>
		<pubDate>Sat, 17 Sep 2011 08:11:14 +0000</pubDate>
		<dc:creator>Olivier Coudert</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[cloud computing]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://www.ocoudert.com/blog/?p=1349</guid>
		<description><![CDATA[I am a strong believer in leveraging cloud infrastructures. I have written about using cloud computing as a vector of new growth opportunities for EDA. Not such big claim here. This post is simply about a recent experience that decided me to put in practice what I have been praising. For the past decade I [...] [...]<p>Continue reading <a href="http://www.ocoudert.com/blog/2011/09/17/time-for-me-to-move-to-the-cloud/">Time for me to move to the cloud</a></p>
Related posts:<ol>
<li><a href='http://www.ocoudert.com/blog/2011/03/22/eda-in-the-cloud-shall-we-be-scared/' rel='bookmark' title='EDA in the cloud: shall we be scared?'>EDA in the cloud: shall we be scared?</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>I am a strong believer in leveraging cloud infrastructures. I have written about using cloud computing as a vector of new growth opportunities for <a href="http://www.ocoudert.com/blog/wp-content/uploads/2011/09/cloud-artwork-resized-600.png"><img class="alignright size-full wp-image-1359" title="cloud-artwork-resized-600" src="http://www.ocoudert.com/blog/wp-content/uploads/2011/09/cloud-artwork-resized-600.png" alt="" width="300" height="264" /></a>EDA.</p>
<p>Not such big claim here. This post is simply about a recent experience that decided me to put in practice what I have been praising.</p>
<p>For the past decade I always had several computers at home –two to five Windows PCs, a Mac, and another couple of Linux machines. Very early I was interested in having a storage unit I could share on my LAN between all my computers. Having one central unit to archive, backup, and serve medias (pictures, music, video) is pretty handy.</p>
<p>Back in 2004 I bought a 250Gb <a href="http://www.ximeta.com/" rel="nofollow">Ximeta</a> Netdisk. Technically it is not a NAS (Network Attached Storage), as you have to install a small program on every computer you want to access the disk from. But the device worked just fine, and it still does. Later in 2007 I upgraded to a real NAS (i.e., using TCP/IP for all communications with the devices on the LAN) for my storage needs with a 500Gb <a href="http://www.lacie.com/us/index.htm" rel="nofollow">LaCie</a> <a href="http://www.lacie.com/us/support/support_manifest.htm?pid=10844" rel="nofollow">Ethernet Disk mini</a>.</p>
<p>Soon I placed all my data on my Lacie drive: email, business related documents, publications, presentations, C/C++ and Java code, tech articles, books, tax declarations, music, photos, etc. A few days ago, after 4 years of good service, the drive quit on me: it just ceased to power up. Since I had 260Gb of data on that disk, you can imagine my reaction. “Do not panic. The disk itself is fine. It’s only the drive mechanism or the controller that is fried”.</p>
<p>Here is the email exchange I had with Jon L. from Lacie’s support:</p>
<blockquote><p>Jon: “[…] according to the serial information, the drive appears to be past the two-year warranty. […] Although the drive is no longer serviceable by our repair department, we strive to provide all of our customers with a positive experience with our service and products. LaCie would like to offer you a discount on a replacement product.”</p>
<p>Me: “Nice thought. But what about my data?”</p>
<p>Jon: “[…] a qualified technician may be able to replace the failed internal drive and reconfigure the unit to accept the new drive.  […] We can not assist with this third party repair process.”</p>
<p>Me: “The most important part for me is to retrieve the data stored on the drive. It looks to me that the disk itself is fine &#8211;the electronic and control part just stopped to function. Do you provide data recovery service?”</p>
<p>Jon: “Pricing is simple:</p>
<ul>
<li>Single drive recovery, no clean room = $399</li>
<li>Single drive recovery, requires clean room = $1299”</li>
</ul>
<p>Me: “Ouch!”</p></blockquote>
<p>So retrieving my data via this service would cost about twice as much as what I paid originally for the disk four years ago. Come on, for $399 I can buy a brand new 4Tb RAID-1 Gigabit Ethernet NAS from Lacie!</p>
<p>The lesson: having a NAS at home is nice to share pictures and music. But if you want to use it as a central repository and backup, you need to think about what happens if that unit fails. Sure, you can use another disk to mirror the backup. Or use a RAID-1 disk, which adds redundancy for higher reliability. But it became clear to me that I was ready to put in practice what I have been advocating for the industry: use the cloud.</p>
<p>Don’t get a backup for the backup, just put the data in the cloud. Then you can always access it –instead of carrying around an external hard drive, as I used to do. Use a service that guarantees replication and redundancy to preserve the integrity of the data, even in case of catastrophic event (e.g., the recent hurricane on the east coast that flooded a few hosting data centers). Encrypt the data at the source, so that nobody but you can read the data.</p>
<p>Eventually I recovered my data for $99 (a fourth of the price Lacie quoted to me) at a <a href="http://www.quickfixus.com/html_files/contact_us_Mtn_View.html" rel="nofollow">computer repair shop</a> in Mountain View. Since then I have been hunting for some cloud data service. I will share my findings and my experiences in a couple of weeks.</p>
<p>Related posts:<ol>
<li><a href='http://www.ocoudert.com/blog/2011/03/22/eda-in-the-cloud-shall-we-be-scared/' rel='bookmark' title='EDA in the cloud: shall we be scared?'>EDA in the cloud: shall we be scared?</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.ocoudert.com/blog/2011/09/17/time-for-me-to-move-to-the-cloud/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Mentor quitting on ESL?</title>
		<link>http://www.ocoudert.com/blog/2011/08/27/mentor-quitting-on-esl/</link>
		<comments>http://www.ocoudert.com/blog/2011/08/27/mentor-quitting-on-esl/#comments</comments>
		<pubDate>Sat, 27 Aug 2011 23:08:54 +0000</pubDate>
		<dc:creator>Olivier Coudert</dc:creator>
				<category><![CDATA[EDA]]></category>
		<category><![CDATA[low power]]></category>
		<category><![CDATA[synthesis]]></category>
		<category><![CDATA[verification]]></category>

		<guid isPermaLink="false">http://www.ocoudert.com/blog/?p=1326</guid>
		<description><![CDATA[So you got the news: Calypto acquired Catapult-C, the ESL synthesis tool from Mentor Graphics. Calypto has been into low power (using notably sequential optimization techniques) and sequential verification for a while. And the company has always been very close to Mentor Graphics: it had integrated its verification tool with Catapult-C as early as 2005. [...] [...]<p>Continue reading <a href="http://www.ocoudert.com/blog/2011/08/27/mentor-quitting-on-esl/">Mentor quitting on ESL?</a></p>
Related posts:<ol>
<li><a href='http://www.ocoudert.com/blog/2010/04/20/is-fpga-a-sustainable-market-for-eda/' rel='bookmark' title='Is FPGA a sustainable market for EDA?'>Is FPGA a sustainable market for EDA?</a></li>
<li><a href='http://www.ocoudert.com/blog/2009/10/06/automated-low-power-design-flow-is-up-for-grabs-part-ii/' rel='bookmark' title='Automated low-power design flow is up for grabs (Part II)'>Automated low-power design flow is up for grabs (Part II)</a></li>
<li><a href='http://www.ocoudert.com/blog/2009/10/05/automated-low-power-design-flow-is-up-for-grab-part-i/' rel='bookmark' title='Automated low-power design flow is up for grabs (Part I)'>Automated low-power design flow is up for grabs (Part I)</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>So you got the news: Calypto <a href="http://www.eetimes.com/electronics-news/4219348/Calypto-acquires-Mentor-s-Catapult-C" rel="nofollow">acquired</a> <a href="http://www.mentor.com/esl/catapult/overview" rel="nofollow">Catapult-C</a>, the ESL synthesis tool from Mentor Graphics.</p>
<p><a href="http://www.ocoudert.com/blog/wp-content/uploads/2011/08/calypto_logo.gif"><img class="size-full wp-image-1329 alignright" style="border: 0pt none; margin-left: 4px; margin-right: 2px;" title="calypto_logo" src="http://www.ocoudert.com/blog/wp-content/uploads/2011/08/calypto_logo.gif" alt="Calypto" width="150" height="40" /></a><a href="http://www.calypto.com/" rel="nofollow">Calypto</a> has been into low power (using notably sequential optimization techniques) and sequential verification for a while. And the company has always been very close to Mentor Graphics: it had integrated its verification tool with Catapult-C as early as 2005.<a href="http://www.ocoudert.com/blog/wp-content/uploads/2011/08/mentor_logo.jpg"><img class="alignright size-full wp-image-1330" style="margin-left: 4px; margin-right: 2px;" title="mentor_logo" src="http://www.ocoudert.com/blog/wp-content/uploads/2011/08/mentor_logo.jpg" alt="Mentor Graphics" width="150" height="47" /></a></p>
<p>But the move came somewhat as a surprise, at least for me. Mentor has been touting itself has the leader in <a href="http://www.mentor.com/esl/" rel="nofollow">ESL</a>, with some good reasons. Mentor had a strong offering in that space, including Catapult-C, and a consistent strategy.</p>
<p>Until now.</p>
<p>The decision of letting Catapult-C go has been sugar-coated, to say the least. Dixit Brian Derrick, VP marketing at Mentor Graphics: &#8220;We remain deeply committed to ESL. We view this transaction as an innovative way to accelerate adoption of ESL methodologies, to strengthen our partnership with Calypto, and as one that complements our continued investment in ESL virtual prototyping environments led by our Vista product”. Huhu.</p>
<p>It is hard to not interpret Mentor’s decision as a change of strategy, and a disengagement from ESL. The truth is, despite all the promises, ESL has been very slow to gain acceptance. After more than seven years, ESL’s market is still dwarfed by conventional synthesis, and even more by the cash cows that are simulation and physical verification. So from Mentor’s perspective, it may make sense to focus on better business opportunities.</p>
<p>Some will see in that transfer of ownership the proof that yet again, pushing EDA innovation to success is essentially left to startups. Wait, isn’t that the very purpose of startups?</p>
<p>Calypto, with the acquisition of Catapult-C, got a sweet deal. They have the opportunity to have a single environment for ESL synthesis and verification. Problem is, unless they provide a path for 3<sup>rd</sup> party verification tool (read: Cadence and Synopsys) to independently check their synthesis, it will be difficult to substantially increase the number of their adopters. Best of luck to them though.</p>
<p>Related posts:<ol>
<li><a href='http://www.ocoudert.com/blog/2010/04/20/is-fpga-a-sustainable-market-for-eda/' rel='bookmark' title='Is FPGA a sustainable market for EDA?'>Is FPGA a sustainable market for EDA?</a></li>
<li><a href='http://www.ocoudert.com/blog/2009/10/06/automated-low-power-design-flow-is-up-for-grabs-part-ii/' rel='bookmark' title='Automated low-power design flow is up for grabs (Part II)'>Automated low-power design flow is up for grabs (Part II)</a></li>
<li><a href='http://www.ocoudert.com/blog/2009/10/05/automated-low-power-design-flow-is-up-for-grab-part-i/' rel='bookmark' title='Automated low-power design flow is up for grabs (Part I)'>Automated low-power design flow is up for grabs (Part I)</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.ocoudert.com/blog/2011/08/27/mentor-quitting-on-esl/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>A practical guide to C++ serialization</title>
		<link>http://www.ocoudert.com/blog/2011/07/09/a-practical-guide-to-c-serialization/</link>
		<comments>http://www.ocoudert.com/blog/2011/07/09/a-practical-guide-to-c-serialization/#comments</comments>
		<pubDate>Sun, 10 Jul 2011 04:52:41 +0000</pubDate>
		<dc:creator>Olivier Coudert</dc:creator>
				<category><![CDATA[CodeProject]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[software]]></category>

		<guid isPermaLink="false">http://www.ocoudert.com/blog/?p=1168</guid>
		<description><![CDATA[CodeProject In a nutshell, serialization consists of writing data and objects on a support (a file, a buffer, a socket), so that they can be reconstructed later in the memory of the same or another computing host. The reconstruction process is also known as deserialization. Serializing a primitive type like a bool, int, or float, [...] [...]<p>Continue reading <a href="http://www.ocoudert.com/blog/2011/07/09/a-practical-guide-to-c-serialization/">A practical guide to C++ serialization</a></p>
Related posts:<ol>
<li><a href='http://www.ocoudert.com/blog/2010/07/07/how-to-write-abstract-iterators-in-c/' rel='bookmark' title='How to write abstract iterators in C++'>How to write abstract iterators in C++</a></li>
<li><a href='http://www.ocoudert.com/blog/2011/05/30/how-to-make-software-deterministic/' rel='bookmark' title='How to make software deterministic'>How to make software deterministic</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><a style="display: none;" rel="tag" href="http://www.codeproject.com/script/Articles/BlogFeedList.aspx?amid=6630043">CodeProject</a><br />
In a nutshell, serialization consists of writing data and objects on a support (a file, a buffer, a socket), so that they can be reconstructed later in the memory of the same or another computing host. The reconstruction process is also known as deserialization.</p>
<p>Serializing a primitive type like a bool, int, or float, is trivial: just write the data as it is (assuming that no compression is used). Serializing a pointer is different: the object it points to must be serialized first. That way deserializing the pointer simply consists of setting its value to the memory address at which the object has been reconstructed.</p>
<p>We can distinguish three levels of complexity in serialization, depending on how complex the pointer (and reference) graph is:</p>
<ol>
<li>The pointer graph is a <em>forest</em> (i.e., a set of <em>trees</em>). Data can simply be serialized bottom up with a depth first traversal of the trees.</li>
<li>The pointer graph is a <em>directed acyclic graph</em> (DAG), i.e., a graph without loop. We can still serialize the data bottom up, making sure we write and restore shared data only once.</li>
<li>The pointer graph is a general graph, i.e., it may have loops. We need to write and restore data with forward references so that loops are handled properly.</li>
</ol>
<p>&nbsp;</p>
<div class="mceTemp mceIEcenter" style="text-align: center;">
<dl id="attachment_1169" class="wp-caption aligncenter" style="width: 610px;">
<dt class="wp-caption-dt"><a href="http://www.ocoudert.com/blog/wp-content/uploads/2011/05/pointers-graph.png"><img class="size-full wp-image-1169 " title="pointers graph" src="http://www.ocoudert.com/blog/wp-content/uploads/2011/05/pointers-graph.png" alt="" width="600" height="362" /></a></dt>
<dd class="wp-caption-dd">Pointer graph as a tree, a DAG, and with loops</dd>
</dl>
</div>
<p>&nbsp;</p>
<p>It is always an option to serialize objects using your own customized code. However serialization is much more complex than a simple pretty-print method. One would like serialization to support the following features:</p>
<ol>
<li>Serialization should be able to handle any pointer graph (i.e., with loops).</li>
<li>Serializing a pointer or a reference should automatically trigger the serialization of the referred object.</li>
<li>Serializing an entire data model can require a lot of code –from simple scalar fields (bool, int, float), to containers (vector, list, hash table, etc), to intricate data structures (graph, quad-tree, sparse matrices, etc). One would like templates that carry most of the burden.</li>
<li>The save and load functions must always be in sync: if the ‘save’ function is modified, the ‘load’ function must be changed appropriately. One would like that process to be automated as much as possible.</li>
<li>One should have a way of serializing objects without changing their .hpp files –this is known as non-intrusive serialization. The reason is that in many case one does not want (or one cannot) change the source files of existing libraries.</li>
<li>Serialization needs to support versioning. As objects evolve, data members are added or removed, and it is desirable to be back compatible –meaning, one can still deserialize archives from older versions into the most recent data model.</li>
<li>Serialization should be cross-platform compatible (32 and 64 bits machines, Windows, Linux, Solaris, etc).</li>
</ol>
<p>The boost library provides a serialization that meets all the requirements above, and more:</p>
<ul>
<li>It is extremely efficient, it supports versioning, and it automatically serializes STL containers.</li>
<li>Serialization (the save function) and deserialization (the load function) are expressed with one single template, which reduces the size of the code, and resolves the synchronization problem.</li>
<li>With a little bit of help, boost serialization is also 32 and 64 bit compatible, which means that a database serialized on a 32 bit machine can be read on a 64 bit machine <em>and conversely</em>.</li>
<li>Also boost serialization (respectively deserialization) takes an output (respectively input) argument that is very similar to a std::ostream (respectively std::istream), meaning that it can be a file on a disk, a buffer, or a socket. You can literally serialize your data over a network.</li>
</ul>
<p>The best way to understand how to serialize with boost is to walk through increasingly complex serialization scenarios.</p>
<h2>Basic serialization</h2>
<p>The code for serialization, as well as an example that saves and restores simple objects, is given below.</p>
<pre style="color: #000000; background-color: #ffe3c1;" lang="c++"><small>#pragma once
// File obj.hpp

// Forward declaration of class boost::serialization::access
namespace boost {
namespace serialization {
class access;
}
}

class Obj {
public:
  // Serialization expects the object to have a default constructor
  Obj() : d1_(-1), d2_(false) {}
  Obj(int d1, bool d2) : d1_(d1), d2_(d2) {}
  bool operator==(const Obj&amp; o) const {
    return d1_ == o.d1_ &amp;&amp; d2_ == o.d2_;
  }
private:
  int  d1_;
  bool d2_;

  // Allow serialization to access non-public data members.
  friend class boost::serialization::access;

  template&lt;typename Archive&gt;
  void serialize(Archive&amp; ar, const unsigned version) {
    ar &amp; d1_ &amp; d2_;  // Simply serialize the data members of Obj
  }
};
</small></pre>
<p>The template ‘serialize’ defines both the save and load. This is achieved because the operator ‘&amp;’ will be defined as ‘&lt;&lt;’ (respectively ‘&gt;&gt;’) for an output (respectively input) archive. Note the friend declaration to allow the save/load template to access the private data members of the objects. Also note that serialization expects the object to have a default constructor (which can be private).</p>
<pre style="color: #000000; background-color: #ffe3c1;" lang="c++"><small>#include "obj.hpp"
#include &lt;assert.h&gt;
#include &lt;fstream&gt;
#include &lt;boost/archive/text_iarchive.hpp&gt;
#include &lt;boost/archive/text_oarchive.hpp&gt;

int main() {
  const char* fileName = "saved.txt";

  // Create some objects
  const Obj o1(-2, false);
  const Obj o2;
  const Obj o3(21, true);
  const Obj* const p1 = &amp;o1;

  // Save data
  {
    // Create an output archive
    std::ofstream ofs(fileName);
    boost::archive::text_oarchive ar(ofs);

    // Write data
    ar &amp; o1 &amp; o2 &amp; o3 &amp; p1;
  }

  // Restore data
  Obj restored_o1;
  Obj restored_o2;
  Obj restored_o3;
  Obj* restored_p1;
  {
    // Create and input archive
    std::ifstream ifs(fileName);
    boost::archive::text_iarchive ar(ifs);

    // Load data
    ar &amp; restored_o1 &amp; restored_o2 &amp; restored_o3 &amp; restored_p1;
  }

  // Make sure we restored the data exactly as it was saved
  assert(restored_o1 == o1);
  assert(restored_o2 == o2);
  assert(restored_o3 == o3);
  assert(restored_p1 != p1);
  assert(restored_p1 == &amp;restored_o1);

  return 0;
}
</small></pre>
<p>In main.cpp, we first include the files declaring the input and output text archives, where objects will be loaded from and saved to, respectively. We create an output archive (here, a file on a disk), and write three instances of class Obj, as well as a pointer to one of the instances. We then read them back and make sure we restore the data as they were. Note how the restored pointer restored_p1 points to the restored object restored_o1.</p>
<h2>More on pointer serialization</h2>
<p>Whenever we call serialization on a pointer (or reference), this triggers the serialization of the object it points to (or refers to) whenever necessary. So we do not need to explicitly serialize pointed objects as boost serialization will make sure the appropriate objects reached in the pointers graph are serialized.</p>
<p>For instance, the code below shows that serializing the pointer p1 triggers the serialization of o1, the object it point to. When restoring the pointer restored_p1, we automatically create a clone of the object o1.</p>
<pre style="color: #000000; background-color: #ffe3c1;" lang="c++"><small>#include "obj.hpp"
#include &lt;assert.h&gt;
#include &lt;fstream&gt;
#include &lt;boost/archive/text_iarchive.hpp&gt;
#include &lt;boost/archive/text_oarchive.hpp&gt;

int main()
{
  const char* fileName = "saved.txt";

  // Create one object o1.
  const Obj o1(-2, false);
  const Obj* const p1 = &amp;o1;

  // Save data
  {
    // Create an output archive
    std::ofstream ofs(fileName);
    boost::archive::text_oarchive ar(ofs);
    // Save only the pointer. This will trigger serialization
    // of the object it points too, i.e., o1.
    ar &amp; p1;
  }

  // Restore data
  Obj* restored_p1;
  {
    // Create and input archive
    std::ifstream ifs(fileName);
    boost::archive::text_iarchive ar(ifs);
    // Load
    ar &amp; restored_p1;
  }

  // Make sure we read exactly what we saved.
  assert(restored_p1 != p1);
  assert(*restored_p1 == o1);

  return 0;
}
</small></pre>
<p>When deserializing a pointer, the object it points to will be automatically deserialized if this object has not been deserialized yet. This means that one should not attempt to deserialize an object <em>after</em> a pointer to this object has been deserialized. The reason is that once the pointer deserialization has forced the object deserialization, one cannot rebuild this object at a different address.</p>
<pre style="color: #000000; background-color: #ffe3c1;" lang="c++"><small>#include "obj.hpp"
#include &lt;fstream&gt;
#include &lt;boost/archive/text_iarchive.hpp&gt;
#include &lt;boost/archive/text_oarchive.hpp&gt;

int main()
{
  const char* fileName = "saved.txt";
  std::ofstream ofs(fileName);

  // Create one object o1 and a pointer p1 to that object.
  const Obj o1(-2, false);
  const Obj* const p1 = &amp;o1;

  // Serialize object, then pointer.
  // This works fine: after the object is deserialized, we can
  // deserialize the pointer by assigning it to the object’s address.
  {
    boost::archive::text_oarchive ar(ofs);
    ar &amp; o1 &amp; p1;
  }

  // Serialize pointer, then object.
  // This does not work: once p1 has been serialized, the object
  // has already been deserialized and its address cannot change.
  // This will throw an instance of 'boost::archive::archive_exception'
  // at runtime.
  {
    boost::archive::text_oarchive ar(ofs);
    ar &amp; p1 &amp; o1;
  }

  return 0;
}
</small></pre>
<p>In the example above, the second serialization will result in a runtime error:</p>
<pre style="color: #000000; background-color: #ffe3c1;" lang="c++"><small>ocoudert@MyMacBookPro $ a.out
terminate called after throwing an instance of 'boost::archive::archive_exception'
    what():  pointer conflict
Abort trap
coudert@MyMacBookPro $
</small></pre>
<p>This means that when pointers need to be serialized, we should never explicitly serialize the objects they point to.</p>
<h2>Explicit save and load function definitions</h2>
<p>We need an explicit definition of the save and load functions whenever they are not fully symmetric. This is typical when versioning is involved. Note the use of the macro BOOST_SERIALIZATION_SPLIT_MEMBER(), which is responsible for calling save/load when using an output/input archive.</p>
<pre style="color: #000000; background-color: #ffe3c1;" lang="c++"><small>#pragma once

#include &lt;boost/serialization/split_member.hpp&gt;

class Obj {
public:
  Obj() : d1_(-1), d2_(false) {}
  Obj(int d1, bool d2) : d1_(d1), d2_(d2) {}
  bool operator==(const Obj&amp; o) const {
    return d1_ == o.d1_ &amp;&amp; d2_ == o.d2_;
  }

private:
  int  d1_;
  bool d2_;

  friend class boost::serialization::access;

  template&lt;class Archive&gt;
  void save(Archive &amp; ar, const unsigned int version) const {
    ar &amp; d1_ &amp; d2_;
  }

  template&lt;class Archive&gt;
  void load(Archive &amp; ar, const unsigned int version) {
    ar &amp; d1_ &amp; d2_;
  }

  BOOST_SERIALIZATION_SPLIT_MEMBER()
};
</small></pre>
<h2>Serialization of C-strings</h2>
<p>A C-string cannot be directly serialized because it assumes a specific interpretation of a char*, namely an array of char terminated by a null character (‘\0’). Thus we need to explicitly serialized C-string. The class below is a simple helper to serialize C-strings (note that this can be optimized by avoiding the construction of the sdt::string).</p>
<pre style="color: #000000; background-color: #ffe3c1;" lang="c++"><small>#pragma once
// File SerializeCStringHelper.hpp

#include &lt;string&gt;
#include &lt;boost/serialization/string.hpp&gt;
#include &lt;boost/serialization/split_member.hpp&gt;

class SerializeCStringHelper {
public:
  SerializeCStringHelper(char*&amp; s) : s_(s) {}
  SerializeCStringHelper(const char*&amp; s) : s_(const_cast&lt;char*&amp;&gt;(s)) {}

private:

  friend class boost::serialization::access;

  template&lt;class Archive&gt;
  void save(Archive&amp; ar, const unsigned version) const {
    bool isNull = (s_ == 0);
    ar &amp; isNull;
    if (!isNull) {
      std::string s(s_);
      ar &amp; s;
    }
  }

  template&lt;class Archive&gt;
  void load(Archive&amp; ar, const unsigned version) {
    bool isNull;
    ar &amp; isNull;
    if (!isNull) {
      std::string s;
      ar &amp; s;
      s_ = strdup(s.c_str());
    } else {
      s_ = 0;
    }
  }

  BOOST_SERIALIZATION_SPLIT_MEMBER();

private:
  char*&amp; s_;
};
</small></pre>
<p>A simple example of its usage is as follows.</p>
<pre style="color: #000000; background-color: #ffe3c1;" lang="c++"><small>#include "SerializeCStringHelper.hpp"
#include &lt;assert.h&gt;
#include &lt;fstream&gt;
#include &lt;boost/archive/text_iarchive.hpp&gt;
#include &lt;boost/archive/text_oarchive.hpp&gt;

int main()
{
  const char* fileName = "saved.txt";
  const char* str = "This is an example a C-string";

  // Save data
  {
    // Create an output archive
    std::ofstream ofs(fileName);

    boost::archive::text_oarchive ar(ofs);
    // Save
    SerializeCStringHelper helper(str);
    ar &amp; helper;
  }

  // Restore data
  char* restored_str;
  {
    // Create and input archive
    std::ifstream ifs(fileName);
    boost::archive::text_iarchive ar(ifs);

    // Load
    SerializeCStringHelper helper(restored_str);
    ar &amp; helper;
  }

  // Make sure we read exactly what we saved
  assert(restored_str!= str);
  assert(strcmp(restored_str, str) == 0);

  return 0;
}
</small></pre>
<h2>Non-intrusive serialization</h2>
<p>So far the serialization code is added in the class definition. A non-intrusive serialization, outside of the class, might be preferable. For instance we would like to serialize a class from a library without altering the library’s hpp file. This is easy when the data members are public:</p>
<pre style="color: #000000; background-color: #ffe3c1;" lang="c++"><small>#pragma once

class Obj {
public:
  Obj() : d1_(-1), d2_(false) {}
  Obj(int d1, bool d2) : d1_(d1), d2_(d2) {}
  bool operator==(const Obj&amp; o) const {
    return d1_ == o.d1_ &amp;&amp; d2_ == o.d2_;
  }

public:
  int  d1_;
  bool d2_;
};

namespace boost {
namespace serialization {

template&lt;typename Archive&gt;
void serialize(Archive&amp; ar, Obj&amp; o, const unsigned int version) {
  ar &amp; o.d1_ &amp; o.d2_;
}

} // namespace serialization
} // namespace boost
</small></pre>
<p>If we want to protect the data members, the code is a bit more complicated because the serialization template needs to be declared as a friend. This requires a forward declaration of the template.</p>
<pre style="color: #000000; background-color: #ffe3c1;" lang="c++"><small>#pragma once

//// Declaration of the template
class Obj;

namespace boost {
namespace serialization {

template&lt;typename Archive&gt;
void serialize(Archive&amp; ar, Obj&amp; o, const unsigned int version);

} // namespace serialization
} // namespace boost

//// Definition of the class
class Obj {
public
  Obj() : d1_(-1), d2_(false) {}
  Obj(int d1, bool d2) : d1_(d1), d2_(d2) {}
  bool operator==(const Obj&amp; o) const {
    return d1_ == o.d1_ &amp;&amp; d2_ == o.d2_;
}

private:
  int  d1_;
  bool d2_;

  // Allow serialization to access data members.
  template&lt;typename Archive&gt; friend
  void boost::serialization::serialize(Archive&amp; ar, Obj&amp; o, const unsigned int version);
};

//// Definition of the template
namespace boost {
namespace serialization {

template&lt;typename Archive&gt;
void serialize(Archive&amp; ar, Obj&amp; o, const unsigned int version) {
ar &amp; o.d1_ &amp; o.d2_;
}

} // namespace serialization
} // namespace boost
</small></pre>
<h2>Non-intrusive explicit save and load function definitions</h2>
<p>This combines the two previous serialization styles, except that the include file and macro are different. For the sake of simplicity, we give the version for public data members.</p>
<pre style="color: #000000; background-color: #ffe3c1;" lang="c++"><small>#pragma once

#include &lt;boost/serialization/split_free.hpp&gt;

class Obj {
public:
  Obj() : d1_(-1), d2_(false) {}
  Obj(int d1, bool d2) : d1_(d1), d2_(d2) {}
  bool operator==(const Obj&amp; o) const {
    return d1_ == o.d1_ &amp;&amp; d2_ == o.d2_;
  }

public:
  int  d1_;
  bool d2_;
};

namespace boost {
namespace serialization {

template&lt;class Archive&gt;
void save(Archive &amp; ar, const Obj&amp; o, const unsigned int version) {
  ar &amp; o.d1_ &amp; o.d2_;
}

template&lt;class Archive&gt;
void load(Archive &amp; ar, Obj&amp; o, const unsigned int version) {
  ar &amp; o.d1_ &amp; o.d2_;
}

} // namespace serialization
} // namespace boost

BOOST_SERIALIZATION_SPLIT_FREE(Obj)

</small></pre>
<h2>Serialization of STL containers</h2>
<p>The boost library comes with templates to automatically serialize STL containers, as well as some STL objects (e.g., std::string). Instead of saving/loading a vector with the following code:</p>
<pre style="color: #000000; background-color: #ffe3c1;" lang="c++"><small>template&lt;typename Archive&gt;
void save(Archive&amp; ar, const std::vector&lt;Obj&gt;&amp; objs, const unsigned version) {
  ar &lt;&lt; objs.size();
  for (size_t i = 0; i &lt; objs.size(); ++i) {
    ar &lt;&lt; objs[i];
  }
}

template&lt;typename Archive&gt;
void load(Archive&amp; ar, std::vector&lt;Obj&gt;&amp; objs, const unsigned version) {
  size_t size;
  ar &gt;&gt; size;
  objs.resize(size);
  for (size_t i = 0; i &lt; size; ++i) {
    ar &gt;&gt; objs[i];
  }
}
</small></pre>
<p>One simply writes:</p>
<pre style="color: #000000; background-color: #ffe3c1;" lang="c++"><small>#include &lt;boost/serialization/vector.hpp&gt;

template&lt;typename Archive&gt;
void serialize(Archive&amp; ar, std::vector&lt;Obj&gt;&amp; objs, const unsigned version) {
  ar &amp; objs;
}
</small></pre>
<p>All the STL containers are supported using the appropriate include files:</p>
<pre style="color: #000000; background-color: #ffe3c1;" lang="c++"><small>#include &lt;boost/serialization/array.hpp&gt;
#include &lt;boost/serialization/vector.hpp&gt;
#include &lt;boost/serialization/hash_map.hpp&gt;
#include &lt;boost/serialization/hash_set.hpp&gt;
#include &lt;boost/serialization/list.hpp&gt;
#include &lt;boost/serialization/slist.hpp&gt;
#include &lt;boost/serialization/map.hpp&gt;
#include &lt;boost/serialization/set.hpp&gt;
#include &lt;boost/serialization/bitset.hpp&gt;
#include &lt;boost/serialization/string.hpp&gt;
</small></pre>
<h2>Serialization of base class</h2>
<p>When a class inherits from another, the base class needs to be serialized as well.</p>
<pre style="color: #000000; background-color: #ffe3c1;" lang="c++"><small>#include &lt;boost/serialization/base_object.hpp&gt;

class Base {
public:
  Base() : c_('\0') {}
  Base(char c) : c_(c) {}
  bool operator==(const Base&amp; o) const { return c_ == o.c_; }

private:
  char c_;

  friend class boost::serialization::access;

  template &lt;typename Archive&gt;
  void serialize(Archive&amp; ar, const unsigned version) {
    ar &amp; c_;
  }
};

class Obj : public Base {
private:
  typedef Base _Super;
public:
  Obj() : _Super(), d1_(-1), d2_(false) {}
  Obj(int d1, bool d2) : _Super('a'), d1_(d1), d2_(d2) {}
  bool operator==(const Obj&amp; o) const {
    return _Super::operator==(o) &amp;&amp; d1_ == o.d1_ &amp;&amp; d2_ == o.d2_;
  }

private:
  int  d1_;
  bool d2_;

  friend class boost::serialization::access;

  template &lt;typename Archive&gt;
  void serialize(Archive&amp; ar, const unsigned version) {
    ar &amp; boost::serialization::base_object&lt;_Super&gt;(*this);
    ar &amp; d1_ &amp; d2_;
  }
};
</small></pre>
<h2>Versioning</h2>
<p>We want maintain back-compatibility when the class Obj evolves. For instance, if a new data member ‘ID_’ is added, we want to read an old archive and build new Obj, with the missing data member taking the default value.</p>
<pre style="color: #000000; background-color: #ffe3c1;" lang="c++"><small>#pragma once

#include &lt;boost/serialization/split_member.hpp&gt;
#include &lt;boost/serialization/version.hpp&gt;

class Obj {
public:
  Obj() : d1_(-1), d2_(false), ID_(0) {}
  Obj(int d1, bool d2, unsigned ID id) : d1_(d1), d2_(d2), ID_(id) {}
  bool operator==(const Obj&amp; o) const {
    return d1_ == o.d1_ &amp;&amp; d2_ == o.d2_ &amp;&amp; ID_ == o.ID_;
  }

private:
  int  d1_;
  bool d2_;
  unsigned ID_;

  friend class boost::serialization::access;

  template&lt;class Archive&gt;
  void save(Archive &amp; ar, const unsigned int version) const {
    ar &amp; d1_ &amp; d2_ &amp; ID_;
  }

  template&lt;class Archive&gt;
  void load(Archive &amp; ar, const unsigned int version) {
    ar &amp; d1_ &amp; d2_;
    // If archive’s version is 0 (i.e., is old), ID_ keeps
    // its default value from the new data model,
    // else we read ID_’s value from the archive.
    if (version &gt; 0) {
      ar &amp; ID_;
    }
  }

  BOOST_SERIALIZATION_SPLIT_MEMBER()

};
</small></pre>
<h2>Serialization of const data or objects</h2>
<p>Attempting to serialize a const data or object triggers a long trail of error messages, which includes something that looks like:</p>
<pre style="color: #000000; background-color: #ffe3c1;" lang="c++"><small>[snip]

/opt/local/include/boost/archive/detail/check.hpp:162: error:
  invalid application of ‘sizeof’ to incomplete type ‘boost::STATIC_ASSERTION_FAILURE&lt;false&gt;‘

[snip]

/opt/local/include/boost/archive/basic_text_iprimitive.hpp:88: error:
  ambiguous overload for ‘operator&gt;&gt;‘ in
  ‘((boost::archive::basic_text_iprimitive&lt;std::basic_istream&lt;char,
       std::char_traits&lt;char&gt; &gt; &gt;*)this)-&gt;boost::archive::basic_text_iprimitive&lt;std::basic_istream&lt;char,
         std::char_traits&lt;char&gt; &gt; &gt;::is &gt;&gt; t’
</small></pre>
<p>This means that the input archive expects the recipient of the data to be non-const. Thus const data members must be const_cast&lt;&gt;()’ed to be serialized. For example:</p>
<pre style="color: #000000; background-color: #ffe3c1;" lang="c++"><small>#pragma once

#include &lt;boost/archive/text_iarchive.hpp&gt;
#include &lt;boost/archive/text_oarchive.hpp&gt;

class Obj {
public:
  Obj() : d1_(-1), d2_(false) {}
  Obj(int d1, bool d2) : d1_(d1), d2_(d2) {}

private:
  const int d1_;
  bool d2_;

  // Allow serialization to access data members.
  friend class boost::serialization::access;

  template&lt;typename A&gt;
  void serialize(A&amp; ar, const unsigned version) {
    ar &amp; const_cast&lt;int&amp;&gt;(d1_) &amp; d2_;
  }
};
</small></pre>
<h2>Text, XML, and binary archives</h2>
<p>The text archive is an ASCII file that is somewhat human readable. There are other archive types available in boost/archive/*.hpp, e.g.:</p>
<pre style="color: #000000; background-color: #ffe3c1;" lang="c++"><small>// Text archive that defines boost::archive::text_oarchive
// and boost::archive::text_iarchive
#include &lt;boost/archive/text_iarchive.hpp&gt;
#include &lt;boost/archive/text_oarchive.hpp&gt;

// XML archive that defines boost::archive::xml_oarchive
// and boost::archive::xml_iarchive
#include &lt;boost/archive/xml_oarchive.hpp&gt;
#include &lt;boost/archive/xml_iarchive.hpp&gt;

// XML archive which uses wide characters (use for UTF-8 output ),
// defines boost::archive::xml_woarchive
// and boost::archive::xml_wiarchive
#include &lt;boost/archive/xml_woarchive.hpp&gt;
#include &lt;boost/archive/xml_wiarchive.hpp&gt;

// Binary archive that defines boost::archive::binary_oarchive
// and boost::archive::binary_iarchive
#include &lt;boost/archive/binary_oarchive.hpp&gt;
#include &lt;boost/archive/binary_iarchive.hpp&gt;
</small></pre>
<p>The text and XML archives are portable across 32 and 64 bits platforms.</p>
<p>Having a binary archive that is portable between 32 and 64 bits is not trivial, because C++ does not specify exactly the size of primitive types. For instance a long is usually 4 bytes on a 32 bits machine, and 8 bytes on a 64 bits machine. In practice though it is pretty portable –there is a non-official version for a portable binary archive.</p>
<p>Related posts:<ol>
<li><a href='http://www.ocoudert.com/blog/2010/07/07/how-to-write-abstract-iterators-in-c/' rel='bookmark' title='How to write abstract iterators in C++'>How to write abstract iterators in C++</a></li>
<li><a href='http://www.ocoudert.com/blog/2011/05/30/how-to-make-software-deterministic/' rel='bookmark' title='How to make software deterministic'>How to make software deterministic</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.ocoudert.com/blog/2011/07/09/a-practical-guide-to-c-serialization/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to make software deterministic</title>
		<link>http://www.ocoudert.com/blog/2011/05/30/how-to-make-software-deterministic/</link>
		<comments>http://www.ocoudert.com/blog/2011/05/30/how-to-make-software-deterministic/#comments</comments>
		<pubDate>Mon, 30 May 2011 17:04:40 +0000</pubDate>
		<dc:creator>Olivier Coudert</dc:creator>
				<category><![CDATA[CodeProject]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[quality]]></category>
		<category><![CDATA[software]]></category>

		<guid isPermaLink="false">http://www.ocoudert.com/blog/?p=1247</guid>
		<description><![CDATA[CodeProject A program is deterministic, or repeatable, if it produces the very same output when given the same input no matter how many times it is run. Refining this definition, we should consider whether a program produces the same result on any platform (32 and 64 bits machines, running Windows, Mac OS, Linux, Solaris, etc). [...] [...]<p>Continue reading <a href="http://www.ocoudert.com/blog/2011/05/30/how-to-make-software-deterministic/">How to make software deterministic</a></p>
Related posts:<ol>
<li><a href='http://www.ocoudert.com/blog/2011/04/09/what-is-software-quality/' rel='bookmark' title='What is software quality?'>What is software quality?</a></li>
<li><a href='http://www.ocoudert.com/blog/2009/10/13/test-driven-design/' rel='bookmark' title='Test-driven design, a methodology for low-defect software'>Test-driven design, a methodology for low-defect software</a></li>
<li><a href='http://www.ocoudert.com/blog/2010/07/07/how-to-write-abstract-iterators-in-c/' rel='bookmark' title='How to write abstract iterators in C++'>How to write abstract iterators in C++</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><a style="display:none;" rel="tag" href="http://www.codeproject.com/script/Articles/BlogFeedList.aspx?amid=6630043">CodeProject</a><br />
A program is deterministic, or repeatable, if it produces the very same output when given the same input no matter how many times it is run.</p>
<p>Refining this definition, we should consider whether a program produces the same result on any platform (32 and 64 bits machines, running Windows, Mac OS, Linux, Solaris, etc). Or whether the program is insensitive to the form of its inputs. For example, the problem of generating the shortest route to visit all the capitals of Europe should not depend on how the map of Europe is entered, nor it should depend on which language is used to name the capitals.</p>
<p>Determinism is obviously very desirable. For the user, a non-deterministic program can be confusing and frustrating. For the developer, a non-deterministic program is extremely hard to test and debug, since bugs and specific configuration cannot be easily reproduced.</p>
<p>Repeatability looks like a given for most applications. For instance, if we add two numbers in a spreadsheet, we expect the same result no matter how many times we perform this operation and regardless of the platform we run on (PC, Mac, etc). Or if we run a spell checker several times, we expect it to flag the very same errors.</p>
<p>But it is not that obvious for more complex applications. This is especially true when there are multiple solutions to a problem, or when heuristics are used to produce a result –because an exact solution is too computationally expensive. For example, it is not uncommon to see slightly different outcomes when running the same EDA synthesis or P&amp;R tool on the same input several times.</p>
<p>Even more, a user would like to see the same result when only minor changes are applied to the input. For instances, running a P&amp;R tool on two netlists that differ only by the names of their cells should produce exactly the same result –a P&amp;R tools should produce a result that only depend on the netlist structure. But experience shows that industrial synthesis and P&amp;R tool does not meet that requirement. Closest to software, it is not uncommon to generate slightly different object codes with gcc by changing the names of a few variables.</p>
<p>Among the causes of non-deterministic response, we can distinguish the following types:</p>
<ol>
<li>A <a href="#random">random number</a> generator</li>
<li>Reading an <a href="#uninitialized">uninitialized</a> data</li>
<li>A <a href="#race">race condition</a> on concurrent threads</li>
<li>An <a href="#unordered">unordered iteration</a> that is assumed ordered</li>
<li>A total order that depends on <a href="#memory_address">memory address</a></li>
<li>A total order that depends on <a href="#time_stamp">time stamps</a></li>
<li>A total order that depends on a <a href="#non_canonical_labelling">non-canonical labeling</a></li>
</ol>
<h4><strong><a name="random"></a>1. Random number generator</strong></h4>
<p>There are a lot of applications that use stochastic processes (e.g., simulated annealing, genetic algorithms, Monte-Carlo simulations), but that we would like to be repeatable. Using a pseudorandom number generator with a known seed makes possible to reproduce the same long sequence of seemingly random numbers over and over again.</p>
<p>Note that some applications (e.g., gaming, cryptography, statistical sampling) <em>require</em> a non-deterministic behavior. In that case the seed of the random number generator must be an always-changing value, for example the host’s current time.</p>
<p>There are more deliberate efforts to produce true random values by relying on natural, chaotic events. For instance <a title="Lavarand" href="http://www.lavarnd.org/">Lavarand</a> produces random numbers by hashing the frames of a video stream of lava lamps. <a href="http://www.fourmilab.ch/hotbits/">HotBits</a> generates random bits by timing successive pairs of radioactive decays detected by a Geiger-Müller tube interfaced to a computer. <a title="Random.org" href="http://www.random.org/">Random.org</a> uses variations in the amplitude of atmospheric noise recorded with a normal radio.<strong> </strong><strong> </strong></p>
<h4><strong><a name="uninitialized"></a>2. Uninitialized or random data read</strong></h4>
<p>Initialized data may not exist in languages that have systematic default values and no memory management control, as opposed to high performance languages like C/C++.</p>
<p>Finding and fixing this kind of issues is relatively simple. For instance, tools like <a href="http://www-01.ibm.com/software/awdtools/purify/">Purify</a> and <a href="http://valgrind.org/">Valgrind</a> can report when a C/C++ code reads arbitrary values in memory. To use Purify’s terminology, such errors are UMR (Uninitialized Memory Read), ABR (Array Bound Read, i.e., dereferencing an array outside of its bounds), and FMR (Free Memory Read). These defects all consist in reading some random value in memory.  The code below illustrates some of these errors.</p>
<pre style="color: #000000; background-color: #ffe3c1;" lang="c++"><small>#include
#include 

int main() {
  bool large;
  int size = 100;

  if (large) {                    // UMR
    size *= 10;
  }

  char* const str    = new char(size);
  char* const middle = str + size/2;
  // Set the end-of-string.
  str[size - 1] = '\0';
  // The loop intends to fill up the string str with 'a'.
  // But this loop is faulty, because *++c is used instead of *c++.
  char* c = str;
  for (int i = 1; i &lt; size; ++i, *++c = 'a');

  printf("%c\n", str[0]);         // UMR
  printf("%c\n", str[1]);         // Ok, will print 'a'.
  printf("%c\n", str[2]);         // Ok, will print 'a'.
  printf("%c\n", str[size - 1]);  // Ok, but will print 'a'
                                  // instead of the expected '\0'.
  printf("%c\n", str[size]);      // ABR
  printf("%lu\n", strlen(str));   // UMR, because we overwrote
                                  // the final '\0' in the loop.
  delete [] str;
  printf("%c\n", *middle);        // FMR

  return 0;
}
</small></pre>
<p>Note that an ABW (Array Bound Write, i.e., writing outside of an array’s bounds), FMW (Free Memory Write), FNH (Freeing Non-Heap memory) and FUM (Freeing Unallocated Memory), although severe bugs also reported by dynamic analysis tools, are not an original source of non-determinism: they consistently reproduce the same bug.<strong> </strong><strong> </strong></p>
<h4><strong><a name="race"></a>3. Thread races</strong></h4>
<p>Thread races are difficult to detect, and fixing them can be very costly. A typical example is when one thread writes a value at some address, and another thread reads the value at that address. Depending on which thread access the address first, the outcome of the program will be different. Two threads performing a non-atomic write at the same address simultaneously results in some unpredictable value.</p>
<p>One can use a mutex to prevent conflicting read/write for non-atomic operations. But racing threads (e.g., who reads/writes first) must be resolved with synchronization, which can be quite complicated. Moreover it can hurt performances.</p>
<h4><strong><a name="unordered"></a>4. Iteration on unordered data</strong></h4>
<p>Iterating data with some random order can make a program non repeatable. This pattern is often encountered, and is easy to fix.</p>
<p>For example an algorithm produces a result via a visitor that assumes a total order. The developer uses an incorrect visitor, which enumerates data in a random order, usually depending on the memory allocation of the data container. E.g., instead of using a <span style="font-family: courier;">std::set</span> as a container, the developer uses a <span style="font-family: courier;">std::hash_set</span> (or a <span style="font-family: courier;">tr1::unordered_set</span> instead of a <span style="font-family: courier;">tr1::ordered_set</span>). Forcing a total order on the data fixes the problem.</p>
<p>Note that the fix may be incomplete if it simply transforms a type (4) non-determinism into a type (5) or (6) non-determinism, which we discuss below.</p>
<h4><strong><a name="memory_address"></a>5. Ordering by pointer value</strong></h4>
<p>This type of non-determinism is extremely common. For instance, a developer uses a <span style="font-family: courier;">tr1::ordered_set</span> as a container of pointers, and feels that the visitor is deterministic. It is indeed deterministic, but only w.r.t. the memory addresses allocated to the data, which depend on factors out of the application’s control.</p>
<p>One way of addressing the problem is to force a specific memory addressing scheme, but that requires a very fine control of the memory allocator and is therefore complicated.  A more common way consists in assigning a unique ID to an object at the time of its creation. The ID can be a 32 bit unsigned integer that is incremented for every new object. A total ordering, independent from the objects’ actual memory addresses, is then obtained from the IDs. It is a simple solution, as long as one can afford the extra 4 bytes for every object. ID-based sorting with no memory penalty can be obtained using custom memory allocators.</p>
<h4><strong><a name="time_stamp"></a>6. Ordering by time stamps</strong></h4>
<p>Note though that the total ID-based ordering described above is exactly the order of creation of the objects. It is no different from an order that depends on time stamps. Therefore two equal sets of inputs that only differ in the order will be visited in a different order, which can lead to different results. This leads us to the type (7) of non-determinism.</p>
<h4><strong><a name="non_canonical_labelling"></a>7. Ordering induced by a non-canonical labeling</strong></h4>
<p>Type (7) non-determinism often goes unrecognized, or is simply ignored. The idea is that as long as the same input is given to a program (but possibly in a different order or form), the output should be the same. If the input can somehow be normalized to a form that captures the notion of “same input”, then the program can be made insensitive to the format of the input. That is of course assuming that the normalization process run time penalty is not too high.</p>
<p>This normalization process is better defined as canonization. Formally, let O be a set of objects, and let EQ be an equivalence relation that captures the notion of “same” on these objects. A function Canon maps an object onto its canonical form, and is such that for any two objects o1 and o2, o1 and o2 are the same (i.e., o1 EQ o2) if and only if Canon(o1) = Canon(o2).</p>
<p>For instance, a set of integers can be represented by a number of containers (a list, an array, a hash set, a binary tree, etc). A canonical form can simply consist in sorting the integers. Two sets that are equal because they contain the very same integers, but that are initially given in different orders and forms, will end up in the same canonical form. Since sorting is an O(n log n) algorithm, this is an efficient canonization.</p>
<p>Canonization can be much more costly. A Boolean function can be represented in many ways, e.g., with a truth table, a Conjunctive Normal Form (CNF), a Disjunctive normal form (DNF), a decision diagram, etc (see below). Boolean function canonization is at least NP-hard, since it solves the satisfiability problem (SAT). In practice this means that Boolean function canonization algorithms have an exponential complexity.</p>
<p><a href="http://www.ocoudert.com/blog/wp-content/uploads/2011/05/Boolean-function.png"><img class="aligncenter size-full wp-image-1257" title="Boolean function" src="http://www.ocoudert.com/blog/wp-content/uploads/2011/05/Boolean-function.png" alt="" width="500" /></a></p>
<p>&nbsp;</p>
<p>Canonization can also be elusive. Let us consider the problem of drawing a graph in some aesthetic way (e.g., such that the nodes are evenly distributed and such that there is a minimum number of crossing edges). One would like the graph to be drawn the very same way, regardless of its representation (adjacency list or adjacency matrix), and regardless of the order the adjacency information is given. For instances the three graphs below, although looking different, are exactly the same, and can be drawn without any edge crossing as shown on the right side.</p>
<p><a href="http://www.ocoudert.com/blog/wp-content/uploads/2011/05/graph-drawing-2.png"><img class="size-full wp-image-1259 aligncenter" title="graph drawing 2" src="http://www.ocoudert.com/blog/wp-content/uploads/2011/05/graph-drawing-2.png" alt="" width="500" /></a></p>
<p>&nbsp;</p>
<p>Graph canonization is also known as graph labeling. It is at least as hard as graph isomorphism, one of these rare problems that are in NP but that are not known to be NP-complete or in P. Although all existing graph canonization algorithm have an exponential worst-case complexity, it is believed that graph canonization can be done in polynomial time.</p>
<h4><strong>Conclusion </strong></h4>
<p><strong> </strong></p>
<p>The most common  cause for non-determinism is related to some unreliable data order. The ultimate solution to make a program insensitive to the form of its input is to canonize its input as a pre-processing step. This proves to be a challenging and costly task in some cases. Whenever possible, canonization (or some imperfect normalization) goes a long way to make the application consistently repeatable.</p>
<p>Related posts:<ol>
<li><a href='http://www.ocoudert.com/blog/2011/04/09/what-is-software-quality/' rel='bookmark' title='What is software quality?'>What is software quality?</a></li>
<li><a href='http://www.ocoudert.com/blog/2009/10/13/test-driven-design/' rel='bookmark' title='Test-driven design, a methodology for low-defect software'>Test-driven design, a methodology for low-defect software</a></li>
<li><a href='http://www.ocoudert.com/blog/2010/07/07/how-to-write-abstract-iterators-in-c/' rel='bookmark' title='How to write abstract iterators in C++'>How to write abstract iterators in C++</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.ocoudert.com/blog/2011/05/30/how-to-make-software-deterministic/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Amazon&#8217;s outage, a step back for EDA in the cloud?</title>
		<link>http://www.ocoudert.com/blog/2011/05/04/amazons-outage-a-step-back-for-eda-in-the-cloud/</link>
		<comments>http://www.ocoudert.com/blog/2011/05/04/amazons-outage-a-step-back-for-eda-in-the-cloud/#comments</comments>
		<pubDate>Wed, 04 May 2011 21:56:39 +0000</pubDate>
		<dc:creator>Olivier Coudert</dc:creator>
				<category><![CDATA[EDA]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[cloud computing]]></category>

		<guid isPermaLink="false">http://www.ocoudert.com/blog/?p=1226</guid>
		<description><![CDATA[On Thursday, April 21st, Amazon experienced a large outage that took down hundreds of websites, including the popular Foursquare, Reddit, Springpad, Hootsuite, BigDoor, and Quora. The service was fully resumed only 3 days later. Amazon released a full description of what happened. In a nutshell, Amazon shifted traffic in one of its zones from one [...] [...]<p>Continue reading <a href="http://www.ocoudert.com/blog/2011/05/04/amazons-outage-a-step-back-for-eda-in-the-cloud/">Amazon&#8217;s outage, a step back for EDA in the cloud?</a></p>
Related posts:<ol>
<li><a href='http://www.ocoudert.com/blog/2011/03/16/cloud-computing-an-opportunity-for-eda/' rel='bookmark' title='Cloud computing: an opportunity for EDA'>Cloud computing: an opportunity for EDA</a></li>
<li><a href='http://www.ocoudert.com/blog/2011/03/29/synopsys-getting-into-the-cloud/' rel='bookmark' title='Synopsys is getting into the cloud'>Synopsys is getting into the cloud</a></li>
<li><a href='http://www.ocoudert.com/blog/2011/03/22/eda-in-the-cloud-shall-we-be-scared/' rel='bookmark' title='EDA in the cloud: shall we be scared?'>EDA in the cloud: shall we be scared?</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.ocoudert.com/blog/wp-content/uploads/2011/05/Cloud-Computing-Failure1.jpg"><img class="alignright size-full wp-image-1236" title="Cloud-Computing-Failure1" src="http://www.ocoudert.com/blog/wp-content/uploads/2011/05/Cloud-Computing-Failure1.jpg" alt="" width="224" height="221" /></a>On Thursday, April 21st, Amazon experienced a large outage that took down hundreds of websites, including the popular Foursquare, Reddit, Springpad, Hootsuite, BigDoor, and Quora. The service was fully resumed only 3 days later.</p>
<p>Amazon released a full <a rel="nofollow" href="http://aws.amazon.com/message/65648/">description</a> of what happened. In a nutshell, Amazon shifted traffic in one of its zones from one network to another in order to upgrade a network. The traffic was mistakenly shifted to a lower capacity network, which was unable to handle the traffic. This caused Amazon EBS volumes (Elastic Block Store, a persistent storage unit for database and file system) in one US East Region zone to become unable to perform read/write operations.</p>
<p>Besides the many websites taken down during the outage, it turned out that 0.07% of the data stored in the EBS volumes in one zone have also been <a rel="nofollow" href="http://www.techflash.com/seattle/2011/04/Amazon-says-some-data-lost-in-cloud.html">lost</a>. Chartbeat reports <a rel="nofollow" href="http://www.webhostingsearch.com/blog/amazon-ec2-outage-resulted-in-permanent-data-loss-0996">losing</a> 11 hours of historical data to their customers saying it is ‘irrecoverable’.</p>
<p>Since then a lot has been written about the dangers of the cloud. It looks like Amazon’s outage brought weight to those opposing security concerns against EDA’s cloud aspirations. What to think of Synopsys&#8217; recent <a href="http://www.ocoudert.com/blog/2011/03/29/synopsys-getting-into-the-cloud/">announcement</a> that they will provide SaaS in Amazon Web Services?</p>
<p>But many companies that are entirely relying on Amazon’s cloud services were not significantly affected by the outage. Twilio did not shut down. And more notably, Netflix, which runs its massive infrastructure entirely in Amazon’s cloud, did <a rel="nofollow" href="http://techblog.netflix.com/2011/04/lessons-netflix-learned-from-aws-outage.html">not</a> shut down.</p>
<p>Why were some websites taken down while others were unaffected? Because some systems are designed to be resilient to all sort of failures. Taken from Netflix’ <a rel="nofollow" href="http://techblog.netflix.com/2010/12/5-lessons-weve-learned-using-aws.html">experience</a> when moving its infrastructure to AWS:</p>
<blockquote><p>&#8220;One of the first systems our engineers built in AWS is called the Chaos Monkey. The Chaos Monkey’s job is to randomly kill instances and services within our architecture. If we aren’t constantly testing our ability to succeed despite failure, then it isn’t likely to work when it matters most – in the event of an unexpected outage.&#8221;</p></blockquote>
<p>In short, being in the cloud does not mean you are inherently safer or more exposed. It means that you have to design your system so that it can recover from defects –any defect. <a rel="nofollow" href="http://broadcast.oreilly.com/2011/04/the-aws-outage-the-clouds-shining-moment.html">From</a> G. Reese in O’Reilly:</p>
<blockquote><p>&#8220;If your systems failed in the Amazon cloud this week, it wasn&#8217;t Amazon&#8217;s fault. You either deemed an outage of this nature an acceptable risk or you failed to design for Amazon&#8217;s cloud computing model. The strength of cloud computing is that it puts control over application availability in the hands of the application developer and not in the hands of your IT staff, data center limitations, or a managed services provider.&#8221;</p></blockquote>
<p>And I’ll stand by this too.</p>
<p>Related posts:<ol>
<li><a href='http://www.ocoudert.com/blog/2011/03/16/cloud-computing-an-opportunity-for-eda/' rel='bookmark' title='Cloud computing: an opportunity for EDA'>Cloud computing: an opportunity for EDA</a></li>
<li><a href='http://www.ocoudert.com/blog/2011/03/29/synopsys-getting-into-the-cloud/' rel='bookmark' title='Synopsys is getting into the cloud'>Synopsys is getting into the cloud</a></li>
<li><a href='http://www.ocoudert.com/blog/2011/03/22/eda-in-the-cloud-shall-we-be-scared/' rel='bookmark' title='EDA in the cloud: shall we be scared?'>EDA in the cloud: shall we be scared?</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.ocoudert.com/blog/2011/05/04/amazons-outage-a-step-back-for-eda-in-the-cloud/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>What is software quality?</title>
		<link>http://www.ocoudert.com/blog/2011/04/09/what-is-software-quality/</link>
		<comments>http://www.ocoudert.com/blog/2011/04/09/what-is-software-quality/#comments</comments>
		<pubDate>Sun, 10 Apr 2011 06:21:24 +0000</pubDate>
		<dc:creator>Olivier Coudert</dc:creator>
				<category><![CDATA[CodeProject]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[quality]]></category>
		<category><![CDATA[software]]></category>

		<guid isPermaLink="false">http://www.ocoudert.com/blog/?p=1125</guid>
		<description><![CDATA[CodeProject The quality of software is assessed by a number of variables. These variables can be divided into external and internal quality criteria. External quality is what a user experiences when running the software in its operational mode. Internal quality refers to aspects that are code-dependent, and that are not visible to the end-user. External [...] [...]<p>Continue reading <a href="http://www.ocoudert.com/blog/2011/04/09/what-is-software-quality/">What is software quality?</a></p>
Related posts:<ol>
<li><a href='http://www.ocoudert.com/blog/2011/05/30/how-to-make-software-deterministic/' rel='bookmark' title='How to make software deterministic'>How to make software deterministic</a></li>
<li><a href='http://www.ocoudert.com/blog/2009/10/13/test-driven-design/' rel='bookmark' title='Test-driven design, a methodology for low-defect software'>Test-driven design, a methodology for low-defect software</a></li>
<li><a href='http://www.ocoudert.com/blog/2010/07/07/how-to-write-abstract-iterators-in-c/' rel='bookmark' title='How to write abstract iterators in C++'>How to write abstract iterators in C++</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><a style="display: none;" href="http://www.codeproject.com/script/Articles/BlogFeedList.aspx?amid=6630043" rel="tag">CodeProject</a><br />
<a href="http://www.ocoudert.com/blog/wp-content/uploads/2011/04/qualityassurance.jpg"><img class="alignright size-medium wp-image-1156" title="qualityassurance" src="http://www.ocoudert.com/blog/wp-content/uploads/2011/04/qualityassurance-300x200.jpg" alt="" width="300" height="200" /></a>The quality of software is assessed by a number of variables. These variables can be divided into external and internal quality criteria. External quality is what a user experiences when running the software in its operational mode. Internal quality refers to aspects that are code-dependent, and that are not visible to the end-user. External quality is critical to the user, while internal quality is meaningful to the developer only.</p>
<p>Some quality criteria are objective, and can be measured accordingly. Some quality criteria are subjective, and are therefore captured with more arbitrary measurements.</p>
<p>The table below lists the most obvious software quality criteria, as well as some lesser known.</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="118"></td>
<td style="text-align: center;" valign="top" width="59">User</td>
<td style="text-align: center;" valign="top" width="63">Developer</td>
<td style="text-align: center;" valign="top" width="95">Measurable</td>
</tr>
<tr>
<td colspan="4" valign="top" width="334">External quality</td>
</tr>
<tr>
<td valign="top" width="118"><a href="#features">features</a></td>
<td style="text-align: center;" valign="top" width="59">x</td>
<td valign="top" width="63"></td>
<td style="text-align: center;" valign="top" width="95">yes</td>
</tr>
<tr>
<td valign="top" width="118"><a href="#speed">speed</a></td>
<td style="text-align: center;" valign="top" width="59">x</td>
<td style="text-align: center;" valign="top" width="63">x</td>
<td style="text-align: center;" valign="top" width="95">yes</td>
</tr>
<tr>
<td valign="top" width="118"><a href="#space">space</a></td>
<td style="text-align: center;" valign="top" width="59">x</td>
<td style="text-align: center;" valign="top" width="63">x</td>
<td style="text-align: center;" valign="top" width="95">yes</td>
</tr>
<tr>
<td valign="top" width="118"><a href="#network">network usage</a></td>
<td style="text-align: center;" valign="top" width="59">x</td>
<td style="text-align: center;" valign="top" width="63">x</td>
<td style="text-align: center;" valign="top" width="95">yes</td>
</tr>
<tr>
<td valign="top" width="118"><a href="#stability">stability</a></td>
<td style="text-align: center;" valign="top" width="59">x</td>
<td style="text-align: center;" valign="top" width="63">x</td>
<td style="text-align: center;" valign="top" width="95">yes</td>
</tr>
<tr>
<td valign="top" width="118"><a href="#robustness">robustness</a></td>
<td style="text-align: center;" valign="top" width="59">x</td>
<td style="text-align: center;" valign="top" width="63">x</td>
<td style="text-align: center;" valign="top" width="95">somewhat</td>
</tr>
<tr>
<td valign="top" width="118"><a href="#eou">ease-of-use</a></td>
<td style="text-align: center;" valign="top" width="59">x</td>
<td valign="top" width="63"></td>
<td style="text-align: center;" valign="top" width="95">subjective</td>
</tr>
<tr>
<td valign="top" width="118"><a href="#determinism">determinism</a></td>
<td style="text-align: center;" valign="top" width="59">x</td>
<td style="text-align: center;" valign="top" width="63">x</td>
<td style="text-align: center;" valign="top" width="95">yes</td>
</tr>
<tr>
<td valign="top" width="118"><a href="#compatibility">back-compatibility</a></td>
<td style="text-align: center;" valign="top" width="59">x</td>
<td valign="top" width="63"></td>
<td style="text-align: center;" valign="top" width="95">yes</td>
</tr>
<tr>
<td valign="top" width="118"><a href="#security">security</a></td>
<td style="text-align: center;" valign="top" width="59">x</td>
<td valign="top" width="63"></td>
<td style="text-align: center;" valign="top" width="95">difficult</td>
</tr>
<tr>
<td valign="top" width="118"><a href="#power">power consumption</a></td>
<td style="text-align: center;" valign="top" width="59">x</td>
<td valign="top" width="63"></td>
<td style="text-align: center;" valign="top" width="95">difficult</td>
</tr>
<tr>
<td colspan="4" valign="top" width="334">Internal quality</td>
</tr>
<tr>
<td valign="top" width="118"><a href="#coverage">test coverage</a></td>
<td valign="top" width="59"></td>
<td style="text-align: center;" valign="top" width="63">x</td>
<td style="text-align: center;" valign="top" width="95">yes</td>
</tr>
<tr>
<td valign="top" width="118"><a href="#testability">testability</a></td>
<td valign="top" width="59"></td>
<td style="text-align: center;" valign="top" width="63">x</td>
<td style="text-align: center;" valign="top" width="95">hard</td>
</tr>
<tr>
<td valign="top" width="118"><a href="#portability">portability</a></td>
<td valign="top" width="59"></td>
<td style="text-align: center;" valign="top" width="63">x</td>
<td style="text-align: center;" valign="top" width="95">somewhat</td>
</tr>
<tr>
<td valign="top" width="118"><a href="#thread">thread-safeness</a></td>
<td valign="top" width="59"></td>
<td style="text-align: center;" valign="top" width="63">x</td>
<td style="text-align: center;" valign="top" width="95">hard</td>
</tr>
<tr>
<td valign="top" width="118"><a href="#conciseness">conciseness</a></td>
<td valign="top" width="59"></td>
<td style="text-align: center;" valign="top" width="63">x</td>
<td style="text-align: center;" valign="top" width="95">somewhat</td>
</tr>
<tr>
<td valign="top" width="118"><a href="#maintainability">maintainability</a></td>
<td valign="top" width="59"></td>
<td style="text-align: center;" valign="top" width="63">x</td>
<td style="text-align: center;" valign="top" width="95">hard</td>
</tr>
<tr>
<td valign="top" width="118"><a href="#documentation">documentation</a></td>
<td valign="top" width="59"></td>
<td style="text-align: center;" valign="top" width="63">x</td>
<td style="text-align: center;" valign="top" width="95">subjective</td>
</tr>
<tr>
<td valign="top" width="118"><a href="#legibility">legibility</a></td>
<td valign="top" width="59"></td>
<td style="text-align: center;" valign="top" width="63">x</td>
<td style="text-align: center;" valign="top" width="95">subjective</td>
</tr>
<tr>
<td valign="top" width="118"><a href="#scalability">scalability</a></td>
<td valign="top" width="59"></td>
<td style="text-align: center;" valign="top" width="63">x</td>
<td style="text-align: center;" valign="top" width="95">somewhat</td>
</tr>
</tbody>
</table>
<p>By definition the internal quality (code characteristics) is a concern to the developer only, while all the external quality aspects (coming from using the software) are critical to the end user. However the developer has also interests in performances (speed, space, network usage) and determinism, because they make testing the software easier. Developers treat ease-of-use, back-compatibility, security, and power consumption as requirements.</p>
<p>It is important to consider how difficult it is to measure each of these criteria. It can be difficult because there is no simple variable to look at, or because the measurement process is costly, or because it requires a complex infrastructure. For instance, speed has an objective measurement that is easy to measure. Power consumption has a simple measurement (how many µW the application consumes), but it is complex to measure. Security is difficult and costly to estimate.</p>
<p><a name="features"></a> <strong>Features</strong>. This is the very reason for the software to be written: to provide a service. By feature we really mean the output produced by the software –e.g., a numerical result, a string, a screen shot, a web page, an audio, etc&#8211;, regardless of the performances (speed, memory).</p>
<p><a name="speed"></a><strong>Speed</strong>. How quickly does the application provide the service? The user experiences the actual time elapsed between the moment she request the service, and the moment the service is delivered. The real elapsed time, or wall time, is the sum of the CPU time, system time, and network latency. Thus the developer should not only focus on the CPU time (how much time the CPU actually spends on executing the program). The CPU time can easily be overshadowed by disk access (a write on the disk is very costly), swapping (due to an excessive virtual memory size), or time spent by the network (latency issue, or too many round trips).</p>
<p><a name="space"></a><strong>Space</strong>. How much RAM and disk space is taken by the application? The aggregate numbers are important –peak memory, virtual memory size, etc. But even more so, how often do we move data that triggers a CPU cache miss or a disk write, has a dominant impact on the speed of the application. A mediocre data design can lead to very poor performances.</p>
<p><a name="network"></a><strong>Network usage</strong>. It is a matter of bandwidth and latency. Mismanaging sockets and channels can lead to unnecessary extra time spent in opening and closing sockets, handshakes, and round trips. As for memory, caching techniques can be used to reduce consuming network resources.</p>
<p><a name="stability"></a><strong>Stability</strong>. How often does one need to patch the software to fix problems? For the user, this is an inconvenience. For the developer, it means that the code is fragile and might benefit from better testing or partial rewrite.</p>
<p><a name="robustness"></a><strong>Robustness</strong>. How often does the application stale, freeze, or crash? How tolerant is it to extreme conditions –limited CPU and memory/disk/network resources, corner cases, system failure or unresponsive 3<sup>rd</sup>-party resources? This aspect is strongly related to testability and coverage.</p>
<p><a name="eou"></a><strong>Ease-of-use</strong>. It can be a very subjective factor, hard to quantify. It includes user documentation, clarity of the error message, management of exceptions, and recovery after failure.</p>
<p><a name="determinism"></a><strong>Determinism</strong>. Also known as repeatability: does the program produce the very same result given the same input? There are many reasons for which a program can exhibit a non-repeatable behavior. A non-repeatable behavior is confusing and frustrating for the user. This also makes the program very difficult to test and debug. Repeatability is strongly dependent on a good data model design.</p>
<p><a name="compatibility"></a><strong>Back-compatibility</strong>. Can a new version of the application be used with an older version’s data? It is essential to the user, because a new version should not require a costly migration of the existing data.</p>
<p><a name="security"></a><strong>Security</strong>. Who is authorized to access the data? Can the data processed by the application be compromised? This is a crucial aspect of many applications, and it is getting more and more difficult to assess with the dissemination of mobile and web-based software.</p>
<p><a name="power"></a><strong>Power consumption</strong>. It is increasingly important with mobile applications, as a program may have to consider how it manages the device’s power producers and consumers (battery, cores, wireless, screen, audio), and not to rely entirely on the operating system.</p>
<p><a name="coverage"></a><strong>Test coverage</strong>. What is the proportion of code that is executed by some unit or regression test? This is measured by the number of lines, number of functions, and number of control branches that are exercised by the tests. Usually one expects coverage of at least 85% for any moderately complex application. In practice reaching high coverage can be achieved only if testability is high, which has deep implication on the architecture and development methodology.</p>
<p><a name="testability"></a><strong>Testability</strong>. An often overlooked or simply ignored aspect of code development, testability is the ability to trigger any specific line of code or branching condition. Highly testable code requires a discipline of architecture and development that is difficult to find. It very costly to fix poorly testable software, as this requires major redesign. This justifies major investment in software architecture, design, and development methodologies.</p>
<p><a name="portability"></a><strong>Portability</strong>. Can the application run on 32 and 64 bits machines? Should it run on a mobile phone? Does it run on multiple OS (e.g., Windows, Linux, Mac OS-X, Solaris, iOS, Android, RIM)? Does it run smoothly on all web browsers (IE, Firefox, Chrome, Safari, Opera)?</p>
<p><a name="thread"></a><strong>Thread-safeness</strong>. Is a specific component thread-safe? Can two threads collide on non-atomic operations? Can the application get into a deadlock? As concurrency is still mostly the result of a manual process (there no compiler that automatically parallelizes the code), these questions are critical to ensure the good functioning of a program, as well as its performance –it is not rare to see the a program running <em>slower</em> when two many threads are available, as the cost of synchronization can become dominant.</p>
<p><a name="conciseness"></a><strong>Conciseness</strong>. Also known as compactness. Is there any dead code, or duplicated code? Is the code shared and factorized properly? A compact code usually means faster compilation and smaller binary size. Also compactness naturally leads to fewer bugs, because the number of bugs is historically <a href="../2009/10/13/test-driven-design/#kloc_per_defect">constant</a> w.r.t. code size.</p>
<p><a name="maintainability"></a><strong>Maintainability</strong>. How easy it is to debug the code? How fast is it to provide a fix? How quickly can a new developer understand the code? Maintainability is a very important aspect, quite difficult to quantify. Maintainability is increased with good testability and flexible (abstract) design.</p>
<p><a name="documentation"></a><strong>Documentation</strong>. This is a pretty subjective topic. Some people claim that a separate documentation written in plain English is necessary. Some others state that at least 30% of the code should be comments. Some finally argue that the code itself is the best documentation –the names of the types, classes, functions and arguments, together with plenty of assertions.</p>
<p><a name="legibility"></a><strong>Legibility</strong>. Also known as readability. This is another subjective topic. It is about how easy it is to read the code. Guidelines are established to unify the style of the code, so that a developer can easily read code written by another developer. Code guidelines abound, and they go from a small set of directives, to a full set of rules that specify every syntactical aspect of the language. For example, see <a href="http://hem.passagen.se/erinyq/industrial/" rel="nofollow">Industrial Strength C++</a>, <a href="http://www.codingstandard.com/HICPPCM/index.html" rel="nofollow">High Integrity C++</a>, <a href="http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml" rel="nofollow">Google C++ Style Guide</a>, and <a href="http://www.maultech.com/chrislott/resources/cstyle/" rel="nofollow">many</a> <a href="http://www.possibility.com/Cpp/CppCodingStandard.html" rel="nofollow">more</a>.</p>
<p><a name="scalability"></a><strong>Scalability</strong>. How easy it is to extend a feature? Or to add a new one? Or to add extra cores, or increase the size of the cluster the application runs on? Again, this is all about software architecture and anticipating future needs.</p>
<p>Software quality is the result of the user experience. But software quality should not and cannot be a reactive action to external defects. Software quality is built from the ground up, with design and development methodologies, and with a special focus on testability, coverage, and flexibility.</p>
<p>Related posts:<ol>
<li><a href='http://www.ocoudert.com/blog/2011/05/30/how-to-make-software-deterministic/' rel='bookmark' title='How to make software deterministic'>How to make software deterministic</a></li>
<li><a href='http://www.ocoudert.com/blog/2009/10/13/test-driven-design/' rel='bookmark' title='Test-driven design, a methodology for low-defect software'>Test-driven design, a methodology for low-defect software</a></li>
<li><a href='http://www.ocoudert.com/blog/2010/07/07/how-to-write-abstract-iterators-in-c/' rel='bookmark' title='How to write abstract iterators in C++'>How to write abstract iterators in C++</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.ocoudert.com/blog/2011/04/09/what-is-software-quality/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>France&#8217;s double standards on privacy</title>
		<link>http://www.ocoudert.com/blog/2011/04/05/france-double-standards-on-privacy/</link>
		<comments>http://www.ocoudert.com/blog/2011/04/05/france-double-standards-on-privacy/#comments</comments>
		<pubDate>Tue, 05 Apr 2011 23:18:24 +0000</pubDate>
		<dc:creator>Olivier Coudert</dc:creator>
				<category><![CDATA[social network]]></category>
		<category><![CDATA[Facebook]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[privacy]]></category>

		<guid isPermaLink="false">http://www.ocoudert.com/blog/?p=1065</guid>
		<description><![CDATA[On March 1, the French government regulated that Internet companies must keep their users’ data for a year, and make them available to the authorities when subpoenaed. These data include anything used to identify a user and allow her to use a web service, i.e., ID, password, name, email addresses, as well as postal address and [...] [...]<p>Continue reading <a href="http://www.ocoudert.com/blog/2011/04/05/france-double-standards-on-privacy/">France&#8217;s double standards on privacy</a></p>
Related posts:<ol>
<li><a href='http://www.ocoudert.com/blog/2010/06/25/why-facebook-wants-you-to-believe-that-%e2%80%9cemail-is-dead%e2%80%9d/' rel='bookmark' title='Why Facebook wants you to believe that “email is dead”'>Why Facebook wants you to believe that “email is dead”</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.ocoudert.com/blog/wp-content/uploads/2011/04/login.jpg"><img class="alignright size-full wp-image-1082" title="login" src="http://www.ocoudert.com/blog/wp-content/uploads/2011/04/login.jpg" alt="privacy" width="250" /></a>On March 1, the French government regulated that Internet companies must  keep their users’ data for a year, and make them available to the  authorities when subpoenaed. These data include anything used to identify a user and allow her to use  a web service, i.e., ID, password, name, email addresses, as well as  postal address and phone number when available.</p>
<p>Continue reading <a rel="nofollow" title="France's double standards on privacy" href="http://thenextweb.com/eu/2011/04/06/france%E2%80%99s-double-standards-on-privacy/">France&#8217;s double standards on privacy</a></p>
<p>Related posts:<ol>
<li><a href='http://www.ocoudert.com/blog/2010/06/25/why-facebook-wants-you-to-believe-that-%e2%80%9cemail-is-dead%e2%80%9d/' rel='bookmark' title='Why Facebook wants you to believe that “email is dead”'>Why Facebook wants you to believe that “email is dead”</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.ocoudert.com/blog/2011/04/05/france-double-standards-on-privacy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

