<?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>Altentee » Performance &#38; Test Automation Experts &#187; theory</title>
	<atom:link href="http://altentee.com/blogs/tag/theory/feed/" rel="self" type="application/rss+xml" />
	<link>http://altentee.com</link>
	<description>Performance and Test Automation Experts</description>
	<lastBuildDate>Fri, 04 Nov 2011 03:17:30 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.3</generator>
		<item>
		<title>Untangling Performance Test Terminology</title>
		<link>http://altentee.com/blogs/2009/performance-test-terminology/</link>
		<comments>http://altentee.com/blogs/2009/performance-test-terminology/#comments</comments>
		<pubDate>Mon, 05 Jan 2009 23:02:30 +0000</pubDate>
		<dc:creator>Tim Koopmans</dc:creator>
				<category><![CDATA[Altentee]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[theory]]></category>

		<guid isPermaLink="false">http://altentee.com/?p=757</guid>
		<description><![CDATA[Confused about the subtle differences between a stress test, performance test or a load test? Don&#8217;t get lost in the technobabble! Altentee uses the following terminology to help describe the different types of tests we conduct: Shakeout – single script, single user, low volume scenarios whose main purpose is to confirm a correctly configured test [...]]]></description>
			<content:encoded><![CDATA[<p>Confused about the subtle differences between a stress test, performance test or a load test? Don&#8217;t get lost in the <a href="http://en.wikipedia.org/wiki/Technobabble">technobabble</a>! <strong>Altentee </strong>uses the following terminology to help describe the different types of tests we conduct:</p>
<ol>
<li><strong>Shakeout</strong> – single script, single user, low volume scenarios whose main purpose is to confirm a correctly configured test harness (script, parameters, data, correlation, iterations) and environment.</li>
<li><strong>Baseline</strong> – arbitrary user/volumes (typically low with multiple iterations) used to establish a baseline or reference point for further testing. Can also be used to explore/set SLAs if they have not been defined by the business using minimum sample sizes appropriate to establish a baseline.</li>
<li><strong>Load / Volume</strong> – often expressed in terms of intended production load at 100% or variations of depending on the desired test outcome. Can also incorporate growth scenarios e.g. 200%. Can also be structured to incrementally increase and sustain load up to a target so that utilization metrics can be collected for capacity modelling at each increment (e.g. ramp up from 100 to 200 users at increments of 20 additional users, with sustained execution of 20 minutes at each increment).</li>
<li><strong>Stress / Stress to Break </strong>– loads greater than intended production loads or with the specific purpose to identify component failure or ‘break’ points. Other variants include Surge / Spike testing simulating peak demands over shorter timeframes.</li>
<li><strong>Soak / Endurance</strong> – long running tests to establish performance over longer timeframes and any anomalies over time.</li>
<li><strong>Failover / Availability</strong> – targeted tests under load in failover conditions. Can also be used to test disaster recovery or availability scenarios.</li>
<li><strong>Component Based</strong> – Targeted tests designed to isolate and examine components (functional and/or specific technologies/platforms) under load.</li>
<li><strong>Penetration / Security</strong> – with the increasing inclusion of security related non-functional requirements, targeted load tests which focus on application level and/or hardware level security NFRs.</li>
<li><strong>Tuning </strong>– cyclic / iterative performance testing using any number of variables in a process of test, tune, retest and compare (for improvement).</li>
</ol>
<p>Still confused? Contact <strong><a href="../corporate/contact/" target="_self">Altentee</a></strong> and we&#8217;ll help explain our approach.</p>
]]></content:encoded>
			<wfw:commentRss>http://altentee.com/blogs/2009/performance-test-terminology/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using bees to find bottlenecks</title>
		<link>http://altentee.com/blogs/2007/using-bees-to-find-bottlenecks/</link>
		<comments>http://altentee.com/blogs/2007/using-bees-to-find-bottlenecks/#comments</comments>
		<pubDate>Mon, 17 Dec 2007 21:30:07 +0000</pubDate>
		<dc:creator>Tim Koopmans</dc:creator>
				<category><![CDATA[Altentee]]></category>
		<category><![CDATA[theory]]></category>

		<guid isPermaLink="false">http://90kts.com/blog/2007/using-bees-to-find-bottlenecks/</guid>
		<description><![CDATA[On a basic level, the honeybeeâ€™s dilemma is a tale of two flower patches. If one patch is yielding better nectar than the other, how can the hive use its workforce most efficiently to retrieve the best supply at the moment? The solution, which earned Austrian zoologist Karl von Frisch a Nobel Prize, is a [...]]]></description>
			<content:encoded><![CDATA[<blockquote><p>On a basic level, the honeybeeâ€™s dilemma is a tale of two flower patches. If one patch is yielding better nectar than the other, how can the hive use its workforce most efficiently to retrieve the best supply at the moment? The solution, which earned Austrian zoologist Karl von Frisch a Nobel Prize, is a communication system called the waggle dance.</p></blockquote>
<p>Saw this on Slashdot &#8230; <a href="http://www.msnbc.msn.com/id/22266034">The waggle dance</a></p>
]]></content:encoded>
			<wfw:commentRss>http://altentee.com/blogs/2007/using-bees-to-find-bottlenecks/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Risk management for dummies</title>
		<link>http://altentee.com/blogs/2007/risk-management-for-dummies/</link>
		<comments>http://altentee.com/blogs/2007/risk-management-for-dummies/#comments</comments>
		<pubDate>Wed, 12 Dec 2007 02:39:13 +0000</pubDate>
		<dc:creator>Tim Koopmans</dc:creator>
				<category><![CDATA[Altentee]]></category>
		<category><![CDATA[theory]]></category>

		<guid isPermaLink="false">http://90kts.com/blog/2007/risk-management-for-dummies/</guid>
		<description><![CDATA[This video is a play on Pascal&#8217;s Wager which really gets you thinking on possible outcomes for a given scenario being climate change &#8230; Is it a better bet to accept doomsday predictions for climate changes, or rest on our haunches and let the world pass by? If you haven&#8217;t thought about it yet, get [...]]]></description>
			<content:encoded><![CDATA[<p>This <a href="http://www.youtube.com/watch?v=mF_anaVcCXg&#038;eurl=http://techdebug.com/blog/2007/12/10/climate-change-the-risks-of-no-action/">video</a> is a play on <a href="http://en.wikipedia.org/wiki/Pascal's_Wager">Pascal&#8217;s Wager</a> which really gets you thinking on possible outcomes for a given scenario being <strong>climate change</strong> &#8230; Is it a better bet to accept doomsday predictions for climate changes, or rest on our haunches and let the world pass by? If you haven&#8217;t thought about it yet, get onto it. Good find Ted, pass the word and do your bit &#8230; <img src='http://altentee.com/blogs/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://altentee.com/blogs/2007/risk-management-for-dummies/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Understanding the effect of MQ persistence on disk performance</title>
		<link>http://altentee.com/blogs/2007/understanding-mq-persistence-on-disk-performance/</link>
		<comments>http://altentee.com/blogs/2007/understanding-mq-persistence-on-disk-performance/#comments</comments>
		<pubDate>Fri, 28 Sep 2007 12:28:44 +0000</pubDate>
		<dc:creator>Tim Koopmans</dc:creator>
				<category><![CDATA[Altentee]]></category>
		<category><![CDATA[MQ]]></category>
		<category><![CDATA[theory]]></category>

		<guid isPermaLink="false">http://90kts.com/blog/2007/understanding-mq-persistence-on-disk-performance/</guid>
		<description><![CDATA[Recently I have been trying to determine what the impact of using MQ message persistence is on disk subsystem performance. There is alot of literature from IBM recommending ideal configurations to support MQ persistence, so I won&#8217;t turn this into a post that recommends ideal settings. What I did want to achieve though, was to [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I have been trying to determine what the impact of using MQ message persistence is on disk subsystem performance. There is alot of literature from IBM recommending ideal configurations to support MQ persistence, so I won&#8217;t turn this into a post that recommends ideal settings. What I did want to achieve though, was to get a better understanding of how MQ interacts with the disk subsystem when using message persistence, so that I could plan for capacity and make better recommendations for tuning on a production SAN environment.</p>
<p><span id="more-289"></span><br />
The first behaviour I wanted to describe, was whether the use of MQ persistence creates random or sequential disk activity, on the assumption that random disk access to block locations on the disk would incur a greater time penalty than sequential access.</p>
<p>In order to setup a test environment, I installed MQ version 6 on winXP platform using the default settings. This test was setup using a custom java load harness to put/get messages from a default queue which had persistence enabled with DEFPSIST(YES). File and disk statistics were collected on a Win32 platform using filemon and diskmon respectively.</p>
<p>The following graphs depict the block size written over time (x axis) relative to the sector position (y axis) of the disk drive being monitored. I was trying to achieve a similar effect to the Solaris internals <a href="http://www.solarisinternals.com/si/tools/taz/">TAZ</a> disk trace utility, albeit in a Windows environment. File stats such as number and size of write operations were collected using filemon. Transaction throughput was measured by dividing the total amount of transactions (1,000) by the total processing time. A number of different configurations were tested, but I chose to present a common setup which uses circular logging with single write, and a file page size of 16,384 x 4KB = 64MB per primary log file. The two variations I have presented are writes (MQPUT) only as well as writes (MQPUT) and reads (MQGET) concurrently. The latter being a more familiar situation for me in the workplace.<br />
<a href='http://90kts.com/blog/wp-content/uploads/2007/09/picture-2.png' title='Scenario 1 MQ Mersistence'><img src='http://90kts.com/blog/wp-content/uploads/2007/09/picture-2.png' alt='Scenario 1 MQ Mersistence' /></a><br />
<a href='http://90kts.com/blog/wp-content/uploads/2007/09/picture-3.png' title='Scenario 2 MQ Mersistence'><img src='http://90kts.com/blog/wp-content/uploads/2007/09/picture-3.png' alt='Scenario 2 MQ Mersistence' /></a></p>
<p>It can be determined from the previous test results that MQ accesses the disk in a sequential behaviour. On windows, depending on the concurrent load, it will tend to allocate 16 &#8211; 32 x 512B blocks ranging from 8 &#8211; 16KB in size, although smaller less frequent writes will favour smaller 8 x 512B blocks 4KB in size. As a result, a high number of disk write IOs are observed.</p>
<p>The environment used to test was virtual (parallels), so limited disk cacacity was available, however the change in amplitude for trans/sec is considered relative. As a result, over an 80% reduction in throughput was observed when reading (MQGET) and writing (MQPUT) to the same queue. This will have significant impact on disk subsystem performance in a production environment.</p>
<p>I was unable to perform this test on a Solaris environment due to lack of privileged access, so would be keen to see what the results are there. I believe Solaris uses the same 512B block size, so am expecting similar results. Although analysing an MQ server&#8217;s impact on disk performance using sar, produces the following information:<br />
<code>sar -d 1 10 | egrep 'md72'<br />
           md72             60     0.7    1867   16749     0.0     0.4<br />
           md72             58     0.6    1955   17272     0.0     0.3<br />
           md72             52     0.6    1768   15619     0.0     0.3<br />
           md72             52     0.6    1764   15577     0.0     0.3<br />
           md72             54     0.6    1817   16045     0.0     0.3<br />
           md72             56     0.6    1861   16447     0.0     0.3</code><br />
From that information I can then infer that the total reads + writes/sec (r+w/s) divided by the number of 512B blocks per second (blk/s) would give me an average size of around 8-9KB/sec being written to the filesystem, which correlates my assumptions on block/file sizes. Using sar and other tools like iostat though is thought to be fraught with danger, especially when monitoring a rather complex SAN subsystem; but without access to any other tools, I&#8217;m stuck with the basics. To date I&#8217;ve been relying on perceived throughput (Mr+Mw/s) reported by iostat -xM</p>
<p>Worth noting, is that when MQ performs an MQGET on a persistent queue, it also causes a write IO to update the active log file, so the number of total write IOs effectively doubles.</p>
<p>Out of all this I&#8217;m working on the following assumptions:<br />
1. MQ uses sequential disk access for persistence logging.<br />
2. The OS is typically allocating between 16 &#8211; 32 x 512B blocks ranging between 8 &#8211; 16KB in size.<br />
3. MQGETs are a contributor to overall writes (I&#8217;m assuming o remove the transactions from the log files)<br />
4. Transaction throughput is significantly reduced when an application is reading (MQGET) and writing (MQPUT) to the same queue.</p>
<p>Attached below is a copy of the qm.ini I am working with, which is based on recommended performance tuning considerations from IBM<br />
<code>#*******************************************************************#<br />
#* Module Name: qm.ini                                             *#<br />
#*******************************************************************#<br />
#ExitPath:<br />
   ExitsDefaultPath=/var/mqm/exits/<br />
   ExitsDefaultPath64=/var/mqm/exits64/<br />
#Log:<br />
   LogPrimaryFiles=15<br />
   LogSecondaryFiles=15<br />
   LogFilePages=16384<br />
   LogType=CIRCULAR<br />
   LogBufferPages=512<br />
   LogPath=/var/mqm/log/QUEUEMANGERNAME/<br />
   LogWriteIntegrity=SingleWrite<br />
#Service:<br />
   Name=AuthorizationService<br />
   EntryPoints=13<br />
#ServiceComponent:<br />
   Service=AuthorizationService<br />
   Name=MQSeries.UNIX.auth.service<br />
   Module=/opt/mqm/lib64/amqzfu<br />
   ComponentDataSize=0<br />
#Channels:<br />
   MaxChannels=400<br />
   MaxActiveChannels=400<br />
#TCP:<br />
   KeepAlive=Yes<br />
#TuningParameters:<br />
   DefaultQBufferSize=1048576<br />
   DefaultPQBufferSize=1048576</code></p>
<p>LogFilePages is set to the maximum 16384 x 4KB making each S0000[n].log file about 64MB in size. You must set this parameter as part of your Queue Manager creation i.e. crtmqm -lf 16384 Hopefully that decreases the frequency MQ needs to loop around the ring of log files. LogPrimaryFiles and LogSecondary files are set to 15, and I haven&#8217;t run out of space in my circular log files yet. It is worth reading up on the MQ system administration manual for this, in terms of planning how much space you need. As a planning figure I add the size of MQPUT messages with DEFPSIST + 750B overhead as IBM state, then multiply that amount by my expected throughput. Checkpoint behaviour as part of circular logging activity should hopefully release space as it checkpoints (once every 10,000 transactions I believe), so if you plan properly, you shouldn&#8217;t hit the tail end of your ring too soon <img src='http://altentee.com/blogs/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>The DefaultQBufferSize is 64KB which I increased to 1MB (1048576). Apparently this increases the size of the buffer before writing to the file system, but I haven&#8217;t seen the evidence of that with the tools I&#8217;m using to monitor disk writes. This area is a little cloudy for me.</p>
<p>I have also modified the LogBufferPages to 512 x 4KB giving me a 2MB buffer for similar reasons.</p>
<p>And finally, I&#8217;ve been using a combination of either MQ, a custom perl script, or <a href="ftp://ftp.emc.com/pub/elab/iorate/">EMC iorate</a> to benchmark message persistence on different mounts/filesystems etc which has been useful. Especially when you don&#8217;t have one or the other available, and you need to determine if the space you&#8217;ve been allocated is up to the task of supporting MQ persistence.</p>
<p>In order to truss the process on a Solaris 9 environment, we first had to establish which pid was writing to the log mount. Our sysadmin was able to do this for me with the following:<br />
<code><br />
# fuser -cu /var/mqm/log<br />
/var/mqm/log:    27306c(root)   27197c(root)   19735o(sr123456)<br />
</code><br />
In this case the sr user was the account under which mqm was running, so we were then able to determine the corresponding process name:<br />
<code><br />
# top -s sr123456<br />
2756  sr123456   11  59    0    0K    0K sleep 313:05 12.08% amqzlaa0_nd<br />
20162 sr123456   10  59    0    0K    0K cpu45 406:47  9.49% amqrmppa<br />
19735 sr123456    6  59    0    0K    0K sleep 718:45  3.47% amqzmuc0<br />
19742 sr123456   14  59    0    0K    0K sleep  22:22  0.00% amqzlaa0_nd<br />
19744 sr123456    1  59    0    0K    0K sleep   1:36  0.00% amqpcsea<br />
19752 sr123456    3  59    0    0K    0K sleep   0:16  0.00% runmqlsr_nd<br />
19734 sr123456    2  59    0    0K    0K sleep   0:10  0.00% amqzfuma<br />
19733 sr123456   14  59    0    0K    0K sleep   0:06  0.00% amqzxma0_nd<br />
19751 sr123456    1  59    0    0K    0K sleep   0:00  0.00% runmqtrm<br />
19749 sr123456    1  59    0    0K    0K sleep   0:00  0.00% runmqtrm<br />
19739 sr123456    4  59    0    0K    0K sleep   0:00  0.00% amqzmgr0<br />
19746 sr123456    1  59    0    0K    0K sleep   0:00  0.00% runmqtrm<br />
19747 sr123456    1  59    0    0K    0K sleep   0:00  0.00% runmqtrm<br />
19737 sr123456    2  59    0    0K    0K sleep   0:00  0.00% amqrrmfa<br />
19738 sr123456    2  59    0    0K    0K sleep   0:00  0.00% amqzdmaa<br />
</code><br />
So in this case, the process named amqzmuc0 was the process performing the logging.</p>
<p>For reference, here is a list of processes and what they typically control for MQ:<br />
<code><br />
1.  RUNMQLSR - MQ TCP listener (multi-threaded)<br />
2.  AMQCLMAA - MQ TCP listener (single-threaded)<br />
3.  AMQRMPPA - Channel process pooling job<br />
4.  RUNMQCHI - MQ channel initiator<br />
5.  AMQCRSTA - MQ receiving MCA jobs<br />
6.  RUNMQCHL - MQ sending MCA jobs<br />
7.  AMQCRS6B - LU62 receiver channel<br />
8.  AMQPCSEA - MQ command server<br />
9.  RUNMQTRM - Application trigger monitor<br />
10. RUNMQDLQ - Dead letter queue handler<br />
11. AMQFCXBA - MQ Broker Worker Job<br />
12. RUNMQBRK - MQ Broker Control Job<br />
13. AMQZMUC0 - MQ Utility Manager<br />
14. AMQZMUR0 - MQ Utility Manager<br />
15. AMQZMGR0 - MQ Process Controller<br />
16. AMQRRMFA - MQ cluster repository manager<br />
17. AMQZDMAA - MQ deferred message manager<br />
18. AMQALMPX - MQ Log Manager<br />
19. AMQZFUMA - MQ Object Authority Manager<br />
20. AMQZLAS0 - MQ Local Queue Manager agents<br />
21. AMQZLAA0 - MQ Local Queue Manager agents<br />
22. AMQZXMA0 - MQ Execution Controller<br />
</code></p>
<p>With this info at hand we could then truss the process as per the following:<br />
<code><br />
# truss -D -p 19735<br />
</code></p>
<p>Which produces the following output:<br />
<code><br />
12677624.0012   lseek(18, 2543616, SEEK_SET)                    = 2543616<br />
12677624.0017   write(18, "0FEE0315\001\0\0\0D6A4 f".., 4096)   = 4096<br />
12677624.0018   lwp_cond_broadcast(0xFFFFFFFF7B46CAC0)          = 0<br />
12677624.0018   lwp_mutex_wakeup(0xFFFFFFFF7B46CAA8)            = 0<br />
12677624.0019   lseek(18, 2547712, SEEK_SET)                    = 2547712<br />
12677624.0023   write(18, "0FEE02FD\001\0\0\0D6A4 f".., 4096)   = 4096<br />
12677624.0024   lwp_cond_broadcast(0xFFFFFFFF7B46C3D8)          = 0<br />
12677624.0024   lwp_mutex_wakeup(0xFFFFFFFF7B46C3C0)            = 0<br />
12677624.0024   lwp_cond_broadcast(0xFFFFFFFF7B46CCE0)          = 0<br />
12677624.0025   lwp_mutex_wakeup(0xFFFFFFFF7B46CCC8)            = 0<br />
12677624.0025   lwp_cond_broadcast(0xFFFFFFFF7B46BE88)          = 0<br />
12677624.0026   lwp_mutex_wakeup(0xFFFFFFFF7B46BE70)            = 0<br />
12677624.0026   lseek(18, 2551808, SEEK_SET)                    = 2551808<br />
12677624.0030   write(18, "\tD10206\001\0\0\0D6A4 f".., 4096)   = 4096<br />
</code></p>
<p>What we can see from this test case is that Solaris is writing 4KB sized blocks of data to the file system in support of MQ persistent logging. I would prefer a higher size (say 8 &#8211; 16KB) as the SAN under test would be more efficient and capable of higher throughput, but I guess that is a limitation of the size of messages I am writing (185B per message) and the way Solaris breaks up the IO.</p>
<p>There is a comment from an IBM performance tuning guide for message persistence that states:<block>It is unlikely that poor persistent message throughput will be attributed to the 2MB limit of the queue manager log.  It is possible to fill and empty the log buffer several times each second and reach a CPU limit writing data into the log buffer, before a log disk bandwidth limit is reached.</block></p>
<p>In this, they are referring to the LogBufferPages parameter which I have increased to its maximum configurable size of 512 x 4K pages = 2MB. At this point in time I am still working with the sysadmin in an effort to prove this statement provided by IBM. For the time being we are investigating the seemingly high number of syscalls and context switching which is evident from vmstat:<br />
<code><br />
# vmstat 1<br />
kthr      memory            page            disk          faults      cpu<br />
r b w   swap  free  re  mf pi po fr de sr m0 m1 m3 m4   in   sy   cs us sy id<br />
0 1 0 27901544 13821744 0 6 8  0  0  0  0  0  0  0  0 11369 173717 83335 16 24 60<br />
0 1 0 27901544 13821688 0 0 8  0  0  0  0  0  0  0  0 11201 175563 84711 14 20 66<br />
0 1 0 27901536 13821648 635 4573 0 0 0 0 0 0  0  0  0 11841 179265 84000 14 26 59<br />
0 0 0 27900496 13821472 847 6045 8 8 8 0 0 0  0  0  0 13003 178012 82634 17 25 58<br />
2 0 0 27901552 13821528 0 0 8  0  0  0  0  0  0  0  0 10994 174223 83744 15 20 64<br />
0 1 0 27901544 13821480 0 0 0  0  0  0  0  0  0  0  0 11210 175509 83986 15 18 66<br />
0 1 0 27901544 13821440 0 0 8  0  0  0  0  0  0  0  0 11178 174778 83952 17 19 63<br />
</code></p>
<p>Another aspect I am investigating is the use of threads my the amqzmuc0 process. It would seem that for a given load amqzmuc0 is spawns around XX threads for that process. Looking at the prstat for that process confirms the following:<br />
<code><br />
# prstat -mL -p 29314<br />
PID  USERNAME USR  SYS TRP TFL DFL LCK SLP LAT VCX ICX SCL SIG PROCESS/LWPID<br />
29314 sr53186  0.4 0.7  -   -   -   -  3.2  -  564 157  1K   0 amqzmuc0/3<br />
29314 sr53186  0.0 0.0  -   -   -   -  0.4  -    1   0   1   0 amqzmuc0/4<br />
29314 sr53186  0.0 0.0  -   -   -   -  0.0  -    0   0   0   0 amqzmuc0/6<br />
29314 sr53186  0.0 0.0  -   -   -   -  0.0  -    0   0   0   0 amqzmuc0/5<br />
29314 sr53186  0.0 0.0  -   -   -   -  100  -    0   0   0   0 amqzmuc0/2<br />
29314 sr53186  0.0 0.0  -   -   -   -  0.0  -    0   0   0   0 amqzmuc0/1<br />
</code></p>
]]></content:encoded>
			<wfw:commentRss>http://altentee.com/blogs/2007/understanding-mq-persistence-on-disk-performance/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Problem solving in general and MQ 2195 reason codes</title>
		<link>http://altentee.com/blogs/2007/problem-solving-in-general-and-mq-2195-reason-codes/</link>
		<comments>http://altentee.com/blogs/2007/problem-solving-in-general-and-mq-2195-reason-codes/#comments</comments>
		<pubDate>Fri, 10 Aug 2007 00:05:37 +0000</pubDate>
		<dc:creator>Tim Koopmans</dc:creator>
				<category><![CDATA[Altentee]]></category>
		<category><![CDATA[MQ]]></category>
		<category><![CDATA[theory]]></category>

		<guid isPermaLink="false">http://90kts.com/blog/2007/problem-solving-in-general-and-mq-2195-reason-codes/</guid>
		<description><![CDATA[So I spent the best part of a day assisting our sys admin and developer resolve MQ errors that a COBOL client was throwing when opening more than one concurrent connection to a clustered queue manager. Because the architecture had recently changed to a cluster, and my load harness was no longer getting the desired [...]]]></description>
			<content:encoded><![CDATA[<p>So I spent the best part of a day assisting our sys admin and developer resolve MQ errors that a COBOL client was throwing when opening more than one concurrent connection to a clustered queue manager.</p>
<p>Because the architecture had recently changed to a cluster, and my load harness was no longer getting the desired response times, we all went down the track of investigating issues with clustering as this was the new kid on the block. Whilst the developer and sys admin revealed many other interesting tid bits of information regarding correct configuration and the like, we still could not collectively resolve the problem: the COBOL code was throwing a 2195 reason code on multiple MQCONN calls to the queue manager.</p>
<p><span id="more-286"></span><br />
Some key lessons I learned here though, was to always simplify the problem by going back to a known configuration. We ended up doing that at the end of the day (using a standard queue manager configuration) and found that the 2195 errors persisted. So this was a good indicator that we had some sort of environment/configuration error.</p>
<p>The second key lesson was to always trust the API documentation. In this case a 2195 error has the following info:</p>
<blockquote><p>
2195 MQRC_UNEXPECTED_ERROR<br />
The call was rejected because an unexpected error occurred.<br />
Corrective action: Check the applicationâ€™s parameter list to ensure, for example, that the correct number of parameters was passed, and that data pointers and storage keys are valid.</p>
<p>If the problem cannot be resolved, contact your system programmer.<br />
v On OS/390, check whether any information has been displayed on the console. If this error occurs on an MQCONN or MQCONNX call, check that the subsystem named is an active MQSeries subsystem. In particular, check that it is not a DB2 subsystem. If the problem cannot be resolved, rerun the application with a CSQSNAP DD card (if you have not already got a dump) and send the resulting dump to IBM.<br />
v On OS/2 and AS/400, consult the FFST record to obtain more detail about the problem.<br />
v On Compaq (DIGITAL) OpenVMS, Tandem NonStop Kernel, and UNIX systems, consult the FDC file to obtain more detail about the problem.
</p></blockquote>
<p>To be honest, I got put off by the &#8220;unexpected error&#8221; bit, and had the same reaction I do when I see server 500 errors for http. It&#8217;s hard not to put your head in the sand in this situation. But on closer inspection, and now with the benefit of hindsight, the corrective action does mention how to resolve this, as well as a key tip to look at the FDC file to obtain more detail about the problem. Never having seen a FDC file before I simply ignored it, but the collective nouse of the sys admin and developer later figured it all out, with the recommended solutions posted <a href="http://techdebug.com/blog/2007/08/10/tuning-solaris-9-for-mq-v60/">here</a> and <a href="http://techdebug.com/blog/2007/08/10/solaris-9-kernel-parameters/">here</a>. Well done Ted <img src='http://altentee.com/blogs/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://altentee.com/blogs/2007/problem-solving-in-general-and-mq-2195-reason-codes/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>The gambler&#039;s fallacy killed by pure maths</title>
		<link>http://altentee.com/blogs/2007/the-gamblers-fallacy-killed-by-pure-maths/</link>
		<comments>http://altentee.com/blogs/2007/the-gamblers-fallacy-killed-by-pure-maths/#comments</comments>
		<pubDate>Mon, 11 Jun 2007 23:15:37 +0000</pubDate>
		<dc:creator>Tim Koopmans</dc:creator>
				<category><![CDATA[Altentee]]></category>
		<category><![CDATA[theory]]></category>

		<guid isPermaLink="false">http://90kts.com/blog/2007/the-gamblers-fallacy-killed-by-pure-maths/</guid>
		<description><![CDATA[Statistics (and the ability to gather/present) are an essential tool for performance testing. At the time of learning basic stats in high school and university I was plagued with the problem of not seeing the real life application of these tools. Sure, exercises and scenarios conducted simulated real life, but in reality, the meaning of [...]]]></description>
			<content:encoded><![CDATA[<p>Statistics (and the ability to gather/present) are an essential tool for performance testing. At the time of learning basic stats in high school and university I was plagued with the problem of not seeing the real life application of these tools. Sure, exercises and scenarios conducted simulated real life, but in reality, the meaning of stats escaped me. Fast forward 10 years and I am now rediscovering the joy of such measurements. In fact, those university text books get more of a workout now than previously during study.</p>
<p>I have already posted a few times about presenting stats using common tools like Microsoft Excel. I am still learning the stats package &#8216;r&#8217; as I see that to be more powerful and extensible. In the interim I use a combination of Excel, MySQL and PHP to prepare and analyse stats. As this contract winds down and I prepare for the next, I&#8217;ve come across a useful application of stats to keep me entertained.</p>
<p>A friend of mine recently stumbled across a well known roulette strategy called the <a href="http://en.wikipedia.org/wiki/Martingale_(betting_system)">martingale</a> strategy.<br />
<blockquote>Originally, martingale referred to a class of betting strategies popular in 18th century France. The simplest of these strategies was designed for a game in which the gambler wins his stake if a coin comes up heads and loses it if the coin comes up tails. The strategy had the gambler double his bet after every loss , so that the first win would recover all previous losses plus win a profit equal to the original stake. Since a gambler with infinite wealth will with probability of 1 eventually flip heads, the martingale betting strategy was seen as a sure thing by those who practiced it&#8230;</p></blockquote>
<p><span id="more-280"></span><br />
So how can you lose? My friend and I put this to test after a few bourbons and a couple of beers. In the two times we&#8217;ve met since, we have both walked away winners, smug in our victory and laughing all the way back to the ATM&#8230; Obviously, casinos would have a counter to this though?</p>
<p><b>Stacked Odds</b><br />
The first point that will work against us in the long run is basic probability. On an American roulette table (which predominates here in Australia) there are 18 red, 18 black and 2 green positions. A total of 38 possible outcomes. The addition of the 2 green positions are the first part of the casino&#8217;s counter attack. It tips the probability in their favour, since if you land on a green and you are betting on red or black (which is the strategy), you will lose regardless.</p>
<p>So if we were betting on either red or black, there is a probability of 18/38 that we will win, and 37/38 that we will lose:<br />
<code>18/38 = 47.36% chance to win<br />
20/38 = 52.64% chance to lose</code></p>
<p>So from the outset, probability wise, we are more likely to lose than win, simply by the casino adding two green numbers (0 and 00). However, it is still likely to be the most fairest bet in the casino if you are hankering to gamble.</p>
<p>Coincidentally, if you add the winning numbers 1 to 36, you come up with the number 666. Hmmm.</p>
<p><b>Expected Value</b><br />
This is also known as the <a href="http://en.wikipedia.org/wiki/Roulette">House&#8217;s Edge</a>, but in probability theory, the expected value of a random variable is the sum of the probability of each possible outcome multiplied by the outcome value (or in this case your winnings). So for the American roulette table with probability of losing being 20/38 and probability of winning being 18/38, the expected outcome value for a $1 bet is:<br />
<code>(-$1 x 20/38) + ($1 x 18/38) = -$0.0526316</code></p>
<p>Therefore on average for every dollar bet the expected value of one dollar is:<br />
<code>$1 - $0.0526316 = $0.95</code></p>
<p>So your net gain is less than what you started with. Statistically, this is not a fair bet.</p>
<p><b>Gambler&#8217;s Fallacy</b><br />
Perhaps the next biggest problem with this strategy, is the simple human tendency to try and recognize patterns. You will hear my friend say that it is extremely unlikely for the play to fall red, black, red, black, red, black and so on. If this happens, and you follow the strategy you will lose quickly, because you will be forced to double each losing bet ($5, $10, $20, $40, $80, $160, $320) &#8230;</p>
<p>Despite human intuition telling us that the next play can&#8217;t possibly be another black, or it can&#8217;t possibly be another red, or it can&#8217;t possibly alternate between red and black <em>I mean, come on, how likely is that?</em> The reality is, each roll is statistically <a href="http://en.wikipedia.org/wiki/Statistical_independence">independent</a>. That is, between two spins of the wheel, the occurence of one black or one red is neither more nor less proabable than the other occurring. The human trait of identifying lucky streaks, or patterns in play is precisely what casinos prey upon. In fact, casinos no doubt go through painstaking measures to ensure that the roulette tables are balanced, because if not, then they risk people using more detailed statistical analysis to recognise patterns for a particular table. This is probably why roulette calculators are banned. In any case, don&#8217;t be fooled by the hype. Or at least that&#8217;s what I try and convince myself. <img src='http://altentee.com/blogs/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p><b>The Maximum Bet</b><br />
It is possible to lose more individual games than win but still win money overall. Assuming you  make bets that are a small percentage of your bankroll (<1%) so for a $500 bankroll you should stick to bets of $5. The bigger your bankroll the better. This is what makes the martingale strategy seemingly unbeatable as my friend and I chuckled to ourselves with suspicious glances from the croupier ... However, perhaps the most effective counter attack at the casino's disposal is the application of a house rule that specifies what the maximum bet for a table can be.  For instance, on a $5 minimum bet table, you will often see $500 as the maximum bet. Why? because this limits the amount of money that a player can progressively double after losses. For example, if you start with $5 and lose, then following the strategy until you win again you will place $10, $20, $40, $80, $160 and $320 before you hit the maximum bet limit. That means you only have to lose around 6 times in a row before your strategy falls apart. Coincidentally, the odds of losing 6 straight games is quite high where 56.2% ^ 6 is approx 1/47. In the short term this doesn't seem too bad, but over a long term, coupled with the other points highlighted in this post I can guarantee one thing.</p>
<p><strong><em>Statistically you will lose.</em></strong></p>
<p>However, in the interests of having a great night out, and not throwing your money away on the pokies, or pointlessly trying to count cards on the black jack table, the martingale strategy keeps the night entertaining. Now try to explain all of this next time you&#8217;re drunk.</p>
<p>If you&#8217;re still not convinced, I wrote a perl script to help simulate the martingale strategy. In the following program, the defaults can be controlled via command line arguments, or you can follow my strategy which I plan to unleash on Queenstown casinos during my upcoming holidays to New Zealand. I&#8217;m not too sure which has the greater probability, me winning, or decent snow falls in July&#8230;</p>
<p><code><br />
#!/usr/bin/perl -w<br />
# --------------------------------------------------------------------------<br />
# Martingale Roulette Betting System Simulator<br />
#<br />
# Usage       : Roulette.pl [options]<br />
# Options     :<br />
#	-bet        minimum bet amount<br />
#	-atm        amount of money to withdraw from ATM each night<br />
#	-maxBets    maximum number of bets to place each night<br />
#   -maxBet     maximum bet amount permitted by house rules<br />
#   -nightsOut  number of nights to visit the casino<br />
#   -verbose    optional [true] flag for verbose results<br />
#	-quit       quite when you're [n] times ahead<br />
#	-fair		optional [false] flag to remove casino edge<br />
#<br />
# $Revision: 1.3 $<br />
# $Date: 2007/06/07 08:43:11 $<br />
#<br />
# Author: tim.koopmans@90kts.com  [http://90kts.com]<br />
# --------------------------------------------------------------------------<br />
use Getopt::Long;</p>
<p>my %opts=();<br />
GetOptions(<br />
	"bet=f"	      => \$opts{bet},<br />
	"atm=i"	      => \$opts{atm},<br />
	"maxBets=i"	  => \$opts{maxBets},<br />
	"maxBet=i"	  => \$opts{maxBet},<br />
	"nightsOut=i" => \$opts{nightsOut},<br />
	"quit=f"	  => \$opts{quit},<br />
	"fair=s"	  => \$opts{fair},<br />
	"verbose=s"	  => \$opts{verbose}</p>
<p>);</p>
<p>my $bet          = $opts{bet}       || 5;<br />
my $atm          = $opts{atm}       || 100;<br />
my $maxBets      = $opts{maxBets}   || 50;<br />
my $maxBet       = $opts{maxBet}    || 500;<br />
my $nightsOut    = $opts{nightsOut} || 15;<br />
my $quit         = $opts{quit}      || 1;<br />
my $fair         = $opts{fair};<br />
my $verbose      = $opts{verbose};</p>
<p>my $wager        = $bet;<br />
my $kitty        = $atm;<br />
my $betColour    = "BLACK"; # Starting colour to bet</p>
<p>for ($n=1; $n<=$nightsOut;$n++)<br />
{<br />
    for ($i=1;$i<=$maxBets;$i++)<br />
    {<br />
		# Subtract your wager from your kitty ...<br />
		$kitty-=$wager;</p>
<p>		# Spin that wheel ...<br />
		my @reds   = (1,3,5,7,9, 12,14,16,18,19,21,23,25,27,30,32,34,36);<br />
        my @blacks = (2,4,6,8,10,11,13,15,17,20,22,24,26,28,29,31,33,35);<br />
        my @greens = (37,38); # American roulette table being used ...</p>
<p>        if($fair) {<br />
			$spin = int(rand(36));<br />
		} else {<br />
			$spin = int(rand(38));<br />
		}</p>
<p>        if ($spin%2==0) { $result = "EVEN"; }<br />
        else { $result = "ODD"; }</p>
<p>        foreach (@reds) {<br />
            if ($_ == $spin) { $colour = "RED";   $ws="  "; }<br />
        }<br />
        foreach (@blacks) {<br />
            if ($_ == $spin) { $colour = "BLACK"; $ws=""; }<br />
        }<br />
        foreach (@greens) {<br />
            if ($_ == $spin) {<br />
                $colour = "GREEN";<br />
                $result = "--";<br />
            }<br />
            if   ($spin==37) { $spin = "0";  }<br />
            elsif($spin==38) { $spin = "0"; }<br />
        }</p>
<p>        if ($betColour =~ /$colour/) {<br />
			# Winner!<br />
			# Add the winnings to the kitty ...<br />
			$kitty += (2 * $wager);<br />
            if($verbose) { print "$ws$spin \t\tBet $wager    \tWon  $wager  \t Kitty $kitty"; }<br />
            $wager = $bet;<br />
        }<br />
        else {<br />
			# Loser!<br />
            if ( ($kitty - (2 * $wager) ) < 0) {<br />
				# You can't afford to play on, double is more than you can afford tonight ...<br />
                if($verbose) {<br />
					print "$ws$spin \t\tBet $wager   \tLost ".$wager."   \t Bust  $kitty";<br />
				}<br />
                #$i=$maxBets;<br />
				if($kitty>0){<br />
					$wager=$kitty;<br />
				} else {<br />
					$i = $maxBets;<br />
				}<br />
            } elsif ( (2 * $wager) > $maxBet) {<br />
				if($fair) {<br />
					$wager = 2 * $wager;<br />
				} else {<br />
					# You have reached maximum bet permitted by house rules ...<br />
					if($verbose) { print "$ws$spin \t\tBet $wager    \tMax  ".$wager."  \t Kitty $kitty"; }<br />
					$wager = $maxBet;<br />
				}<br />
			} else {<br />
				# Double the wager and bet on the losing colour ...<br />
				if($verbose) { print "$ws$spin \t\tBet $wager    \tLost ".$wager."  \t Kitty $kitty"; }<br />
				$wager = 2 * $wager;<br />
            }<br />
        }</p>
<p>		$betColour = $colour;</p>
<p>        if($verbose) { print "\t$colour, $result\n";}</p>
<p>		if($quit>1){<br />
			if($kitty > ( $quit * $atm) ){<br />
				# Quit while you're ahead tonight a [n] times atm ...<br />
				if($verbose) { print "$ws$spin \t\tBet $wager    \tQuit ".$wager."  \t Kitty $kitty\n"; }<br />
				$i=$maxBets;<br />
			}<br />
		}</p>
<p>    }<br />
    $wager = $bet;</p>
<p>	# Winnings tonight ...<br />
	if($verbose) {<br />
		print "------------------------------------------------------\n";<br />
		print "\$$kitty.00 \tTotal winnings on night $n\n";<br />
		print "\$".($kitty-$atm).".00 \tless ATM debt\n\n";<br />
	} else {<br />
		print "\$$kitty.00\n";<br />
	}</p>
<p>	$totalWinnings+=$kitty;</p>
<p>	# Withdraw from your ATM for the next night like a sucker that you are ...<br />
	$kitty=$atm;</p>
<p>	# Keep track of your winnings though ...<br />
	$totalWinnings-=$atm;</p>
<p>}</p>
<p># Summary statistics<br />
print "\n------------------------------------------------------\n";<br />
print "$bet         \tMinimum bet\n";<br />
print "$maxBet      \tMaximum bet permitted by house rules\n";<br />
print "$maxBets      \tMaximum number of bets placed in one night\n";<br />
print "".($n-1)."        \tTotal nights out at casino\n";<br />
print "\$$totalWinnings.00   \tTotal winnings less ATM debt\n";<br />
print "------------------------------------------------------\n";<br />
</code></p>
]]></content:encoded>
			<wfw:commentRss>http://altentee.com/blogs/2007/the-gamblers-fallacy-killed-by-pure-maths/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>RWI 00239 The server has reached the maximum number of simultaneous connections</title>
		<link>http://altentee.com/blogs/2007/rwi-00239-the-server-has-reached-the-maximum-number-of-simultaneous-connections/</link>
		<comments>http://altentee.com/blogs/2007/rwi-00239-the-server-has-reached-the-maximum-number-of-simultaneous-connections/#comments</comments>
		<pubDate>Fri, 25 May 2007 02:30:14 +0000</pubDate>
		<dc:creator>Tim Koopmans</dc:creator>
				<category><![CDATA[Altentee]]></category>
		<category><![CDATA[MQ]]></category>
		<category><![CDATA[theory]]></category>

		<guid isPermaLink="false">http://90kts.com/blog/2007/rwi-00239-the-server-has-reached-the-maximum-number-of-simultaneous-connections/</guid>
		<description><![CDATA[Once again on the topic of performance testing Business Objects, when executing a benchmark for a web intelligence report with goal being to see how many concurrent users it could support, the following error mesage was being generated in the vuser log: Connection failed. The server has reached the maximum number of simultaneous connections. (Error: [...]]]></description>
			<content:encoded><![CDATA[<p>Once again on the topic of performance testing Business Objects, when executing a benchmark for a web intelligence report with goal being to see how many concurrent users it could support, the following error mesage was being generated in the vuser log:<br />
<a href='http://90kts.com/blog/wp-content/uploads/2007/05/rwi-00239.png' title='RWI 00239 The server has reached the maximum number of simultaneous connections'><img src='http://90kts.com/blog/wp-content/uploads/2007/05/rwi-00239.png' alt='RWI 00239 The server has reached the maximum number of simultaneous connections' /></a><code><br />
Connection failed. The server has reached the maximum number of simultaneous connections. (Error: RWI 00239) (Error: INF )</code></p>
<p>What to do?</p>
<p><span id="more-279"></span></p>
<p>In order to find this error I generated a snapshot on error in the run time settings for LoadRunner, then browsed the html source for the vuser typically available at <code>C:\Documents and Settings\UserName\Local Settings\Temp\res</code></p>
<p>There were a number of incorrect conclusions that I jumped to here:</p>
<p>1. That google would save the day and spoon feed me the answer! The only information I could find was <a href="http://www.forumtopics.com/busobj/viewtopic.php?p=330313">here</a> but alas they did not have the answer. Hence my decision to post here, as no doubt some other performance tester out there is going to hit this problem. I would post on the BOB forum, but hey, you need a login to comment. Meh.</p>
<p>2. My <a href="http://en.wikipedia.org/wiki/Kludge">kludge&#8217;s</a> approach would be good enough. I thought if I want 50 concurrent users, all I need to do is make sure that I have at least 100 simultaneous connections available. Right?<br />
<a href='http://90kts.com/blog/wp-content/uploads/2007/05/boconcurrentusersettings.png' title='boconcurrentusersettings.png'><img src='http://90kts.com/blog/wp-content/uploads/2007/05/boconcurrentusersettings.thumbnail.png' alt='boconcurrentusersettings.png' /></a><br />
Wrong &#8230;</p>
<p>As it turns out, a user opens more than one session on the web intelligence server. It seems they need one to login, one as they start to navigate around the folder structure and another to open reports. I&#8217;m not too sure if this behaviour is caused by the browser (IE or Mozilla) but it seems to be consistent when using a browser. You can see this information by monitoring a user session in the central management console.<br />
<a href='http://90kts.com/blog/wp-content/uploads/2007/05/3sessionsperuser.png' title='3 Sessions Per User'><img src='http://90kts.com/blog/wp-content/uploads/2007/05/3sessionsperuser.thumbnail.png' alt='3 Sessions Per User' /></a></p>
<p>So that seems to fix the RWI 00239 errors. Now that I&#8217;m past that, on to investigating why the web intelligence servers fails under concurrent user load. RWI 00236 is my starting point, let&#8217;s revisit google to see what others have found &#8230;</p>
<p><a href='http://90kts.com/blog/wp-content/uploads/2007/05/rwi-00236.png' title='RWI 00236 The Web Intelligence server could not be reached.'><img src='http://90kts.com/blog/wp-content/uploads/2007/05/rwi-00236.png' alt='RWI 00236 The Web Intelligence server could not be reached.' /></a><br />
<code>The Web Intelligence server could not be reached. Contact your Business Objects administrator. (Error: RWI 00236)(Error: INF)</code></p>
]]></content:encoded>
			<wfw:commentRss>http://altentee.com/blogs/2007/rwi-00239-the-server-has-reached-the-maximum-number-of-simultaneous-connections/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Curve dampening for a custom load harness</title>
		<link>http://altentee.com/blogs/2007/curve-dampening-for-load-balancer/</link>
		<comments>http://altentee.com/blogs/2007/curve-dampening-for-load-balancer/#comments</comments>
		<pubDate>Mon, 30 Apr 2007 02:54:29 +0000</pubDate>
		<dc:creator>Tim Koopmans</dc:creator>
				<category><![CDATA[Altentee]]></category>
		<category><![CDATA[theory]]></category>

		<guid isPermaLink="false">http://90kts.com/blog/?p=20</guid>
		<description><![CDATA[Recently I wrote a test harness that had a "discovery" mode. That is, given a target service level agreement (SLA), what transaction pacing or throughput did the load harness have to apply in order to achieve the SLA response times. Now my maths is a tad scratchy, but I knew that I could somehow figure out the equation to determine how much the load balancer should adjust throughput in order to achieve the desired response time. In my mind I pictured a horizontal line that is the target, and a sinusoidal line that is the actual response time that varies according to load. If I could just figure out how to dampen that curve, I would have the magic formula!]]></description>
			<content:encoded><![CDATA[<p>Recently I wrote a test harness that had a &#8216;discovery&#8217; mode. That is, given a target service level agreement (SLA), what transaction pacing or throughput did the load harness have to apply in order to achieve the SLA response times. Now my maths is a tad scratchy, but I knew that I could somehow figure out the equation to determine how much the load balancer should adjust throughput in order to achieve the desired response time. In my mind I pictured a horizontal line that is the target, and a sinusoidal line that is the actual response time that varies according to load. If I could just figure out how to dampen that curve, I would have the magic formula!</p>
<p><span id="more-272"></span><br />
So let&#8217;s start with a diagram of what I&#8217;m talking about. This is what I am trying to achieve &#8230;<br />
<img src="http://90kts.com/blog/wp-content/uploads/2007/04/dampen.png" border="0" height="175" width="183" alt="dampen.png" /></p>
<p>There&#8217;s many <a href="http://www.sparknotes.com/physics/dynamics/newtonsthreelaws/section2.rhtml">reference&#8217;s</a> to this but I couldn&#8217;t for the life of me figure out how to<br />
a. Demonstrate this in something like excel, and<br />
b. Create the same harmonic damped effect in a simple java load harness.</p>
<p>Well I couldn&#8217;t at first, but here is something that kind of works.</p>
<p>In the following graph, the green line is my SLA of 2,000 milliseconds. The dark blue line is response time that can vary according to load. The light blue line is the varying pacing (or throughput) that is required in order to achieve the SLA. In an excel spreadsheet, the meaning (and calculation) of these values went something like this:<br />
<img src="http://90kts.com/blog/wp-content/uploads/2007/04/loadbalance.png" border="0" height="216" width="379" alt="loadbalance.png" /></p>
<p><img src="http://90kts.com/blog/wp-content/uploads/2007/04/symbols.png" border="0" height="155" width="511" alt="symbols.png" /></p>
<p>So putting it all together in excel works ok. You can download the <a href='http://90kts.com/blog/wp-content/uploads/2007/05/curvedamper.xls' title='curve dampening spreadsheet'>curve dampening spreadsheet here.</a></p>
<p><code>// LOAD BALANCER CALCULATIONS FOR DISCOVER MODE<br />
// Pacing mods based on response time<br />
double diff    = (double)sla - (double)responseTime;<br />
double fract   = diff/1000;<br />
double inv	   = 1.00 - fract;<br />
double fractSq = fract * fract;<br />
double factor  = (sla/100) * (sla/100);</p>
<p>if(diff<0){<br />
	adjustedPacing = (int)( (fractSq * inv * 100) + factor);<br />
} else {<br />
	adjustedPacing = (int)( (1-(fractSq * 100))+ factor);<br />
}</code></p>
]]></content:encoded>
			<wfw:commentRss>http://altentee.com/blogs/2007/curve-dampening-for-load-balancer/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

