Skip to content

Get SQL Server working with ASP.NET tests on Windows #336

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jul 16, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,21 @@ Now you can run tests:
python run-tests.py -s server-ip -c client-ip -i "C:\Users\Administrator\Desktop\client.key" --max-threads 2 --duration 30 --sleep 5 --name win --test aspnet --type all


### SQL Server on Windows Instructions

Server installation scripts for Windows Server 2012 with SQL Server 2012 Standard on Amazon EC2.

Instructions:

* Create an instance from the [Windows Server 2012 RTM English 64-bit SQL 2012 Standard](https://aws.amazon.com/amis/amazon-ebs-backed-windows-server-2012-rtm-english-64-bit-sql-2012-standard) image on Amazon EC2
* Connect to it via Remote Desktop
* Run a `Command Prompt` as Administrator
* Enter `powershell -ExecutionPolicy Bypass -Command "iex (New-Object Net.WebClient).DownloadString('https://raw.github.com/TechEmpower/FrameworkBenchmarks/master/setup-sqlserver-bootstrap.ps1')"`
* This will configure SQL Server, the Windows Firewall, and populate the database.

Now, when running `python run-tests.py`, just add `-d <ip of SQL Server instance>`. This works for the (Windows Server-based) `aspnet-sqlserver-raw` and `aspnet-sqlserver-entityframework` tests.


## Result Files

After a test run, the directory ~/FrameworkBenchmarks/results/machine-name/timestamp will contains all the result files. In this folder are four files: three CSV files, one for each of the test types (json, db, query), and a single results.json file that contains all the results as well as some additional information. The results.json file is what we use to drive our blog post, and may or may not be useful to you. There are three subdirectories: one for each of the test types (json, db, query), each of these directories contain the raw weighttp results for each framework.
Expand Down
1 change: 1 addition & 0 deletions aspnet/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
* Npgsql 2.0.12 ([custom build](https://github.com/pdonald/Npgsql2))
* Entity Framework 6.0.0-alpha3
* Mongo C# Driver 1.8.1
* SqlClient Data Provider for SQL Server

**Developer Tools**

Expand Down
24 changes: 22 additions & 2 deletions aspnet/benchmark_config
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,16 @@
"port": 8080,
"sort": 93
},
"sqlserver-raw": {
"setup_file": "setup_iis",
"os": "nt",
"db_url": "/ado/sqlserver",
"query_url": "/ado/sqlserver?queries=",
"fortune_url": "/ado/sqlserver/fortunes",
"update_url": "/ado/sqlserver/update?queries=",
"port": 8080,
"sort": 94
},
"mysql-entityframework": {
"setup_file": "setup_iis",
"os": "nt",
Expand All @@ -46,7 +56,7 @@
"fortune_url": "/entityframework/mysql/fortunes",
"update_url": "/entityframework/mysql/update?queries=",
"port": 8080,
"sort": 94
"sort": 95
},
"postgresql-entityframework": {
"setup_file": "setup_iis",
Expand All @@ -56,7 +66,17 @@
"fortune_url": "/entityframework/postgresql/fortunes",
"update_url": "/entityframework/postgresql/update?queries=",
"port": 8080,
"sort": 95
"sort": 96
},
"sqlserver-entityframework": {
"setup_file": "setup_iis",
"os": "nt",
"db_url": "/entityframework/sqlserver",
"query_url": "/entityframework/sqlserver?queries=",
"fortune_url": "/entityframework/sqlserver/fortunes",
"update_url": "/entityframework/sqlserver/update?queries=",
"port": 8080,
"sort": 97
},
"mono": {
"setup_file": "setup_nginx",
Expand Down
2 changes: 1 addition & 1 deletion aspnet/src/Application.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ private void Routes()
name: "WithProviders",
url: "{controller}/{providerName}/{action}",
defaults: new { action = "Index" },
constraints: new { controller = "ado|entityframework", providerName = "mysql|postgresql" }
constraints: new { controller = "ado|entityframework", providerName = "mysql|postgresql|sqlserver" }
);

RouteTable.Routes.MapRoute(
Expand Down
6 changes: 5 additions & 1 deletion aspnet/src/Controllers/AdoController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -143,12 +143,16 @@ public ActionResult Update(string providerName, int? queries)
if (world == null)
continue;

DbParameter idUpdateParameter = updateCommand.CreateParameter();
idUpdateParameter.ParameterName = "@ID";
idUpdateParameter.Value = randomID;

DbParameter numberParameter = updateCommand.CreateParameter();
numberParameter.ParameterName = "@Number";
numberParameter.Value = randomNumber;

updateCommand.Parameters.Clear();
updateCommand.Parameters.Add(idParameter);
updateCommand.Parameters.Add(idUpdateParameter);
updateCommand.Parameters.Add(numberParameter);

updateCommand.ExecuteNonQuery();
Expand Down
3 changes: 3 additions & 0 deletions aspnet/src/Web.config
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,23 @@
<add name="MySQL" connectionString="server=localhost; user id=benchmarkdbuser; password=benchmarkdbpass; database=hello_world" providerName="MySql.Data.MySqlClient"/>
<add name="PostgreSQL" connectionString="server=localhost; user id=benchmarkdbuser; password=benchmarkdbpass; database=hello_world" providerName="Npgsql"/>
<add name="MongoDB" connectionString="mongodb://localhost"/>
<add name="SQLServer" connectionString="server=localhost; user id=benchmarkdbuser; password=B3nchmarkDBPass; database=hello_world" providerName="System.Data.SqlClient"/>
</connectionStrings>
<!-- ADO.NET -->
<system.data>
<DbProviderFactories>
<clear/>
<add name="MySql.Data.MySqlClient" description="Data Provider for MySQL" invariant="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.7.2.0"/>
<add name="Npgsql" description="Data Provider for PostgreSQL" invariant="Npgsql" type="Npgsql.NpgsqlFactory, Npgsql, Version=2.0.12.0"/>
<add name="SqlClient Data Provider" description=".Net Framework Data Provider for SqlServer" invariant="System.Data.SqlClient" type="System.Data.SqlClient.SqlClientFactory, System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
</DbProviderFactories>
</system.data>
<!-- Entity Framework -->
<entityFramework>
<providers>
<provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.Entity, Version=6.7.2.0"/>
<provider invariantName="Npgsql" type="Npgsql.NpgsqlServices, Npgsql, Version=2.0.12.0"/>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
<appSettings>
Expand Down
28 changes: 28 additions & 0 deletions config/create-sqlserver-login-and-database.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
-- This SQL Server T-SQL script creates the database user and hello_world database.
--
-- To run this script, login to an administrator account in Windows, open a command prompt and run:
--
-- "%ProgramFiles%\Microsoft SQL Server\110\Tools\binn\sqlcmd.exe" -i <filename of this file>
--

IF EXISTS (SELECT * FROM sys.server_principals WHERE name = 'benchmarkdbuser')
DROP LOGIN benchmarkdbuser
GO

-- This password has mixed-case and a number to satisfy the Windows password policy
CREATE LOGIN benchmarkdbuser WITH PASSWORD = 'B3nchmarkDBPass'
GO

IF EXISTS(SELECT * FROM SYS.DATABASES WHERE NAME='hello_world')
DROP DATABASE hello_world
GO

CREATE DATABASE hello_world
GO
USE hello_world
GO

-- Give this user total power over the database
CREATE USER benchmarkdbuser FOR LOGIN benchmarkdbuser
EXEC sp_addrolemember 'db_owner', 'benchmarkdbuser'
GO
55 changes: 55 additions & 0 deletions config/create-sqlserver.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
-- This SQL Server T-SQL script creates and populates the World and Fortune tables.
--
-- To run this script, make sure that you've already run create-sqlserver-login-and-database.sql
-- to create the database user and database, then open a command prompt and run:
--
-- "%ProgramFiles%\Microsoft SQL Server\110\Tools\binn\sqlcmd.exe" -U benchmarkdbuser -P B3nchmarkDBPass -d hello_world -i <filename of this file>

IF OBJECT_ID('World', 'U') IS NOT NULL
DROP TABLE World
GO

CREATE TABLE World (
id int NOT NULL IDENTITY PRIMARY KEY,
randomNumber int NOT NULL default 0
)
GO

-- Populate World table
DECLARE @RowCount INT
DECLARE @Random INT
SET @RowCount = 0

WHILE @RowCount < 10000
BEGIN
SELECT @Random = ((10000 + 1) - 1) * RAND() + 1
INSERT INTO World (randomNumber) VALUES (@Random)
SET @RowCount = @RowCount + 1
END

GO

IF OBJECT_ID('Fortune', 'U') IS NOT NULL
DROP TABLE Fortune
GO

-- Note that this uses nvarchar to make sure that the column is Unicode.
CREATE TABLE Fortune (
id int NOT NULL IDENTITY PRIMARY KEY,
message nvarchar(2048) NOT NULL
)
GO

INSERT INTO Fortune (message) VALUES (N'fortune: No such file or directory');
INSERT INTO Fortune (message) VALUES (N'A computer scientist is someone who fixes things that aren''t broken.');
INSERT INTO Fortune (message) VALUES (N'After enough decimal places, nobody gives a damn.');
INSERT INTO Fortune (message) VALUES (N'A bad random number generator: 1, 1, 1, 1, 1, 4.33e+67, 1, 1, 1');
INSERT INTO Fortune (message) VALUES (N'A computer program does what you tell it to do, not what you want it to do.');
INSERT INTO Fortune (message) VALUES (N'Emacs is a nice operating system, but I prefer UNIX. — Tom Christaensen');
INSERT INTO Fortune (message) VALUES (N'Any program that runs right is obsolete.');
INSERT INTO Fortune (message) VALUES (N'A list is only as strong as its weakest link. — Donald Knuth');
INSERT INTO Fortune (message) VALUES (N'Feature: A bug with seniority.');
INSERT INTO Fortune (message) VALUES (N'Computers make very fast, very accurate mistakes.');
INSERT INTO Fortune (message) VALUES (N'<script>alert("This should not be displayed in a browser alert box.");</script>');
INSERT INTO Fortune (message) VALUES (N'フレームワークのベンチマーク');
GO
25 changes: 25 additions & 0 deletions setup-sqlserver-bootstrap.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# To download and run this script, open an elevated Command Prompt and then run:
#
# powershell -ExecutionPolicy Bypass -Command "iex (New-Object Net.WebClient).DownloadString('https://raw.github.com/TechEmpower/FrameworkBenchmarks/master/setup-sqlserver-bootstrap.ps1')"

$basedir = "C:\FrameworkBenchmarks"
$rawRepo = "https://raw.github.com/TechEmpower/FrameworkBenchmarks/master"

$config_url = $basedir + "/config"
$config_local = $basedir + "\config"
$setup_sqlserver_url = $rawRepo + "/setup-sqlserver.ps1"
$setup_sqlserver_local = $basedir + "\setup-sqlserver.ps1"
$create_sqlserver_login_and_database_url = $config_url + "/create-sqlserver-login-and-database.sql"
$create_sqlserver_login_and_database_local = $config_local + "/create-sqlserver-login-and-database.sql"
$create_sqlserver_url = $config_url + "/create-sqlserver.sql"
$create_sqlserver_local = $config_local + "/create-sqlserver.sql"

Write-Host "Creating directory: $config`n"
New-Item -Path $config_local -Type Directory -Force | Out-Null

Write-Host "Downloading setup files...`n"
(New-Object System.Net.WebClient).DownloadFile($setup_sqlserver_url, $setup_sqlserver_local)
(New-Object System.Net.WebClient).DownloadFile($create_sqlserver_login_and_database_url, $create_sqlserver_login_and_database_local)
(New-Object System.Net.WebClient).DownloadFile($create_sqlserver_url, $create_sqlserver_local)

powershell -ExecutionPolicy Bypass -File $setup_sqlserver_local
91 changes: 91 additions & 0 deletions setup-sqlserver.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# This script downloads and installs SQL Server and opens it on port 1433.
#
# To run this script, run an elevated Command Prompt and enter:
#
# powershell -ExecutionPolicy Bypass -File <this script's filename>

$basedir = "C:\FrameworkBenchmarks"
$workdir = "$basedir\installs"
New-Item -Path $workdir -Type directory -Force | Out-Null

If (-Not (Get-Service | ? Name -Eq "MSSQLSERVER")) {

Write-Host "Could not find default SQL Server instance, MSSQLSERVER."
Write-Host "Downloading SQL Server (several GBs)..."

# URLs from http://www.microsoft.com/en-us/download/details.aspx?id=35575

$sqlserver_exe_url = "http://download.microsoft.com/download/3/B/D/3BD9DD65-D3E3-43C3-BB50-0ED850A82AD5/SQLServer2012SP1-FullSlipstream-x64-ENU.exe"
$sqlserver_exe_local = "$workdir\SQLServer2012SP1-FullSlipstream-x64-ENU.exe"
(New-Object System.Net.WebClient).DownloadFile($sqlserver_exe_url, $sqlserver_exe_local)

$sqlserver_box_url = "http://download.microsoft.com/download/3/B/D/3BD9DD65-D3E3-43C3-BB50-0ED850A82AD5/SQLServer2012SP1-FullSlipstream-x64-ENU.box"
$sqlserver_box_local = "$workdir\SQLServer2012SP1-FullSlipstream-x64-ENU.box"
(New-Object System.Net.WebClient).DownloadFile($sqlserver_box_url, $sqlserver_box_local)

Write-Host "Installing SQL Server..."

# Install only the SQL Server database engine.
# Use a default instance name.
# Make %COMPUTERNAME%\Administrators have administrative rights.

# The following is not used because this is done in PowerShell below.
# /securitymode=SQL /sapwd=S3cr3tS3cr3t /TCPENABLED=1
# Allow Windows Authentication or old-style SQL authentication.
# The password of the sa account is specified.
# SQL Server will be listening on TCP port 1433.
#
Start-Process "$sqlserver_exe_local" "/q /action=install /features=SQLEngine /INSTANCENAME=MSSQLSERVER /SQLSYSADMINACCOUNTS=Administrators /IACCEPTSQLSERVERLICENSETERMS" -Wait
}

# In case we just installed SQL Server and the environment variables haven't been refreshed, manually
# refresh PSModulePath so that Import-Module sqlps will work.

$env:PSModulePath = [Environment]::GetEnvironmentVariable("PSModulePath", [System.EnvironmentVariableTarget]::Machine)

Import-Module sqlps

Write-Host "Setting SQL Server to start on boot..."

Set-Service MSSQLSERVER -StartupType Automatic

Write-Host "Ensuring that SQL Server is started..."

Start-Service MSSQLSERVER

Write-Host "Enabling SQL authentication..."

# Enable SQL authentication
$s = New-Object ('Microsoft.SqlServer.Management.Smo.Server')
$s.Settings.LoginMode = [Microsoft.SqlServer.Management.SMO.ServerLoginMode]::Mixed
$s.Alter()

Write-Host "Configuring SQL Server to listen on TCP (default port 1433)..."

# Enable the TCP protocol on the default instance.
$wmi = New-Object ('Microsoft.SqlServer.Management.Smo.Wmi.ManagedComputer')
$uri = "ManagedComputer[@Name='" + (Get-Content env:computername) + "']/ ServerInstance[@Name='MSSQLSERVER']/ServerProtocol[@Name='Tcp']"
$Tcp = $wmi.GetSmoObject($uri)
$Tcp.IsEnabled = $true
$Tcp.Alter()

Write-Host "Restarting SQL Server..."

Restart-Service -Name MSSQLSERVER

If (-Not (Get-NetFirewallPortFilter | ? LocalPort -Eq "1433")) {
Write-Host "Opening port 1433 in firewall..."
New-NetFirewallRule -DisplayName "SQL 1433" -Action Allow -Direction Inbound -LocalPort 1433 -Protocol TCP | Out-Null
} else {
Write-Host "Port 1433 is already configured in firewall."
}

Write-Host "Creating SQL Server login and populated database..."

# Connect with Windows Authentication, assuming that we have access.
Invoke-Sqlcmd -InputFile "$basedir\config\create-sqlserver-login-and-database.sql" -OutputSqlErrors $True

# Now that benchmarkdbuser has been created, we can connect with those credentials.
Invoke-Sqlcmd -Username benchmarkdbuser -Password B3nchmarkDBPass -Database hello_world -InputFile "$basedir\config\create-sqlserver.sql" -OutputSqlErrors $True

Write-Host "Done."