Skip to content

Commit bdf7a5b

Browse files
authored
FIx perf pipeline (#838)
* dont start func host in fixture for perf * don't use fixture in perf test * finally block
1 parent 537ee5a commit bdf7a5b

File tree

3 files changed

+171
-149
lines changed

3 files changed

+171
-149
lines changed

performance/SqlBindingBenchmarks.cs

Lines changed: 44 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT License. See License.txt in the project root for license information.
33

4+
using System.Diagnostics;
45
using System.Linq;
56
using BenchmarkDotNet.Running;
6-
using Microsoft.Azure.WebJobs.Extensions.Sql.Tests.Integration;
7+
using Microsoft.Azure.WebJobs.Extensions.Sql.Tests.Common;
78

89
namespace Microsoft.Azure.WebJobs.Extensions.Sql.Performance
910
{
@@ -13,40 +14,49 @@ public static void Main(string[] args)
1314
{
1415
bool runAll = args.Length == 0;
1516

16-
using var testFixture = new IntegrationTestFixture();
17+
Process azuriteHost = TestUtils.StartAzurite();
18+
TestUtils.SetupDatabase(out string masterConnectionString, out string connectionString);
19+
try
20+
{
21+
// **IMPORTANT** If changing these make sure to update template-steps-performance.yml as well
22+
if (runAll || args.Contains("input"))
23+
{
24+
BenchmarkRunner.Run<SqlInputBindingPerformance>();
25+
}
26+
if (runAll || args.Contains("output"))
27+
{
28+
BenchmarkRunner.Run<SqlOutputBindingPerformance>();
29+
}
30+
if (runAll || args.Contains("trigger"))
31+
{
32+
BenchmarkRunner.Run<SqlTriggerBindingPerformance>();
33+
}
34+
if (runAll || args.Contains("trigger_batch"))
35+
{
36+
BenchmarkRunner.Run<SqlTriggerBindingPerformance_BatchOverride>();
37+
}
38+
if (runAll || args.Contains("trigger_poll"))
39+
{
40+
BenchmarkRunner.Run<SqlTriggerBindingPerformance_PollingIntervalOverride>();
41+
}
42+
if (runAll || args.Contains("trigger_overrides"))
43+
{
44+
BenchmarkRunner.Run<SqlTriggerPerformance_Overrides>();
45+
}
46+
if (runAll || args.Contains("trigger_parallel"))
47+
{
48+
BenchmarkRunner.Run<SqlTriggerBindingPerformance_Parallelization>();
49+
}
50+
if (runAll || args.Contains("trigger_changerate"))
51+
{
52+
BenchmarkRunner.Run<SqlTriggerBindingPerformance_ChangeRate>();
53+
}
54+
}
55+
finally
56+
{
57+
TestUtils.StopAzurite(azuriteHost);
58+
TestUtils.DropDatabase(masterConnectionString, connectionString);
1759

18-
// **IMPORTANT** If changing these make sure to update template-steps-performance.yml as well
19-
if (runAll || args.Contains("input"))
20-
{
21-
BenchmarkRunner.Run<SqlInputBindingPerformance>();
22-
}
23-
if (runAll || args.Contains("output"))
24-
{
25-
BenchmarkRunner.Run<SqlOutputBindingPerformance>();
26-
}
27-
if (runAll || args.Contains("trigger"))
28-
{
29-
BenchmarkRunner.Run<SqlTriggerBindingPerformance>();
30-
}
31-
if (runAll || args.Contains("trigger_batch"))
32-
{
33-
BenchmarkRunner.Run<SqlTriggerBindingPerformance_BatchOverride>();
34-
}
35-
if (runAll || args.Contains("trigger_poll"))
36-
{
37-
BenchmarkRunner.Run<SqlTriggerBindingPerformance_PollingIntervalOverride>();
38-
}
39-
if (runAll || args.Contains("trigger_overrides"))
40-
{
41-
BenchmarkRunner.Run<SqlTriggerPerformance_Overrides>();
42-
}
43-
if (runAll || args.Contains("trigger_parallel"))
44-
{
45-
BenchmarkRunner.Run<SqlTriggerBindingPerformance_Parallelization>();
46-
}
47-
if (runAll || args.Contains("trigger_changerate"))
48-
{
49-
BenchmarkRunner.Run<SqlTriggerBindingPerformance_ChangeRate>();
5060
}
5161
}
5262
}

test/Common/TestUtils.cs

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
using System.Threading;
1313
using System.Threading.Tasks;
1414
using Microsoft.Azure.WebJobs.Extensions.Sql.Samples.Common;
15+
using Microsoft.Data.SqlClient;
1516

1617
namespace Microsoft.Azure.WebJobs.Extensions.Sql.Tests.Common
1718
{
@@ -22,6 +23,125 @@ public static class TestUtils
2223
{
2324
internal static int ThreadId;
2425

26+
/// <summary>
27+
/// This returns a running Azurite storage emulator.
28+
/// </summary>
29+
public static Process StartAzurite()
30+
{
31+
Console.WriteLine("Starting Azurite Host...");
32+
var azuriteHost = new Process()
33+
{
34+
StartInfo = new ProcessStartInfo
35+
{
36+
FileName = "azurite",
37+
WindowStyle = ProcessWindowStyle.Hidden,
38+
UseShellExecute = true
39+
}
40+
};
41+
42+
azuriteHost.Start();
43+
return azuriteHost;
44+
}
45+
46+
public static void StopAzurite(Process azuriteHost)
47+
{
48+
Console.WriteLine("Stopping Azurite Host...");
49+
try
50+
{
51+
azuriteHost.Kill(true);
52+
azuriteHost.Dispose();
53+
}
54+
catch (Exception e)
55+
{
56+
Console.WriteLine($"Failed to stop Azurite, Error: {e.Message}");
57+
}
58+
}
59+
60+
/// <summary>
61+
/// Sets up a test database for the tests to use.
62+
/// </summary>
63+
/// <remarks>
64+
/// The server the database will be created on can be set by the environment variable "TEST_SERVER", otherwise localhost will be used by default.
65+
/// By default, integrated authentication will be used to connect to the server, unless the env variable "SA_PASSWORD" is set.
66+
/// In this case, connection will be made using SQL login with user "SA" and the provided password.
67+
/// </remarks>
68+
public static void SetupDatabase(out string MasterConnectionString, out string DatabaseName)
69+
{
70+
SqlConnectionStringBuilder connectionStringBuilder;
71+
string connectionString = Environment.GetEnvironmentVariable("TEST_CONNECTION_STRING");
72+
string masterConnectionString;
73+
if (connectionString != null)
74+
{
75+
masterConnectionString = connectionString;
76+
connectionStringBuilder = new SqlConnectionStringBuilder(connectionString);
77+
}
78+
else
79+
{
80+
// Get the test server name from environment variable "TEST_SERVER", default to localhost if not set
81+
string testServer = Environment.GetEnvironmentVariable("TEST_SERVER");
82+
if (string.IsNullOrEmpty(testServer))
83+
{
84+
testServer = "localhost";
85+
}
86+
87+
// First connect to master to create the database
88+
connectionStringBuilder = new SqlConnectionStringBuilder()
89+
{
90+
DataSource = testServer,
91+
InitialCatalog = "master",
92+
Pooling = false,
93+
Encrypt = SqlConnectionEncryptOption.Optional
94+
};
95+
96+
// Either use integrated auth or SQL login depending if SA_PASSWORD is set
97+
string userId = "SA";
98+
string password = Environment.GetEnvironmentVariable("SA_PASSWORD");
99+
if (string.IsNullOrEmpty(password))
100+
{
101+
connectionStringBuilder.IntegratedSecurity = true;
102+
}
103+
else
104+
{
105+
connectionStringBuilder.UserID = userId;
106+
connectionStringBuilder.Password = password;
107+
}
108+
masterConnectionString = connectionStringBuilder.ToString();
109+
}
110+
111+
// Create database
112+
// Retry this in case the server isn't fully initialized yet
113+
string databaseName = GetUniqueDBName("SqlBindingsTest");
114+
Retry(() =>
115+
{
116+
using var masterConnection = new SqlConnection(masterConnectionString);
117+
masterConnection.Open();
118+
ExecuteNonQuery(masterConnection, $"CREATE DATABASE [{databaseName}]", Console.WriteLine);
119+
// Enable change tracking for trigger tests
120+
ExecuteNonQuery(masterConnection, $"ALTER DATABASE [{databaseName}] SET CHANGE_TRACKING = ON (CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON);", Console.WriteLine);
121+
}, Console.WriteLine);
122+
123+
connectionStringBuilder.InitialCatalog = databaseName;
124+
125+
// Set SqlConnectionString env var for the tests to use
126+
Environment.SetEnvironmentVariable("SqlConnectionString", connectionStringBuilder.ToString());
127+
MasterConnectionString = masterConnectionString;
128+
DatabaseName = databaseName;
129+
}
130+
131+
public static void DropDatabase(string masterConnectionString, string databaseName)
132+
{
133+
try
134+
{
135+
using var masterConnection = new SqlConnection(masterConnectionString);
136+
masterConnection.Open();
137+
ExecuteNonQuery(masterConnection, $"DROP DATABASE IF EXISTS {databaseName}", Console.WriteLine);
138+
}
139+
catch (Exception e)
140+
{
141+
Console.WriteLine($"Failed to drop {databaseName}, Error: {e.Message}");
142+
}
143+
}
144+
25145
/// <summary>
26146
/// Returns a mangled name that unique based on Prefix + Machine + Process
27147
/// </summary>

test/Integration/IntegrationTestFixture.cs

Lines changed: 7 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
using System.IO;
88
using System.Threading.Tasks;
99
using Microsoft.Azure.WebJobs.Extensions.Sql.Tests.Common;
10-
using Microsoft.Data.SqlClient;
1110
using Xunit;
1211
using static Microsoft.Azure.WebJobs.Extensions.Sql.Telemetry.Telemetry;
1312

@@ -22,17 +21,17 @@ public class IntegrationTestFixture : IDisposable
2221
/// Host process for Azurite local storage emulator. This is required for non-HTTP trigger functions:
2322
/// https://docs.microsoft.com/azure/azure-functions/functions-develop-local
2423
/// </summary>
25-
private Process AzuriteHost;
24+
private readonly Process AzuriteHost;
2625

2726
/// <summary>
2827
/// Connection string to the master database on the test server, mainly used for database setup and teardown.
2928
/// </summary>
30-
private string MasterConnectionString;
29+
private readonly string MasterConnectionString;
3130

3231
/// <summary>
3332
/// Name of the database used.
3433
/// </summary>
35-
private string DatabaseName;
34+
private readonly string DatabaseName;
3635

3736
/// <summary>
3837
/// List of all functions in the samples folder that will be started before the
@@ -56,98 +55,11 @@ public class IntegrationTestFixture : IDisposable
5655

5756
public IntegrationTestFixture()
5857
{
59-
this.StartAzurite();
60-
this.SetupDatabase();
58+
this.AzuriteHost = TestUtils.StartAzurite();
59+
TestUtils.SetupDatabase(out this.MasterConnectionString, out this.DatabaseName);
6160
this.StartFunctionHosts();
6261
}
6362

64-
/// <summary>
65-
/// This starts the Azurite storage emulator.
66-
/// </summary>
67-
protected void StartAzurite()
68-
{
69-
Console.WriteLine("Starting Azurite Host...");
70-
this.AzuriteHost = new Process()
71-
{
72-
StartInfo = new ProcessStartInfo
73-
{
74-
FileName = "azurite",
75-
WindowStyle = ProcessWindowStyle.Hidden,
76-
UseShellExecute = true
77-
}
78-
};
79-
80-
this.AzuriteHost.Start();
81-
}
82-
83-
/// <summary>
84-
/// Sets up a test database for the tests to use.
85-
/// </summary>
86-
/// <remarks>
87-
/// The server the database will be created on can be set by the environment variable "TEST_SERVER", otherwise localhost will be used by default.
88-
/// By default, integrated authentication will be used to connect to the server, unless the env variable "SA_PASSWORD" is set.
89-
/// In this case, connection will be made using SQL login with user "SA" and the provided password.
90-
/// </remarks>
91-
private void SetupDatabase()
92-
{
93-
SqlConnectionStringBuilder connectionStringBuilder;
94-
string connectionString = Environment.GetEnvironmentVariable("TEST_CONNECTION_STRING");
95-
if (connectionString != null)
96-
{
97-
this.MasterConnectionString = connectionString;
98-
connectionStringBuilder = new SqlConnectionStringBuilder(connectionString);
99-
}
100-
else
101-
{
102-
// Get the test server name from environment variable "TEST_SERVER", default to localhost if not set
103-
string testServer = Environment.GetEnvironmentVariable("TEST_SERVER");
104-
if (string.IsNullOrEmpty(testServer))
105-
{
106-
testServer = "localhost";
107-
}
108-
109-
// First connect to master to create the database
110-
connectionStringBuilder = new SqlConnectionStringBuilder()
111-
{
112-
DataSource = testServer,
113-
InitialCatalog = "master",
114-
Pooling = false,
115-
Encrypt = SqlConnectionEncryptOption.Optional
116-
};
117-
118-
// Either use integrated auth or SQL login depending if SA_PASSWORD is set
119-
string userId = "SA";
120-
string password = Environment.GetEnvironmentVariable("SA_PASSWORD");
121-
if (string.IsNullOrEmpty(password))
122-
{
123-
connectionStringBuilder.IntegratedSecurity = true;
124-
}
125-
else
126-
{
127-
connectionStringBuilder.UserID = userId;
128-
connectionStringBuilder.Password = password;
129-
}
130-
this.MasterConnectionString = connectionStringBuilder.ToString();
131-
}
132-
133-
// Create database
134-
// Retry this in case the server isn't fully initialized yet
135-
this.DatabaseName = TestUtils.GetUniqueDBName("SqlBindingsTest");
136-
TestUtils.Retry(() =>
137-
{
138-
using var masterConnection = new SqlConnection(this.MasterConnectionString);
139-
masterConnection.Open();
140-
TestUtils.ExecuteNonQuery(masterConnection, $"CREATE DATABASE [{this.DatabaseName}]", Console.WriteLine);
141-
// Enable change tracking for trigger tests
142-
TestUtils.ExecuteNonQuery(masterConnection, $"ALTER DATABASE [{this.DatabaseName}] SET CHANGE_TRACKING = ON (CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON);", Console.WriteLine);
143-
}, Console.WriteLine);
144-
145-
connectionStringBuilder.InitialCatalog = this.DatabaseName;
146-
147-
// Set SqlConnectionString env var for the tests to use
148-
Environment.SetEnvironmentVariable("SqlConnectionString", connectionStringBuilder.ToString());
149-
}
150-
15163
/// <summary>
15264
/// This starts the function hosts for each language.
15365
/// </summary>
@@ -257,28 +169,8 @@ void TestOutputHandler(object sender, DataReceivedEventArgs e)
257169
public void Dispose()
258170
{
259171
this.DisposeFunctionHosts();
260-
261-
try
262-
{
263-
this.AzuriteHost.Kill(true);
264-
this.AzuriteHost.Dispose();
265-
}
266-
catch (Exception e)
267-
{
268-
Console.WriteLine($"Failed to stop Azurite, Error: {e.Message}");
269-
}
270-
271-
try
272-
{
273-
// Drop the test database
274-
using var masterConnection = new SqlConnection(this.MasterConnectionString);
275-
masterConnection.Open();
276-
TestUtils.ExecuteNonQuery(masterConnection, $"DROP DATABASE IF EXISTS {this.DatabaseName}", Console.WriteLine);
277-
}
278-
catch (Exception e4)
279-
{
280-
Console.WriteLine($"Failed to drop {this.DatabaseName}, Error: {e4.Message}");
281-
}
172+
TestUtils.StopAzurite(this.AzuriteHost);
173+
TestUtils.DropDatabase(this.MasterConnectionString, this.DatabaseName);
282174

283175
GC.SuppressFinalize(this);
284176
}

0 commit comments

Comments
 (0)