<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	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/"
		>
<channel>
	<title>Comments on: Micro-optimization is stupid</title>
	<atom:link href="http://blog.codef00.com/2009/02/11/micro-optimization-is-stupid/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.codef00.com/2009/02/11/micro-optimization-is-stupid/</link>
	<description>Just some thoughts from a computer geek</description>
	<lastBuildDate>Thu, 05 Jan 2012 18:32:24 +0000</lastBuildDate>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
	<item>
		<title>By: Kevin</title>
		<link>http://blog.codef00.com/2009/02/11/micro-optimization-is-stupid/comment-page-1/#comment-6291</link>
		<dc:creator>Kevin</dc:creator>
		<pubDate>Tue, 14 Dec 2010 10:00:13 +0000</pubDate>
		<guid isPermaLink="false">http://blog.codef00.com/?p=35#comment-6291</guid>
		<description>There is an excessively tiny difference:

  std::list::end will return something from the std::list, it is inlined and in
 GNU world it looks like this:

iterator
 end()
{ return iterator(&amp;this-&gt;_M_impl._M_node); }

and underneath, without looking to closely, the type iterator is basically a 
wrapper over a pointer, so no big deal.

I still have not gotten to the difference yet: if the std::list object is passed by 
pointer or reference, then the value looked up from std::list::end() is not 
on the stack, where as

std::list::iterator i, end;

are on the stack. So in _theory_ what the poster said could avoid a cache miss.
Because of side effects, the compiler cannot cache the return value to std::list::end,
unless the contents of the for-loop contains no function calls (or all function calls
are inlined function and those themselves follow that rule and all do not
touch the std::list, but even then that is putting alot of faith in the optimizing compiler).
But even then, the memory location where the value of std::list::end is located will
be put into the cache anyways after the first call, so unless the contents do enough
jazz to push it out of the cache, then there won&#039;t be a cache miss anyways.

For std::vector, the story is actually the same, internally the end of the container is stored, 
not the size, so repeated calls to std::vector::end are the same story, so you _might_  get
a cache miss in doing it, with the same jazz as noted for std::list::end.

Lastly, the boost macro BOOST_FOR_EACH, uses saving the begin and end iterators as
well, so for such loop constructs it is bad luck to add/remove elements from the
container. Generally speaking, one usually cannot go wrong in emulating the behavior 
of boost.</description>
		<content:encoded><![CDATA[<p>There is an excessively tiny difference:</p>
<p>  std::list::end will return something from the std::list, it is inlined and in<br />
 GNU world it looks like this:</p>
<p>iterator<br />
 end()<br />
{ return iterator(&amp;this-&gt;_M_impl._M_node); }</p>
<p>and underneath, without looking to closely, the type iterator is basically a<br />
wrapper over a pointer, so no big deal.</p>
<p>I still have not gotten to the difference yet: if the std::list object is passed by<br />
pointer or reference, then the value looked up from std::list::end() is not<br />
on the stack, where as</p>
<p>std::list::iterator i, end;</p>
<p>are on the stack. So in _theory_ what the poster said could avoid a cache miss.<br />
Because of side effects, the compiler cannot cache the return value to std::list::end,<br />
unless the contents of the for-loop contains no function calls (or all function calls<br />
are inlined function and those themselves follow that rule and all do not<br />
touch the std::list, but even then that is putting alot of faith in the optimizing compiler).<br />
But even then, the memory location where the value of std::list::end is located will<br />
be put into the cache anyways after the first call, so unless the contents do enough<br />
jazz to push it out of the cache, then there won&#8217;t be a cache miss anyways.</p>
<p>For std::vector, the story is actually the same, internally the end of the container is stored,<br />
not the size, so repeated calls to std::vector::end are the same story, so you _might_  get<br />
a cache miss in doing it, with the same jazz as noted for std::list::end.</p>
<p>Lastly, the boost macro BOOST_FOR_EACH, uses saving the begin and end iterators as<br />
well, so for such loop constructs it is bad luck to add/remove elements from the<br />
container. Generally speaking, one usually cannot go wrong in emulating the behavior<br />
of boost.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Chris</title>
		<link>http://blog.codef00.com/2009/02/11/micro-optimization-is-stupid/comment-page-1/#comment-3036</link>
		<dc:creator>Chris</dc:creator>
		<pubDate>Thu, 13 May 2010 09:39:37 +0000</pubDate>
		<guid isPermaLink="false">http://blog.codef00.com/?p=35#comment-3036</guid>
		<description>I prefer this:

std::list::iterator it = l.begin();
const std::list::iterator end = l.end();
while (it != end) { /* whatever */ it++; }

I don&#039;t do this much, but it is possible too:

void PrintSomeItems(std::list::iterator&amp; it, const std::list::iterator&amp; end)
{
  while (it != end) { /* whatever */ it++; }
}

PrintSomeItems(it, end);

This function can be templated to accept a vector too for more awesomeness.</description>
		<content:encoded><![CDATA[<p>I prefer this:</p>
<p>std::list::iterator it = l.begin();<br />
const std::list::iterator end = l.end();<br />
while (it != end) { /* whatever */ it++; }</p>
<p>I don&#8217;t do this much, but it is possible too:</p>
<p>void PrintSomeItems(std::list::iterator&amp; it, const std::list::iterator&amp; end)<br />
{<br />
  while (it != end) { /* whatever */ it++; }<br />
}</p>
<p>PrintSomeItems(it, end);</p>
<p>This function can be templated to accept a vector too for more awesomeness.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Evan Teran</title>
		<link>http://blog.codef00.com/2009/02/11/micro-optimization-is-stupid/comment-page-1/#comment-493</link>
		<dc:creator>Evan Teran</dc:creator>
		<pubDate>Fri, 13 Feb 2009 02:37:13 +0000</pubDate>
		<guid isPermaLink="false">http://blog.codef00.com/?p=35#comment-493</guid>
		<description>Indeed without optimizations the compiler does the obvious thing which is terribly slow. In fact, much of the STL is often slow when there are no optimizations. Fortunately though current c++ compilers are pretty damn impressive with optimizations :)</description>
		<content:encoded><![CDATA[<p>Indeed without optimizations the compiler does the obvious thing which is terribly slow. In fact, much of the STL is often slow when there are no optimizations. Fortunately though current c++ compilers are pretty damn impressive with optimizations <img src='http://blog.codef00.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
	</item>
	<item>
		<title>By: WRS</title>
		<link>http://blog.codef00.com/2009/02/11/micro-optimization-is-stupid/comment-page-1/#comment-492</link>
		<dc:creator>WRS</dc:creator>
		<pubDate>Fri, 13 Feb 2009 02:21:31 +0000</pubDate>
		<guid isPermaLink="false">http://blog.codef00.com/?p=35#comment-492</guid>
		<description>After reading your post my first thought was, yeah you&#039;re right but why not do it that jerk&#039;s way in case it does matter. In fact I thought I remembered running into an instance where it did matter... map I think it was. So unlike the friend in our story above, I decided to code up the two examples and run them through gprof so I could see exactly how many times end() was called in each.

Long story short, they were EXACTLY the same when using optimization. Without optimization, there was a penalty for calling end() each time... it is not a O(1) but O(lg n) operation.

All-in-all, Evan I only have one issue with the blog... you need to post more often. As always, good stuff!</description>
		<content:encoded><![CDATA[<p>After reading your post my first thought was, yeah you&#8217;re right but why not do it that jerk&#8217;s way in case it does matter. In fact I thought I remembered running into an instance where it did matter&#8230; map I think it was. So unlike the friend in our story above, I decided to code up the two examples and run them through gprof so I could see exactly how many times end() was called in each.</p>
<p>Long story short, they were EXACTLY the same when using optimization. Without optimization, there was a penalty for calling end() each time&#8230; it is not a O(1) but O(lg n) operation.</p>
<p>All-in-all, Evan I only have one issue with the blog&#8230; you need to post more often. As always, good stuff!</p>
]]></content:encoded>
	</item>
</channel>
</rss>

