Monday, July 15, 2013

Creating automated load test run report reminders

Load Test Run results can be populated in a database. Scripts to set up this database are available here.
In order to send automated reports on new results, we can register a trigger and an xslt transformation like so:

USE PerfResults;
GO
IF OBJECT_ID ('dbo.LoadTestRunCompleted','TR') IS NOT NULL
    DROP TRIGGER dbo.LoadTestRunCompleted;
GO
CREATE TRIGGER dbo.LoadTestRunCompleted
ON LoadTestRun
AFTER UPDATE
AS
DECLARE @RunID uniqueidentifier;
SELECT TOP 1 @RunID = RunID from LoadTestRun where Outcome = 'Completed' order by EndTime desc;
DECLARE @msg nvarchar(max);
SELECT @msg = dbo.fn_DisplayLoadTestReport(@RunID);
EXEC msdb.dbo.sp_send_dbmail
    @profile_name = 'Performance Reports Administrator',
    @recipients = 'user@xyz.com',
    @body_format='HTML',
    @body = @msg,
    @subject = 'Automated Performance Reports' ;
GO


-- ================================================
-- Template generated from Template Explorer using:
-- Create Scalar Function fn_DisplayLoadReport.SQL
--
-- Use the Specify Values for Template Parameters
-- command (Ctrl-Shift-M) to fill in the parameter
-- values below.
--
-- This block of comments will not be included in
-- the definition of the function.
-- ================================================
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: Ravishankar Rajamani
-- Create date: 15th July, 2013
-- Description: function to render an html for summary display
-- =============================================
CREATE FUNCTION dbo.fn_DisplayLoadTestReport
(
-- Add the parameters for the function here
@RunId uniqueidentifier
)
RETURNS nvarchar(MAX)
AS
BEGIN

    DECLARE @name nvarchar(255)
DECLARE @description nvarchar(255)
DECLARE @starttime datetime
DECLARE @endtime datetime
DECLARE @warmuptime int
DECLARE @runduration int
DECLARE @controller nvarchar(255)
DECLARE @runsettings nvarchar(255)

SELECT @name = LoadTestName, @description = Description, @starttime = StartTime, @endtime = EndTime, @warmuptime = (WarmupTime/60) , @runduration = (RunDuration/60), @controller = ControllerName, @runsettings = RunSettingUsed from LoadTestRun where RunId = @RunId

DECLARE @ret nvarchar(max)
SET @ret = N'<head>
<style type="text/css">
#fullwidth
{
width:100%;
clear:both
}
#leftcol
{
width:49%;
float:left;
clear:all;
position:relative;
}
#rightcol
{
width:49%;
float:right;
position:relative;
}
.pagetitle
{
font-family: Tahoma, Verdana, Arial, Helvetica, sans-serif;
font-size: .8em;
font-weight: bold;
}
.bodytext
{
font-family: Tahoma, Verdana, Arial, Helvetica, sans-serif;
font-size: .7em;
font-weight: normal;
}
.sectiontitle
{
font-family: Tahoma, Verdana, Arial, Helvetica, sans-serif;
font-size: .7em;
font-weight: bold;
text-align: left;
padding-top: 1.5em;
}
.content table
{
width: 100%;
border-top: 1px solid #D4D0C8;
border-right: 1px solid #D4D0C8;
}
.content td
{
font-family: Tahoma, Verdana, Arial, Helvetica, sans-serif;
font-size: .7em;
text-align: left;
border-bottom: 1px solid #D4D0C8;
border-left: 1px solid #D4D0C8;
padding-top: .2em;
padding-left: .3em;
}
.content th
{
font-family: Tahoma, Verdana, Arial, Helvetica, sans-serif;
font-size: .7em;
font-weight: normal;
text-align: left;
border-bottom: 1px solid #D4D0C8;
border-left: 1px solid #D4D0C8;
background-color: #ECE9D8;
padding-top: .2em;
padding-left: .4em;
}
</style>
<script language="JavaScript">
function clickHandler()
{
var targetId, srcElement, targetElement;
srcElement = window.event.srcElement;
if (srcElement.className == "Expandable")
{
targetId = srcElement.id + "div";
targetElement = document.all(targetId);
if (targetElement.style.display == "none")
{
targetElement.style.display = "";
srcElement.innerText = "6";
} else {
targetElement.style.display = "none";
srcElement.innerText = "4";
}}}
document.onclick = clickHandler
</script>
</head>
<body bgcolor="#ffffff">
<div class="pagetitle">Load Test Summary</div>
<div id="leftcol">
<div class="sectiontitle">Test Run Information</div>
<div class="content">
<table cellspacing="0" id="TestRunInformation">
<tr>
<td nowrap width="50%">Load test name</td>
<td nowrap width="50%">' + @name + '</td>
</tr>
<tr>
<td nowrap width="50%">Description</td>
<td nowrap width="50%">' + @description + '&nbsp;</td>
</tr>
<tr>
<td nowrap width="50%">Start time</td>
<td nowrap width="50%">' + CONVERT(nvarchar, @starttime) + '</td>
</tr>
<tr>
<td nowrap width="50%">End time</td>
<td nowrap width="50%">' + CONVERT(nvarchar, @starttime) + '</td>
</tr>
<tr>
<td nowrap width="50%">Warm-up duration</td>
<td nowrap width="50%">' + CONVERT(nvarchar, @warmuptime) + '</td>
</tr>
<tr>
<td nowrap width="50%">Duration</td>
<td nowrap width="50%">' + CONVERT(nvarchar, @runduration) + '</td>
</tr>
<tr>
<td nowrap width="50%">Controller</td>
<td nowrap width="50%">' + @controller + '</td>
</tr>
<tr>
<td nowrap width="50%">Run settings used</td>
<td nowrap width="50%">' + @runsettings + '</td>
</tr>
</table>
</div>
</div>
';

RETURN @ret;


END
GO

Remember to set the content-type of the message as
Content-Type: multipart/mixed
so that it can be displayed  as desired.

Sunday, July 14, 2013

Crash course in file systems

File System Fundamentals :
File attributes include name, type, location, size, protection, and time, date and user identification.
Operations supported are creating a file, writing a file, reading a file, repositioning within a file, deleting a file, and  truncating a file.
Data structures include the following
1) two levels of internal tables : there is a per process table of all the files that each process has opened . This points to the location inside a file where data is to be read or written. This table is arranged by the file handles and has the name, permissions, access dates and pointer to disk block. The other table is a system wide table with open count, file pointer, and disk location of the file.
Sections of the file can be locked for multi-process access and even to map sections of a file on virtual memory systems. The latter is called memory mapping and it enables multiple processes to share the data. Each sharing process' virtual memory map points to the same page of physical memory - the page that holds a copy of the disk block.
File Structure is dependent on the file types.  Internal file structure is operating system dependent. Disk access is done in units of block. Since logical records vary in size, several of them are packed in single physical block as for example at byte size. The logical record size, the physical block size and the packing technique determine how many logical records are in each physical block. There are three major methods of allocation methods : contiguous, linked and indexed. Internal fragmentation is a common occurrence from the wasted bytes in block size.
Access methods are either sequential or direct. The block number is relative to the beginning of the file. The use of relative block number helps the program to determine where the file should be placed  and helps to prevent the users from accessing portions of the file system that may not be part of his file.
File system is broken into partitions. Each disk on the system contains at least one partition. Partitions are like separate devices or virtual disks. Each partition contains information about files within it and is referred to as the directory structure. The directory can be viewed as a symbol table that translates file names into their directory entries. Directories are represented as a tree structure. Each user has a current directory. A tree structure prohibits the sharing of a files or directories. An acyclic graph allows directories to have shared sub-directories and files. Sharing means there's one actual file and changes made by one user are visible to the other. Shared files can be implemented via a symbolic link which is resolved via the path name. Garbage collection may be necessary to avoid cycles.
Protection involves access lists and groups. Consistency is maintained via open and close operation wrapping.
File system is layered in the following manner:
1) application programs, 2) logical file system, 3) file-organization module, 4) basic file system, 4) i/o control  and 5) devices. The last layer is the hardware. The i/o control is the consists of device drivers and interrupt handlers, the basic file system issues generic commands to the appropriate device driver. The file organization module knows about files and their logical blocks. The logical file system uses the directory structure to inform the file organization module. The application program is responsible for creating and deleting files. 
Syllabus :
Algorithms and Data Structures
Programming questions
Design patterns
.Net Technology Stack
ASP.Net
WCF
WPF
SQL Server
Windows operating system
 

Saturday, July 13, 2013

Today mom was 8 - 4. When mom was at work, I got to watch two shows just like mom told Patti and Patti told me. Dad gave me some cursive writing so I did that. I played with some Legos. After mom came back, I rode bikes for some time. First Kailey rode bikes with me then she went inside. In the night, we all played with chutes and ladders.
 
The client logon process
We look at how DC and clients communicate during logon process but in addition we also look at how a RODC gets passwords from a writeable domain controller and caches them locally. Each RODC has a krbtgt account . The krbtgt accounts are the credentials used by DCs to encrypt Kerberos messages. RODC keeps the password for this locally. However, writeable DCs keep all the passwords for krbgt accounts. Let us consider an example where a user logins to his PC and there are two DCs : one read-write and another read only. First the users machine will contact RODC and provide a Kerberos authentication service request packet. When the RODC receives this KRB_AS_REQ packet it will check its local database to see if it already has the user's password. If it does not, it will forward the RWDC and provide the KRB_AS_REQ it received. The RWDC will generate a KRB_AS_REP - a Kerberos authentication service reply and forward it back to RODC. This is then relayed to the user's machine. At this point, the users machine has a Kerberos ticket-granting ticket signed with the domain krbtgt account. Two additional steps are performed next. The RODC will request the RWDC to have the user PC's credential replicated to it. The RWDC will verify if such a policy is permitted and replicate the password.
Now let's look at the process of user authentication. The following are the steps taken when the user attempts to login to his machine.
The user presents his credential to his machine that sends a KRB_AS_REQ to the use. When the RODC receives this request, it will check its local database to see if there's a password cached otherwise it proceeds to the same steps that it took for machine account. However the user logon is still not complete. Before the user can use his workstation, he must obtain a Kerberos service ticket (TGS) for his PC. The user's machine sends the  KRB_TGS_REQ including the users TGT from the previous example. However RODC is unable to decrypt since it is encrypted with the domain krbtgt account. RODC transmits the KRB_TGS_REQ to RWDC who replies with the corresponding response. The RODC receives a valid KRB_TGS_REP. At this point instead of forwarding it to the user's machine, the RODC may decide to send an error indicating the ticket has expired. Since RODC now holds cached credentials for the user it is able to construct a new KRB_AS_REP locally and thus a new TGT for the user, encrypt it with the local krbtgt account and transmit it to the user's machine. The user's machine sends a new TGS request to RODC including the new TGT for the user which the RODC is able to decrypt and construct a TGS response permitting the user to use his PC. After completing these steps, the user is able to logon.

reports and xslt and load test runs.

XSLT transformation enables test results to be displayed. This is how we prepare the data for display or mailing out to subscribers. The resulting xhtml is easy to share. First we get the results from a trx file or the stored procedure execution in a database. This gives us the data in the form of a xml or dataset. Then we take create the xslt with the summary we would like to see. Note that visual studio has default summary view and results that you can open from a load test run using the open and manage results button on the toolbar. This already converts the summary and the results to an html that can be cut and pasted into any application using object linking and embedding technology. The views we create with xslt merely defines a customized view using headings, row and columns to summarize the data.
 The results from a trx file or a stored procedure execution need not be wrapped in a html. It can be converted to xml or excel file with a load test plugin. The load test plugin will simply have an event handler invoked at the end of the relevant test execution and can be written in C#.
Likewise xslt transform and database mail can be written as a SQL Stored procedure. So that newer additions of test runs can trigger database mail. This also scales well to enterprise load. where the runs and the results could be stored in the order of gigabytes. It is easier to design the html and transforms using tools such as report manager and word prior to moving it inside a stored procedure.
Reports can be generated for all kinds of runs. For performance testing, these runs are usually, load test, stress test, and capacity test.  The load test determines the throughput required to support the anticipated peak production load,  the adequacy of a hardware environment and the adequacy of a load balancer. It also detects functionality errors under load, collects data for scalability and capacity planning. However, it is not designed for speed of response. Stress test determines if data can be corrupted by overstressing the system, provides an estimate of how far beyond the target load an application can go before causing failures and errors in addition to slowness, allows establishing application monitoring triggers  to warn of impending failures and helps to plan what kind of failures are most valuable to plan for. Capacity test provides information about how workload can be handled to meet the business requirements, provide actual data that capacity planners can use to validate or enhance their models or predictions, and determines current usage and capacity of the existing system as well as trends to aid in capacity planning. Note that in practice, the most frequently used tests are smoke test which is the initial run of the performance  test to see if your application can perform its operation under normal load. For all these runs, reports generation and subscription is somewhat similar.

Friday, July 12, 2013

Publishing load test results.

In the Visual Studio, when we open a load test, we see an option to "open and manage Results" in the toolbar.  This brings up a dialog box which lists the results associated with the loadtest. Each of these results can be selected and opened. Opening a result brings up the summary view by default. This view can then be cut and paste in the body of an e-mail for reporting. Alternatively it can be exported to a file on the fileshare.

SQL Services Reporting Manager provides great functionality to design custom reports. These reports can draw data using SQL queries. They can also be subscribed with e-mail registration.

Team Foundation Server enables automation of a performance test cycle.  The steps involved in a performance test cycle are as follows:
1. Understand the process and compliance criteria
2. Understand the system and the project plan
3. Identify performance acceptance criteria
4. Plan performance-testing activities
5. Design tests
6. Configure the test environment
7. Implement the test design
8. Execute the work items
9. Report results and archive data
10. Modify the pain and gain approvals for Modifications
11. Return to activity 5
12. Prepare the final report.

The first step involves getting a buy-in on the performance testing prior to the testing and to comply with the standards, if any.  The second step is to determine the use case scenarios and their priority. The third step is to determine the requirements and goals for performance testing as determined with stakeholders, project documentation, usability study and competitive analysis.  The goals should be articulated in a measurable way and recorded somewhere. Plan work items to project plans and schedule them accordingly. This planning is required to line up the activities ahead of time. Designing performance tests involves identifying usage scenarios, user variances and generating test data. Test are designed based on real operations and data, to produce more credible results and enhance the value of performance testing. Tests include component-level testing. Next, configure the environments using load-generation and application monitoring tools, isolated network environments and ensuring compatibility all of which takes time. Test Designs are implemented to simulate a single or virtual user. Next, work items are executed in the order of their priority, their results evaluated and recorded, communicated and test plan adapted. Results are then reported  and archived. Even if there are runs that may not all be usable, they are sometimes archived with appropriate labels.  After each testing phase, it is important to review the performance test plan. Mark the test plan that have been completed and evaluated and submit for approval. Repeat the iterations. Finally, prepare a report to be submitted to the relevant stakeholders for acceptance.