<?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: ESUG Screencast</title>
	<atom:link href="http://www.mirandabanda.org/cogblog/2010/07/20/29/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.mirandabanda.org/cogblog/2010/07/20/29/</link>
	<description>Speeding Up Croquet and Squeak with a new open-source VM from Teleplace</description>
	<lastBuildDate>Mon, 05 Sep 2011 20:38:51 +0000</lastBuildDate>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
	<item>
		<title>By: Eliot Miranda</title>
		<link>http://www.mirandabanda.org/cogblog/2010/07/20/29/comment-page-1/#comment-4203</link>
		<dc:creator>Eliot Miranda</dc:creator>
		<pubDate>Sun, 17 Oct 2010 20:35:49 +0000</pubDate>
		<guid isPermaLink="false">http://www.mirandabanda.org/cogblog/?p=29#comment-4203</guid>
		<description>Hi Igor,

    you have to balance the cost of GC against the cost of the extra indirection.  Since GCs are relatively rare I think it&#039;s better to concentrate on runtime performance.  Remember, dedicating a register to point to objects means an extra register to save and restore around every send, not just method activation.

But GC time is important and Cog takes care to minimise the amount of work done scanning machine code.  It does this by maintaining a list of native methods that contain references to objects in newSpace.  See CogMethodZone&gt;youngReferrers.  So on incremental GC only those methods that contain young object references are scanned and, you guessed it, in the normal case the young referrers list is empty.  Only when you compile new code or do a become does the young referrer list get populated.

As far as the metadata goes that&#039;s of the order of one byte per reference and that&#039;s only a third of all metadata.  Eliminating them would only save 1.4% of the used space, only a little more than the extra 4 bytes needed in a method to refer to its indirect literals, ignoring the size taken by the extra save-restore code for the indirect references.

In summary keeping object references in machine code may appear costly but it is both more efficient and not a problem for GC in practice since few if any methods refer to new objects and global garbage collections are extremely rare.


FYI here&#039;s the code I used to gather the above stats (I had to write Cogit&gt;&gt;mapFor:do: and will add it to the VMMaker package soon).  I ran an image under Cog and measured the state after start-up:

&lt;code&gt;&lt;pre&gt;&#124; annotations num nmethods types &#124;
annotations := Bag new.
nmethods := num := 0.
self methodsDo:
	[:m&#124;
	m cmType = CMMethod ifTrue:
		[nmethods := nmethods + 1.
		cogit mapFor: m do: [:ann :pc&#124; num := num + 1.  annotations add: ann. false]]].
		&quot;table copied from Cogit class&gt;&gt;initializeAnnotationConstants&quot;
types := #(	IsSendCall
		IsRelativeCall
		HasBytecodePC
		IsMethodReference
		IsObjectReference
		nil
		nil) reverse.
{ nmethods. num. (annotations sortedCounts collect: [:assoc&#124; { assoc key * 100 / num roundTo: 0.1. assoc key. types at: assoc value }]) }

#(&quot;nmethods&quot; 1366
   &quot;nannotations:&quot; 19688
#(#(33.1 6510 #IsObjectReference)
    #(32.2 6336 #IsSendCall)
    #(15.3 3021 #HasBytecodePC)
    #(12.5 2458 #IsRelativeCall)
    #(6.9 1363 #IsMethodReference))

mzFreeStart - baseAddress  470320 &quot;used space in method zone&quot;
6510/4703.20 1.384163973464875 &quot;percentage of used space in IsObjectReference annotations&quot;
1366 * 4 5464 &quot;size taken by an extra pointer per method to indirect literals&quot;
&lt;/pre&gt;)&lt;/code&gt;</description>
		<content:encoded><![CDATA[<p>Hi Igor,</p>
<p>    you have to balance the cost of GC against the cost of the extra indirection.  Since GCs are relatively rare I think it&#8217;s better to concentrate on runtime performance.  Remember, dedicating a register to point to objects means an extra register to save and restore around every send, not just method activation.</p>
<p>But GC time is important and Cog takes care to minimise the amount of work done scanning machine code.  It does this by maintaining a list of native methods that contain references to objects in newSpace.  See CogMethodZone&gt;youngReferrers.  So on incremental GC only those methods that contain young object references are scanned and, you guessed it, in the normal case the young referrers list is empty.  Only when you compile new code or do a become does the young referrer list get populated.</p>
<p>As far as the metadata goes that&#8217;s of the order of one byte per reference and that&#8217;s only a third of all metadata.  Eliminating them would only save 1.4% of the used space, only a little more than the extra 4 bytes needed in a method to refer to its indirect literals, ignoring the size taken by the extra save-restore code for the indirect references.</p>
<p>In summary keeping object references in machine code may appear costly but it is both more efficient and not a problem for GC in practice since few if any methods refer to new objects and global garbage collections are extremely rare.</p>
<p>FYI here&#8217;s the code I used to gather the above stats (I had to write Cogit&gt;&gt;mapFor:do: and will add it to the VMMaker package soon).  I ran an image under Cog and measured the state after start-up:</p>
<p><code>
<pre>| annotations num nmethods types |
annotations := Bag new.
nmethods := num := 0.
self methodsDo:
	[:m|
	m cmType = CMMethod ifTrue:
		[nmethods := nmethods + 1.
		cogit mapFor: m do: [:ann :pc| num := num + 1.  annotations add: ann. false]]].
		"table copied from Cogit class&gt;&gt;initializeAnnotationConstants"
types := #(	IsSendCall
		IsRelativeCall
		HasBytecodePC
		IsMethodReference
		IsObjectReference
		nil
		nil) reverse.
{ nmethods. num. (annotations sortedCounts collect: [:assoc| { assoc key * 100 / num roundTo: 0.1. assoc key. types at: assoc value }]) }

#("nmethods" 1366
   "nannotations:" 19688
#(#(33.1 6510 #IsObjectReference)
    #(32.2 6336 #IsSendCall)
    #(15.3 3021 #HasBytecodePC)
    #(12.5 2458 #IsRelativeCall)
    #(6.9 1363 #IsMethodReference))

mzFreeStart - baseAddress  470320 "used space in method zone"
6510/4703.20 1.384163973464875 "percentage of used space in IsObjectReference annotations"
1366 * 4 5464 "size taken by an extra pointer per method to indirect literals"
</pre>
<p>)</code></p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Igor Stasenko</title>
		<link>http://www.mirandabanda.org/cogblog/2010/07/20/29/comment-page-1/#comment-4129</link>
		<dc:creator>Igor Stasenko</dc:creator>
		<pubDate>Mon, 11 Oct 2010 01:58:58 +0000</pubDate>
		<guid isPermaLink="false">http://www.mirandabanda.org/cogblog/?p=29#comment-4129</guid>
		<description>Hi, Elliot

i wonder if you can measure, how many cycles you losing by validating a JIT code each time you doing GC. Because for each instruction, like:

mov oop -&gt; register

where oop is an immediate value,
you have to change it, if oop has moved in memory. 
In addition to that, you have to keep a meta-information about location of this immediate in code, in order to change it.

What if you put all oops to special &#039;literal frame&#039; of native code, and reserve a register (lets say ESI) which will point to beginning of them, then
mov oop -&gt; register
could be changed to:
mov [ESI + offset] -&gt; register

Moreover, this special literal frame could be a usual object , like Array instance, so GC will update pointers inside it in same way as it does for any other object(s), which having references.</description>
		<content:encoded><![CDATA[<p>Hi, Elliot</p>
<p>i wonder if you can measure, how many cycles you losing by validating a JIT code each time you doing GC. Because for each instruction, like:</p>
<p>mov oop -&gt; register</p>
<p>where oop is an immediate value,<br />
you have to change it, if oop has moved in memory.<br />
In addition to that, you have to keep a meta-information about location of this immediate in code, in order to change it.</p>
<p>What if you put all oops to special &#8216;literal frame&#8217; of native code, and reserve a register (lets say ESI) which will point to beginning of them, then<br />
mov oop -&gt; register<br />
could be changed to:<br />
mov [ESI + offset] -&gt; register</p>
<p>Moreover, this special literal frame could be a usual object , like Array instance, so GC will update pointers inside it in same way as it does for any other object(s), which having references.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Carl Gundel</title>
		<link>http://www.mirandabanda.org/cogblog/2010/07/20/29/comment-page-1/#comment-4063</link>
		<dc:creator>Carl Gundel</dc:creator>
		<pubDate>Tue, 27 Jul 2010 17:32:30 +0000</pubDate>
		<guid isPermaLink="false">http://www.mirandabanda.org/cogblog/?p=29#comment-4063</guid>
		<description>Thanks for putting this together Eliot.  I&#039;m always fascinated by what you&#039;re working on.  Keep it coming!

Smalltalk Solutions or bust!</description>
		<content:encoded><![CDATA[<p>Thanks for putting this together Eliot.  I&#8217;m always fascinated by what you&#8217;re working on.  Keep it coming!</p>
<p>Smalltalk Solutions or bust!</p>
]]></content:encoded>
	</item>
</channel>
</rss>

