<?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>DelphiTools.info &#187; IDE</title>
	<atom:link href="http://delphitools.info/tag/ide/feed/" rel="self" type="application/rss+xml" />
	<link>http://delphitools.info</link>
	<description>SamplingProfiler, DWS and other Delphi tools</description>
	<lastBuildDate>Thu, 02 Feb 2012 11:33:23 +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>Spotlight on DWS&#8217;s IDebugger</title>
		<link>http://delphitools.info/2010/12/03/spotlight-on-dwss-idebugger/</link>
		<comments>http://delphitools.info/2010/12/03/spotlight-on-dwss-idebugger/#comments</comments>
		<pubDate>Fri, 03 Dec 2010 09:45:32 +0000</pubDate>
		<dc:creator>Eric</dc:creator>
				<category><![CDATA[Tips]]></category>
		<category><![CDATA[Debug]]></category>
		<category><![CDATA[DWS]]></category>
		<category><![CDATA[IDE]]></category>
		<category><![CDATA[Monitor]]></category>
		<category><![CDATA[Profiler]]></category>
		<category><![CDATA[Real-time]]></category>

		<guid isPermaLink="false">http://delphitools.info/?p=735</guid>
		<description><![CDATA[DWScript includes a debugging facility, in the form of the IDebugger interface. The TdwsSimpleDebugger component implements that interface and can be used to simply surface the events. Debugger interface You activate a debugger by merely attaching it to a compiled script (a TdswProgram), you&#8217;ll then get notified of debugging events. Note that the events will [...]]]></description>
			<content:encoded><![CDATA[<p>DWScript includes a debugging facility, in the form of the <em>IDebugger</em> interface. The <em>TdwsSimpleDebugger</em> component implements that interface and can be used to simply surface the events.</p>
<h4>Debugger interface</h4>
<p>You activate a debugger by merely attaching it to a compiled script (a <em>TdswProgram</em>), you&#8217;ll then get notified of debugging events. Note that the events will be invoked from the thread the scripts runs in, so if you&#8217;ve got some UI updates involved f.i., you&#8217;ll have to handle the cross-thread synchronization.</p>
<ul>
<li><em><strong>StartDebug</strong></em>: invoked when the program execution (under debug) starts.</li>
<li><em><strong>DoDebug</strong></em>: invoked for each instruction by executed.</li>
<li><em><strong>StopDebug</strong></em>: invoked when the program execution (under debug) ends.</li>
<li><em><strong>EnterFunc</strong></em>: invoked when the script enters a function.</li>
<li><em><strong>LeaveFunc</strong></em>: invoked when the script enters a function.</li>
</ul>
<p>For aborting script execution, you have the standard <em>TdwsProgram.Stop</em> method.</p>
<h4>Standard debugging tasks</h4>
<p><strong>Breakpoints</strong></p>
<p>Breakpoints can be implemented by merely checking the position of the instruction you get in <em>DoDebug</em> against a reference of breakpoints (you can use a <em>TBits</em> for that). You can then suspend or check conditions (see below).</p>
<p><strong>Suspend, step</strong></p>
<p>To suspend execution, just don&#8217;t return from <em>DoDebug</em> and the script will effectively be suspended.</p>
<p>When stepping, <em>DoDebug</em> will fire on instructions, so if you step from <em>DoDebug </em>to <em>DoDebug</em>, and the user placed two instruction in the same script lines f.i., you&#8217;ll step twice on the same script line. If that isn&#8217;t desirable, you can filter and step only if the source line changed.<br />
Step into and step over can be implemented with the help of the <em>EnterFunc</em>/<em>LeaveFunc </em>notifications.</p>
<p><strong>Evaluating symbols</strong></p>
<p>If you want to evaluate a symbol, you can use <em>Expr.Prog.Table.FindSymbol()</em>, with <em>Expr </em>being the expression you got passed in the <em>DoDebug</em>. That will find the symbol in the current context (the current method if you&#8217;re in a method f.i.). You can also find a symbol from the root by going through the <em>Root </em>property.<br />
Note that <em>FindSymbol </em>will return any symbol, not just variables (<em>TDataSymbol</em>), so you can use this to evaluate functions (with side-effects) if you wish. Data symbols are stored in the stack, so the relevant part for you will be a data symbol&#8217;s stack address (<em>Addr</em>).</p>
<p>The stack is accessible via <em>Expr.Prog.Stack</em>, you&#8217;ll need it to evaluate data symbols. You can of course also use it to modify a variable (just write to the variable&#8217;s stack location).</p>
<p><strong>Call stack</strong></p>
<p>DWS 2.1: If you want the call stack, the most pragmatic approach is IME to do it via <em>EnterFunc/LeaveFunc</em>, the script call stack structure exist, but they aren&#8217;t really geared towards ease of use when debugging. So you can just maintain your own simplified call stack.</p>
<p>DWS 2.2+: StackTrace is available directly in the execution, both as a raw expression CallStack array, or via CallStackToString, as a textual version. You also have access to any script Exception call stack via the StackTrace method.</p>
<p><strong>Note on calls to Delphi-functions</strong></p>
<p>Keep in mind the debugger can only operate on the script code. If the script has invoked a Delphi function, and your execution is stuck there, the debugger won&#8217;t help. You&#8217;ll have to handle suspension in your Delphi code.</p>
<p>That&#8217;s a reason why here it&#8217;s considered a good practice to wrap calls to Delphi code with a safety net, as failure, crashes, incorrect data are the norm when scripting. Raw exposure of Delphi (or external) functions can often be problematic when the user is writing and debugging his scripts.</p>
<h4>Using the debugger for profiling</h4>
<p>You can easily make use of <em>IDebugger </em>for profiling purposes via <em>DoDebug </em>and <em>EnterFunc/LeaveFunc</em>. Instrumenting is implicitly there, so it&#8217;s just a matter of performing the timings.</p>
<p>In our mini-IDE for scripting here (not open-source), a sampling profiler is always active when running code: it periodically suspends the script, notes the current expression, call stack and resumes execution ASAP. For scripting purposes, a sampling frequency of 100 Hz is more than enough IME, and it&#8217;s low-frequency enough to have no measurable impact on the script execution time.<br />
Another cheap profiling tool is to add a function call counter (via EnterFunc), with the two combined, you can pretty much identify all bottlenecks at a glance.</p>
<p>Finally, another tool in your chest can be to implement an execution monitor with the debugger, like the one in <a href="http://delphitools.info/2009/04/15/samplingprofiler-170-still-hot-from-the-compiler/">SamplingProfiler</a>, which can be useful not just at the IDE level, but also at runtime. A typical use is to make a watchdog screen, where you can have an overview of what all the running scripts are doing: useful to diagnose in-production slowdowns, see if they&#8217;re all stuck on the same database access, shared resources, or whatever.</p>
]]></content:encoded>
			<wfw:commentRss>http://delphitools.info/2010/12/03/spotlight-on-dwss-idebugger/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>begin&#8230;end as bottlenecks?</title>
		<link>http://delphitools.info/2009/03/25/beginend-as-bottlenecks/</link>
		<comments>http://delphitools.info/2009/03/25/beginend-as-bottlenecks/#comments</comments>
		<pubDate>Wed, 25 Mar 2009 12:02:49 +0000</pubDate>
		<dc:creator>Eric</dc:creator>
				<category><![CDATA[Tips]]></category>
		<category><![CDATA[Bottleneck]]></category>
		<category><![CDATA[Breakpoint]]></category>
		<category><![CDATA[CPU]]></category>
		<category><![CDATA[Delphi]]></category>
		<category><![CDATA[IDE]]></category>
		<category><![CDATA[Profiler]]></category>
		<category><![CDATA[Stack]]></category>

		<guid isPermaLink="false">http://delphitools.info/?p=68</guid>
		<description><![CDATA[There will come a time when SamplingProfiler may report you that begin or end are your bottlenecks. This may sound a little surprising, but it&#8217;s actually quite a common occurrence, and something that instrumenting profilers are not going to point out, so it might be worth a little explanation. This can be illustrated it with [...]]]></description>
			<content:encoded><![CDATA[<p>There will come a time when SamplingProfiler may report you that <em>begin</em> or <em>end</em> are your bottlenecks. This may sound a little surprising, but it&#8217;s actually quite a common occurrence, and something that instrumenting profilers are not going to point out, so it might be worth a little explanation.</p>
<p>This can be illustrated it with the minimalistic example of an array property getter. Witness the innocuous looking code below:</p>
<pre style="padding-left: 30px">function TMyList.GetItem(index : Integer) : T;
begin
    if (index &lt; 0) or (index &gt;= Count) then
       Error(index);
    Result := FItems[index];
 end;</pre>
<p style="text-align: left">Nothing out of the ordinary there, you can find similar looking code in practically every array-based collection in the RTL and many third party libraries. But someday, that <em>GetItem</em> will be bottleneck, and you could be left looking at code profiling results like those:</p>
<p style="text-align: center;"><img class="size-full wp-image-85 aligncenter" title="begin-end-critical-01" src="http://delphitools.info/wp-content/uploads/2009/03/begin-end-critical-01.png" alt="begin-end-critical-01" width="567" height="213" /></p>
<p style="text-align: left">Yes, those are the are the <em>begin</em> and <em>end</em> lines taking up more than 70% of the CPU time spent inside <em>GetItem</em>&#8230;<br />
 You knew it! Sampling profilers are unreliable&#8230; or are they? Surely the index range checking must be the culprit? or the assignment and the reference counting business? Well, they could be, but in this case they aren&#8217;t.</p>
<p style="text-align: left">To understand why, let&#8217;s have a look in the CPU view. Place a breakpoint on your <em>begin</em>, run up to there and hit <em>Ctr+Alt+C</em>, here is what you could see:</p>
<p style="text-align: center;"><img class="size-full wp-image-86 aligncenter" title="begin-end-critical-02" src="http://delphitools.info/wp-content/uploads/2009/03/begin-end-critical-02.png" alt="begin-end-critical-02" width="429" height="354" /></p>
<p style="text-align: left">That&#8217;s a whole lot of traffic to the stack: 3 registers saved, 3 copies. Those things aren&#8217;t free, they can dwarf what your explicit code does, and in this example, they do. We didn&#8217;t even have any local variables, if we did, they would have taken setup and teardown code, and this code would have been &#8220;hidden&#8221; in <em>begin</em> and <em>end</em> too.</p>
<p style="text-align: left">This illustrates a difference of sampling vs instrumenting profilers: the ability to pinpoint an actual bottleneck, even if it is &#8220;outside&#8221; of your explicit code, so you can find where the actual bottleneck is, and don&#8217;t waste time trying to optimize what isn&#8217;t critical.</p>
<p style="text-align: left">Now what can you do to improve things locally? With generics, an interface type and Delphi 2009 sp2, nothing much, short of going BASM. The bottleneck code is compiler-generated, optimizing the assignment or the range checking would only provide minimal benefits. If you want to go faster, you&#8217;ll have to reduce the number of calls to <em>GetItem</em>, ie. open that <em>&#8220;Show Callers&#8221;</em> pane, have a look there, and solve the issue at the higher-level routines that are involved.</p>
<p style="text-align: left">But there are other situations in which you can influence the auto-generated <em>begin</em>/<em>end</em> code, the solutions then typically revolve around distributing the code across smaller local functions or methods, tweaking your variable usage, separating branches, or if all else fails, going BASM&#8230; but that is food for future posts!</p>
]]></content:encoded>
			<wfw:commentRss>http://delphitools.info/2009/03/25/beginend-as-bottlenecks/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>MapFileStats public release</title>
		<link>http://delphitools.info/2009/03/12/mapfilestats-public-release/</link>
		<comments>http://delphitools.info/2009/03/12/mapfilestats-public-release/#comments</comments>
		<pubDate>Thu, 12 Mar 2009 16:56:29 +0000</pubDate>
		<dc:creator>Eric</dc:creator>
				<category><![CDATA[News]]></category>
		<category><![CDATA[Download]]></category>
		<category><![CDATA[IDE]]></category>
		<category><![CDATA[MAP]]></category>
		<category><![CDATA[MapFileStats]]></category>
		<category><![CDATA[Site]]></category>
		<category><![CDATA[Size]]></category>
		<category><![CDATA[Statistics]]></category>
		<category><![CDATA[Tools]]></category>

		<guid isPermaLink="false">http://delphitools.info/?p=201</guid>
		<description><![CDATA[MapFileStats is a simple free utility to obtain executable binary size statistics derived from a &#8220;.map&#8221; file. Use it to know which units contribute the most to an executable&#8217;s size, which DFMs are the largest, which units you have dependencies on but barely use in your executable, or merely to know exactly what gets into [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://delphitools.info/wp-content/uploads/2009/03/mapfilestats.png"><img class="alignleft size-thumbnail wp-image-191" style="margin: 5px 10px;" title="mapfilestats" src="http://delphitools.info/wp-content/uploads/2009/03/mapfilestats-150x150.png" alt="mapfilestats" width="150" height="150" /></a><a href="http://delphitools.info/other-tools/mapfilestats/">MapFileStats</a> is a simple free utility to obtain executable binary size statistics derived from a &#8220;.map&#8221; file.</p>
<p>Use it to know which units contribute the most to an executable&#8217;s size, which DFMs are the largest, which units you have dependencies on but barely use in your executable, or merely to know exactly what gets into your executable.</p>
<p>You can integrate it into the Delphi IDE via the Tools menu, see the <a href="http://delphitools.info/other-tools/mapfilestats/">MapFileStats</a> page for more details or to the <a href="http://delphitools.info/downloads/mapfilestats-changelog/">download</a> page and see for yourself!</p>
]]></content:encoded>
			<wfw:commentRss>http://delphitools.info/2009/03/12/mapfilestats-public-release/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Using SamplingProfiler from the IDE</title>
		<link>http://delphitools.info/2009/02/27/using-samplingprofiler-from-the-delphi-ide/</link>
		<comments>http://delphitools.info/2009/02/27/using-samplingprofiler-from-the-delphi-ide/#comments</comments>
		<pubDate>Fri, 27 Feb 2009 10:13:30 +0000</pubDate>
		<dc:creator>Eric</dc:creator>
				<category><![CDATA[Tips]]></category>
		<category><![CDATA[Configuration]]></category>
		<category><![CDATA[EXENAME]]></category>
		<category><![CDATA[IDE]]></category>
		<category><![CDATA[Integration]]></category>
		<category><![CDATA[Profiler]]></category>
		<category><![CDATA[Tools]]></category>

		<guid isPermaLink="false">http://delphitools.info/?p=48</guid>
		<description><![CDATA[SamplingProfiler comes as a stand alone-application, but it&#8217;s also ready for integration in the IDE via the Tools menu. Go to the Tools menu configuration and add an entry for SamplingProfiler. Set the parameters field to $EXENAME. Voilà! From now on, when working on a project, you can compile and then hit the SamplingProfiler entry [...]]]></description>
			<content:encoded><![CDATA[<p>SamplingProfiler comes as a stand alone-application, but it&#8217;s also ready for integration in the IDE via the Tools menu. Go to the Tools menu configuration and add an entry for SamplingProfiler. Set the parameters field to $EXENAME. Voilà!</p>
<p>From now on, when working on a project, you can compile and then hit the SamplingProfiler entry in the tools menu, it will open on your current project executable. If you saved a profiling project (.spp file) alongside your executable, it will be loaded automatically too.</p>
]]></content:encoded>
			<wfw:commentRss>http://delphitools.info/2009/02/27/using-samplingprofiler-from-the-delphi-ide/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
<!-- This Quick Cache file was built for (  www.delphitools.info/tag/ide/feed/ ) in 0.84475 seconds, on Feb 4th, 2012 at 1:23 pm UTC. -->
<!-- This Quick Cache file will automatically expire ( and be re-built automatically ) on Feb 5th, 2012 at 1:23 pm UTC -->
