();
30 | int i = 0;
31 | try
32 | {
33 | if (userArgs.Length > 0)
34 | {
35 | foreach (var tmp in userArgs)
36 | {
37 | if (tmp.StartsWith("-"))
38 | {
39 | var paramAndValue = new[] {tmp.Substring(1, tmp.IndexOf(":", StringComparison.Ordinal) - 1), tmp.Substring(tmp.IndexOf(":", StringComparison.Ordinal) + 1)};
40 | tempUserArgs.Add(paramAndValue[0].ToLower(), paramAndValue[1]);
41 | }
42 | else
43 | {
44 | tempUserArgs.Add(methodParameters[i].Name.ToLower(), tmp);
45 | }
46 | i++;
47 | }
48 | }
49 | foreach (var parameter in methodParameters)
50 | {
51 | var val = parameter.DefaultValue;
52 | var key = parameter.Name.ToLower();
53 | if (tempUserArgs.ContainsKey(key))
54 | {
55 | val = tempUserArgs[key];
56 | }
57 | Type paramType = parameter.ParameterType;
58 |
59 | try
60 | {
61 | val = Convert.ChangeType(val, paramType);
62 | }
63 | catch (InvalidCastException)
64 | {
65 | if (paramType.IsEnum)
66 | {
67 | var enumValues = Enum.GetNames(paramType);
68 | var constant = enumValues.FirstOrDefault(s => s.Equals(val.ToString(), StringComparison.CurrentCultureIgnoreCase));
69 | if (constant != null)
70 | {
71 | val = Enum.Parse(paramType, constant);
72 | }
73 | else
74 | {
75 | var message = string.Format("Parameter {0} has unavailable value {1}! Available values are: {2}.",
76 | parameter.Name,
77 | val,
78 | string.Join("|", enumValues));
79 | throw new ArgumentException(message);
80 | }
81 | }
82 | }
83 |
84 | joinedArgs.Add(val);
85 | }
86 | }
87 | catch (IndexOutOfRangeException)
88 | {
89 | throw new Exception("Not enough arguments");
90 | }
91 |
92 | return joinedArgs.ToArray();
93 | }
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # azure-functions-performance-test
2 |
3 | ## Set up Environment
4 |
5 | ### Tests samples required to run the according tests.
6 |
7 | #### Queue-Node-Js-CPU-Intensive
8 |
9 |
10 | Function is triggered by queue input. Input ia a number and function generates to random square matixes of input x input size
11 | then in multiplies matrixes, prints "Finish." when calculation is done.
12 | This operation is very heavily using CPU resources, concurrent executions on single container cause function to execute slower
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | #### Queue-Node-Js-High-Memory
24 |
25 |
26 | Function is designed to allocate big array depending on input size.
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 | #### Queue-Node-Js-Low-Usage
38 |
39 |
40 | Function has low usage gets message, reads it count to 1000 and finishes.
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 | #### Blob-Node-Js-CPU-Intensive
53 |
54 |
55 | Function is triggered by queue input. Input ia a number and function generates to random square matixes of input x input size
56 | then in multiplies matrixes, prints "Finish." when calculation is done.
57 | This operation is very heavily using CPU resources, concurrent executions on single container cause function to execute slower
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 | #### Blob-Node-Js-High-Memory
69 |
70 |
71 | Function is designed to allocate big array depending on input size.
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 | #### Blob-Node-Js-Low-Usage
83 |
84 |
85 | Function has low usage gets message, reads it count to 1000 and finishes.
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 | #### Http-Node-Js-CPU-Intensive
99 |
100 |
101 | Function is triggered by queue input. Input ia a number and function generates to random square matixes of input x input size
102 | then in multiplies matrixes, prints "Finish." when calculation is done.
103 | This operation is very heavily using CPU resources, concurrent executions on single container cause function to execute slower
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 | #### Http-Node-Js-High-Memory
115 |
116 |
117 | Function is designed to allocate big array depending on input size.
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 | #### Http-Node-Js-Low-Usage
129 |
130 |
131 | Function has low usage gets message, reads it count to 1000 and finishes.
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## Security
4 |
5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
6 |
7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below.
8 |
9 | ## Reporting Security Issues
10 |
11 | **Please do not report security vulnerabilities through public GitHub issues.**
12 |
13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report).
14 |
15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey).
16 |
17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc).
18 |
19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
20 |
21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
22 | * Full paths of source file(s) related to the manifestation of the issue
23 | * The location of the affected source code (tag/branch/commit or direct URL)
24 | * Any special configuration required to reproduce the issue
25 | * Step-by-step instructions to reproduce the issue
26 | * Proof-of-concept or exploit code (if possible)
27 | * Impact of the issue, including how an attacker might exploit the issue
28 |
29 | This information will help us triage your report more quickly.
30 |
31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs.
32 |
33 | ## Preferred Languages
34 |
35 | We prefer all communications to be in English.
36 |
37 | ## Policy
38 |
39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd).
40 |
41 |
42 |
--------------------------------------------------------------------------------
/SampleUsages/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/SampleUsages/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Data;
4 | using System.Drawing;
5 | using System.IO;
6 | using System.Linq;
7 | using MiniCommandLineHelper;
8 | using ServerlessBenchmark;
9 | using ServerlessBenchmark.LoadProfiles;
10 | using ServerlessBenchmark.PerfResultProviders;
11 | using ServerlessBenchmark.TriggerTests.AWS;
12 | using ServerlessBenchmark.TriggerTests.Azure;
13 | using ServerlessBenchmark.TriggerTests.BaseTriggers;
14 |
15 | namespace SampleUsages
16 | {
17 | public class Program : CmdHelper
18 | {
19 | public new static void Main(string[] args)
20 | {
21 | var p = new Program();
22 | ((CmdHelper) p).Main(args);
23 | }
24 |
25 | #region LambdaTests
26 | [Command]
27 | public void S3Test(string functionName, string blobPath, string srcBucket, string targetBucket, string loadProfile, int eps = 0, bool repeat = false, int durationMinutes = 0)
28 | {
29 | var blobs = Directory.GetFiles(blobPath);
30 | var test = new AmazonS3TriggerTest(functionName, blobs, srcBucket, targetBucket);
31 | StorageTriggerTest(test, blobs, loadProfile, eps, repeat, durationMinutes);
32 | }
33 |
34 | [Command]
35 | public void SqsTest(string functionName, string messages, string srcQueue, string targetQueue,
36 | string loadProfile, int eps = 0, bool repeat = false, int durationMinutes = 0)
37 | {
38 | var queueMessages = File.ReadAllLines(messages);
39 | var test = new AmazonSqsTriggerTest(functionName, queueMessages, srcQueue, targetQueue);
40 | StorageTriggerTest(test, queueMessages, loadProfile, eps, repeat, durationMinutes);
41 | }
42 |
43 | [Command]
44 | public void ApiGatewayTest(string functionName, string urlsFile, string loadProfile, int eps = 0, bool repeat = false, int durationMinutes = 0)
45 | {
46 | var urls = File.ReadAllLines(urlsFile);
47 | var test = new AmazonApiGatewayTriggerTest(functionName, urls);
48 | HttpTriggerTest(test, urls, loadProfile, eps, repeat, durationMinutes);
49 | }
50 |
51 | [Command]
52 | public void SnsToSqsTest(string functionName, string messages, string srcTopic, string targetQueue,
53 | string loadProfile, int eps = 0, bool repeat = false, int durationMinutes = 0)
54 | {
55 | var queueMessages = File.ReadAllLines(messages);
56 | var test = new AmazonSnsToSqs(functionName, queueMessages, srcTopic, targetQueue);
57 | StorageTriggerTest(test, queueMessages, loadProfile, eps, repeat, durationMinutes);
58 | }
59 |
60 | [Command]
61 | public void AnalyzeAwsTest(string functionName, DateTime startTime, DateTime endTime)
62 | {
63 | var resultsProvider = new AwsGenericPerformanceResultsProvider();
64 | var results = resultsProvider.GetPerfMetrics(functionName, startTime, endTime);
65 | //print perf results
66 | var originalColor = Console.ForegroundColor;
67 | Console.ForegroundColor = ConsoleColor.Green;
68 | Console.WriteLine(results);
69 | Console.ForegroundColor = originalColor;
70 | }
71 | #endregion
72 |
73 | #region AzureFunctionTest
74 |
75 | [Command]
76 | public void BlobTest(string functionName, string blobPath, string srcBlobContainer,
77 | string targetBlobContainer, string loadProfile, int eps = 0, bool repeat = false, int durationMinutes = 0)
78 | {
79 | AzureStorageTest(TriggerTypes.Blob, functionName, blobPath, srcBlobContainer, targetBlobContainer, loadProfile, eps, repeat, durationMinutes);
80 | }
81 |
82 | [Command]
83 | public void QueueTest(string functionName, string queueItems, string srcQueue,
84 | string targetQueue, string loadProfile, int eps = 0, bool repeat = false, int durationMinutes = 0)
85 | {
86 | AzureStorageTest(TriggerTypes.Queue, functionName, queueItems, srcQueue, targetQueue, loadProfile, eps, repeat, durationMinutes);
87 | }
88 |
89 | [Command]
90 | public void AzureHttpTest(string functionName, string urlsFile, string loadProfile, int eps = 0, bool repeat = false, int durationMinutes = 0)
91 | {
92 | var urls = File.ReadAllLines(urlsFile);
93 | var test = new AzureHttpTriggerTest(functionName, urls);
94 | HttpTriggerTest(test, urls, loadProfile, eps, repeat, durationMinutes);
95 | }
96 |
97 | private void AzureStorageTest(TriggerTypes triggerType, string functionName, string items, string source, string target, string loadProfile, int eps = 0, bool repeat = false, int durationMinutes = 0)
98 | {
99 | FunctionTest test;
100 | switch (triggerType)
101 | {
102 | case TriggerTypes.Blob:
103 | var blobs = Directory.GetFiles(items);
104 | test = new AzureBlobTriggerTest(functionName, blobs, source, target);
105 | StorageTriggerTest(test, blobs, loadProfile, eps, repeat, durationMinutes);
106 | break;
107 | case TriggerTypes.Queue:
108 | var queueMessages = File.ReadAllLines(items);
109 | test = new AzureQueueTriggerTest(functionName, queueMessages, source, target);
110 | StorageTriggerTest(test, queueMessages, loadProfile, eps, repeat, durationMinutes);
111 | break;
112 | }
113 | }
114 |
115 | [Command]
116 | public void AnalyzeAzureTest(string functionName, DateTime startTime, DateTime endTime)
117 | {
118 | var resultsProvider = new AzureGenericPerformanceResultsProvider();
119 | var results = resultsProvider.GetPerfMetrics(functionName, startTime, endTime);
120 | //print perf results
121 | var originalColor = Console.ForegroundColor;
122 | Console.ForegroundColor = ConsoleColor.Green;
123 | Console.WriteLine(results);
124 | Console.ForegroundColor = originalColor;
125 | }
126 | #endregion
127 |
128 | private void HttpTriggerTest(FunctionTest functionTest, IEnumerable urls, string loadProfile, int eps = 0, bool repeat = false,
129 | int durationMinutes = 0)
130 | {
131 | TriggerTestLoadProfile profile;
132 | if (loadProfile.Equals("Linear", StringComparison.CurrentCultureIgnoreCase) && repeat)
133 | {
134 | if (durationMinutes <= 0)
135 | {
136 | throw new ArgumentException("No parameter to specify how long to repeat this load. Indicate how long in minutes to repeat load.", "durationMinutes");
137 | }
138 | profile = new LinearLoad(TimeSpan.FromMinutes(durationMinutes), eps == 0 ? 1 : eps);
139 | }
140 | else if (loadProfile.Equals("Linear", StringComparison.CurrentCultureIgnoreCase) && !repeat)
141 | {
142 | profile = new LinearLoad(urls.Count(), eps == 0 ? 1 : eps);
143 | }
144 | else
145 | {
146 | throw new Exception(string.Format("{0} does not exist", loadProfile));
147 | }
148 | var perfResult = functionTest.RunAsync(profile).Result;
149 |
150 | //print perf results
151 | var originalColor = Console.ForegroundColor;
152 | Console.ForegroundColor = ConsoleColor.Green;
153 | Console.WriteLine(perfResult);
154 | Console.ForegroundColor = originalColor;
155 | }
156 |
157 | private void StorageTriggerTest(FunctionTest functionTest, IEnumerable sourceItems, string loadProfile, int eps = 0, bool repeat = false, int durationMinutes = 0)
158 | {
159 | TriggerTestLoadProfile profile;
160 |
161 | if (loadProfile.Equals("Linear", StringComparison.CurrentCultureIgnoreCase) && repeat)
162 | {
163 | if (durationMinutes <= 0)
164 | {
165 | throw new ArgumentException("No parameter to specify how long to repeat this load. Indicate how long in minutes to repeat load.", "durationMinutes");
166 | }
167 | profile = new LinearLoad(TimeSpan.FromMinutes(durationMinutes), eps == 0 ? 1 : eps);
168 | }
169 | else if (loadProfile.Equals("Linear", StringComparison.CurrentCultureIgnoreCase) && !repeat)
170 | {
171 | profile = new LinearLoad(sourceItems.Count(), eps == 0 ? 1 : eps);
172 | }
173 | else
174 | {
175 | throw new Exception(string.Format("{0} does not exist", loadProfile));
176 | }
177 |
178 | var perfResult = functionTest.RunAsync(profile).Result;
179 |
180 | //print perf results
181 | var originalColor = Console.ForegroundColor;
182 | Console.ForegroundColor = ConsoleColor.Green;
183 | Console.WriteLine(perfResult);
184 | Console.ForegroundColor = originalColor;
185 | }
186 | }
187 | }
188 |
--------------------------------------------------------------------------------
/SampleUsages/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("SampleUsages")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("SampleUsages")]
13 | [assembly: AssemblyCopyright("Copyright © 2016")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("834f2f93-ce2f-4080-b4e0-49aee23c4617")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/SampleUsages/SampleUsages.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {6B65B2D7-6344-4B15-A428-483E74E9AF51}
8 | Exe
9 | Properties
10 | SampleUsages
11 | SampleUsages
12 | v4.5
13 | 512
14 |
15 |
16 | AnyCPU
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | AnyCPU
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | {600ba962-07ea-46ec-b8f5-9bc5933c5533}
75 | MiniCommandLineHelper
76 |
77 |
78 | {582cc16b-6c75-494b-b27f-7a769dec0c30}
79 | ServerlessBenchmark
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
102 |
--------------------------------------------------------------------------------
/SampleUsages/TestSamples/Blob-NodeJs-CPUIntensive/azuredeploy.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://schemas.management.azure.com/schemas/2015-01-01-preview/deploymentTemplate.json#",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "storageAccountType": {
6 | "allowedValues": [
7 | "Standard_LRS",
8 | "Standard_GRS",
9 | "Standard_ZRS",
10 | "Premium_LRS"
11 | ],
12 | "defaultValue": "Standard_LRS",
13 | "metadata": {
14 | "description": "Storage Account type"
15 | },
16 | "type": "string"
17 | }
18 | },
19 | "resources": [
20 | {
21 | "apiVersion": "2015-06-15",
22 | "location": "[resourceGroup().location]",
23 | "name": "[variables('storageAccountName')]",
24 | "properties": {
25 | "accountType": "[parameters('storageAccountType')]"
26 | },
27 | "type": "Microsoft.Storage/storageAccounts"
28 | },
29 | {
30 | "apiVersion": "2015-04-01",
31 | "location": "[resourceGroup().location]",
32 | "name": "[variables('hostingPlanName')]",
33 | "properties": {
34 | "computeMode": "Dynamic",
35 | "name": "[variables('hostingPlanName')]",
36 | "sku": "Dynamic"
37 | },
38 | "type": "Microsoft.Web/serverfarms"
39 | },
40 | {
41 | "apiVersion": "2015-08-01",
42 | "dependsOn": [
43 | "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]",
44 | "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
45 | ],
46 | "kind": "functionapp",
47 | "location": "[resourceGroup().location]",
48 | "name": "[variables('functionAppName')]",
49 | "properties": {
50 | "name": "[variables('functionAppName')]",
51 | "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]"
52 | },
53 | "resources": [
54 | {
55 | "apiVersion": "2016-03-01",
56 | "dependsOn": [
57 | "[resourceId('Microsoft.Web/sites', variables('functionAppName'))]",
58 | "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
59 | ],
60 | "name": "appsettings",
61 | "properties": {
62 | "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING" : "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listkeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2015-05-01-preview').key1,';')]",
63 | "WEBSITE_CONTENTSHARE" : "[concat(variables('functionAppName'))]",
64 | "AzureWebJobsDashboard": "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listkeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2015-05-01-preview').key1,';')]",
65 | "AzureWebJobsStorage": "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listkeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2015-05-01-preview').key1,';')]",
66 | "FUNCTIONS_EXTENSION_VERSION": "~0.3"
67 | },
68 | "type": "config"
69 | },
70 | {
71 | "apiVersion": "2016-03-01",
72 | "dependsOn": [
73 | "[resourceId('Microsoft.Web/sites', variables('functionAppName'))]",
74 | "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
75 | ],
76 | "name": "[concat(variables('functionAppName'), '/', variables('functionName'))]",
77 | "type": "Microsoft.Web/sites/functions",
78 | "properties": {
79 | "files":
80 | {
81 | "index.js": "// function is triggered by queue input. Input ia a number and function generates to random square matixes of input x input size\r\n// then in multiplies matrixes, prints \"Finish.\" when calculation is done.\r\n// This operation is very heavily using CPU resources, concurrent executions on single container cause function to execute slower\r\n\r\nmodule.exports = function (context, myBlob) {\r\n main(context, myBlob);\r\n context.done();\r\n}\r\n\r\nvar multiple_row_and_column = function(row, column){\r\n // assume same length of row and column\r\n var result = 0;\r\n for(var i = 0; i < row.length; i++)\r\n {\r\n result += row[i] * column[i];\r\n }\r\n\r\n return result;\r\n}\r\n\r\nvar create_random_matrix = function(size, seed, value_min, value_max) {\r\n var matrix = [];\r\n\r\n for (var i = 0; i < size; i++) {\r\n var row = [];\r\n for (var j = 0; j < size; j++){\r\n var val = parseInt(Math.random(seed) * (value_max - value_min), 10);\r\n row.push(val);\r\n }\r\n\r\n matrix.push(row);\r\n }\r\n\r\n return matrix;\r\n}\r\n\r\nvar get_row_from_matrix = function(matrix, i){\r\n return matrix[i];\r\n}\r\n\r\nvar get_column_from_matrix = function(matrix, j){\r\n var column = [];\r\n for(var i = 0; i < matrix.length; i++){\r\n column.push(matrix[i][j]);\r\n }\r\n\r\n return column;\r\n}\r\n\r\nvar multiple_matrix = function(matrixA, matrixB) {\r\n var result = [];\r\n\r\n for (var i = 0; i < matrixA.length; i++) {\r\n var result_row = [];\r\n for (var j = 0; j < matrixA[0].length; j++) {\r\n var row = get_row_from_matrix(matrixA, i);\r\n var column = get_column_from_matrix(matrixB, j);\r\n result_row.push(multiple_row_and_column(row, column));\r\n }\r\n result.push(result_row);\r\n }\r\n\r\n return result; \r\n}\r\n\r\nvar print_matrix = function(matrix){\r\n for (var i = 0; i < matrix.length; i++) {\r\n var row = '';\r\n for (var j = 0; j < matrix[0].length; j++) {\r\n row += (' ' + matrix[i][j]);\r\n }\r\n\r\n console.log(row);\r\n }\r\n}\r\n\r\nvar main = function (context, myBlob) {\r\n var seed = 123;\r\n var value_min = 0;\r\n var value_max = 101;\r\n var size = parseInt(myBlob);\r\n\r\n var matrix = create_random_matrix(size, seed, value_min, value_max);\r\n seed = 2 * seed;\r\n var matrix2 = create_random_matrix(size, seed, value_min, value_max);\r\n multiple_matrix(matrix, matrix2);\r\n}\r\n"
82 | },
83 | "config": {
84 | "bindings": [
85 | {
86 | "type": "blobTrigger",
87 | "name": "myBlob",
88 | "path": "mycontainer/{name}",
89 | "direction": "in"
90 | },
91 | {
92 | "type": "blobTrigger",
93 | "name": "myQueue",
94 | "path": "myresultcontainer/{name}",
95 | "direction": "out"
96 | }
97 | ]
98 | }
99 | }
100 | }
101 | ],
102 | "type": "Microsoft.Web/sites"
103 | }
104 | ],
105 | "variables": {
106 | "functionAppName": "[concat('blob-nodejs-cpu-intensive', uniquestring(resourceGroup().id))]",
107 | "functionName": "function",
108 | "hostingPlanName": "[concat('blob-nodejs-cpu-intensive', uniquestring(resourceGroup().id))]",
109 | "storageAccountName": "[concat(uniquestring(resourceGroup().id), 'azfunctions')]"
110 | }
111 | }
--------------------------------------------------------------------------------
/SampleUsages/TestSamples/Blob-NodeJs-CPUIntensive/function.json:
--------------------------------------------------------------------------------
1 | {
2 | "bindings": [
3 | {
4 | "type": "blobTrigger",
5 | "name": "myBlob",
6 | "path": "mycontainer/{name}",
7 | "direction": "in"
8 | },
9 | {
10 | "type": "blobTrigger",
11 | "name": "myQueue",
12 | "path": "myresultcontainer/{name}",
13 | "direction": "out"
14 | }
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/SampleUsages/TestSamples/Blob-NodeJs-CPUIntensive/index.js:
--------------------------------------------------------------------------------
1 | // function is triggered by queue input. Input ia a number and function generates to random square matixes of input x input size
2 | // then in multiplies matrixes, prints "Finish." when calculation is done.
3 | // This operation is very heavily using CPU resources, concurrent executions on single container cause function to execute slower
4 |
5 | module.exports = function (context, myBlob) {
6 | main(context, myBlob);
7 | context.done();
8 | }
9 |
10 | var multiple_row_and_column = function(row, column){
11 | // assume same length of row and column
12 | var result = 0;
13 | for(var i = 0; i < row.length; i++)
14 | {
15 | result += row[i] * column[i];
16 | }
17 |
18 | return result;
19 | }
20 |
21 | var create_random_matrix = function(size, seed, value_min, value_max) {
22 | var matrix = [];
23 |
24 | for (var i = 0; i < size; i++) {
25 | var row = [];
26 | for (var j = 0; j < size; j++){
27 | var val = parseInt(Math.random(seed) * (value_max - value_min), 10);
28 | row.push(val);
29 | }
30 |
31 | matrix.push(row);
32 | }
33 |
34 | return matrix;
35 | }
36 |
37 | var get_row_from_matrix = function(matrix, i){
38 | return matrix[i];
39 | }
40 |
41 | var get_column_from_matrix = function(matrix, j){
42 | var column = [];
43 | for(var i = 0; i < matrix.length; i++){
44 | column.push(matrix[i][j]);
45 | }
46 |
47 | return column;
48 | }
49 |
50 | var multiple_matrix = function(matrixA, matrixB) {
51 | var result = [];
52 |
53 | for (var i = 0; i < matrixA.length; i++) {
54 | var result_row = [];
55 | for (var j = 0; j < matrixA[0].length; j++) {
56 | var row = get_row_from_matrix(matrixA, i);
57 | var column = get_column_from_matrix(matrixB, j);
58 | result_row.push(multiple_row_and_column(row, column));
59 | }
60 | result.push(result_row);
61 | }
62 |
63 | return result;
64 | }
65 |
66 | var print_matrix = function(matrix){
67 | for (var i = 0; i < matrix.length; i++) {
68 | var row = '';
69 | for (var j = 0; j < matrix[0].length; j++) {
70 | row += (' ' + matrix[i][j]);
71 | }
72 |
73 | console.log(row);
74 | }
75 | }
76 |
77 | var main = function (context, myBlob) {
78 | var seed = 123;
79 | var value_min = 0;
80 | var value_max = 101;
81 | var size = parseInt(myBlob);
82 |
83 | var matrix = create_random_matrix(size, seed, value_min, value_max);
84 | seed = 2 * seed;
85 | var matrix2 = create_random_matrix(size, seed, value_min, value_max);
86 | multiple_matrix(matrix, matrix2);
87 | }
--------------------------------------------------------------------------------
/SampleUsages/TestSamples/Blob-NodeJs-HighMemory/azuredeploy.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://schemas.management.azure.com/schemas/2015-01-01-preview/deploymentTemplate.json#",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "storageAccountType": {
6 | "allowedValues": [
7 | "Standard_LRS",
8 | "Standard_GRS",
9 | "Standard_ZRS",
10 | "Premium_LRS"
11 | ],
12 | "defaultValue": "Standard_LRS",
13 | "metadata": {
14 | "description": "Storage Account type"
15 | },
16 | "type": "string"
17 | }
18 | },
19 | "resources": [
20 | {
21 | "apiVersion": "2015-06-15",
22 | "location": "[resourceGroup().location]",
23 | "name": "[variables('storageAccountName')]",
24 | "properties": {
25 | "accountType": "[parameters('storageAccountType')]"
26 | },
27 | "type": "Microsoft.Storage/storageAccounts"
28 | },
29 | {
30 | "apiVersion": "2015-04-01",
31 | "location": "[resourceGroup().location]",
32 | "name": "[variables('hostingPlanName')]",
33 | "properties": {
34 | "computeMode": "Dynamic",
35 | "name": "[variables('hostingPlanName')]",
36 | "sku": "Dynamic"
37 | },
38 | "type": "Microsoft.Web/serverfarms"
39 | },
40 | {
41 | "apiVersion": "2015-08-01",
42 | "dependsOn": [
43 | "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]",
44 | "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
45 | ],
46 | "kind": "functionapp",
47 | "location": "[resourceGroup().location]",
48 | "name": "[variables('functionAppName')]",
49 | "properties": {
50 | "name": "[variables('functionAppName')]",
51 | "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]"
52 | },
53 | "resources": [
54 | {
55 | "apiVersion": "2016-03-01",
56 | "dependsOn": [
57 | "[resourceId('Microsoft.Web/sites', variables('functionAppName'))]",
58 | "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
59 | ],
60 | "name": "appsettings",
61 | "properties": {
62 | "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING" : "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listkeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2015-05-01-preview').key1,';')]",
63 | "WEBSITE_CONTENTSHARE" : "[concat(variables('functionAppName'))]",
64 | "AzureWebJobsDashboard": "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listkeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2015-05-01-preview').key1,';')]",
65 | "AzureWebJobsStorage": "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listkeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2015-05-01-preview').key1,';')]",
66 | "FUNCTIONS_EXTENSION_VERSION": "~0.3"
67 | },
68 | "type": "config"
69 | },
70 | {
71 | "apiVersion": "2016-03-01",
72 | "dependsOn": [
73 | "[resourceId('Microsoft.Web/sites', variables('functionAppName'))]",
74 | "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
75 | ],
76 | "name": "[concat(variables('functionAppName'), '/', variables('functionName'))]",
77 | "type": "Microsoft.Web/sites/functions",
78 | "properties": {
79 | "files": {
80 | "index.js": "// function is designed to allocate big array depending on input size\r\n\r\nmodule.exports = function (context, myBlob) {\r\n var array = [];\r\n var size = parseInt(myBlob);\r\n var seed = size;\r\n\r\n for(var i = 0; i < size; i++){\r\n var x = Math.random(seed) * size;\r\n array.push(x);\r\n }\r\n\r\n for(var j = 1; j < size; j++){\r\n var y = Math.random(seed) * size;\r\n array[j] = array[j - 1] + y;\r\n }\r\n \r\n context.done();\r\n}\r\n"
81 | },
82 | "config": {
83 | "bindings": [
84 | {
85 | "type": "blobTrigger",
86 | "name": "myBlob",
87 | "path": "mycontainer/{name}",
88 | "direction": "in"
89 | },
90 | {
91 | "type": "blobTrigger",
92 | "name": "myQueue",
93 | "path": "myresultcontainer/{name}",
94 | "direction": "out"
95 | }
96 | ]
97 | }
98 | }
99 | }
100 | ],
101 | "type": "Microsoft.Web/sites"
102 | }
103 | ],
104 | "variables": {
105 | "functionAppName": "[concat('blob-nodejs-memory-intensive', uniquestring(resourceGroup().id))]",
106 | "functionName": "function",
107 | "hostingPlanName": "[concat('blob-nodejs-memory-intensive', uniquestring(resourceGroup().id))]",
108 | "storageAccountName": "[concat(uniquestring(resourceGroup().id), 'azfunctions')]"
109 | }
110 | }
--------------------------------------------------------------------------------
/SampleUsages/TestSamples/Blob-NodeJs-HighMemory/function.json:
--------------------------------------------------------------------------------
1 | {
2 | "bindings": [
3 | {
4 | "type": "httpTrigger",
5 | "name": "req",
6 | "authLevel": "function",
7 | "direction": "in"
8 | }
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/SampleUsages/TestSamples/Blob-NodeJs-HighMemory/index.js:
--------------------------------------------------------------------------------
1 | // function is designed to allocate big array depending on input size
2 |
3 | module.exports = function (context, myBlob) {
4 | var array = [];
5 | var size = parseInt(myBlob);
6 | var seed = size;
7 |
8 | for(var i = 0; i < size; i++){
9 | var x = Math.random(seed) * size;
10 | array.push(x);
11 | }
12 |
13 | for(var j = 1; j < size; j++){
14 | var y = Math.random(seed) * size;
15 | array[j] = array[j - 1] + y;
16 | }
17 |
18 | context.done();
19 | }
--------------------------------------------------------------------------------
/SampleUsages/TestSamples/Blob-NodeJs-LowUsage/azuredeploy.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://schemas.management.azure.com/schemas/2015-01-01-preview/deploymentTemplate.json#",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "storageAccountType": {
6 | "allowedValues": [
7 | "Standard_LRS",
8 | "Standard_GRS",
9 | "Standard_ZRS",
10 | "Premium_LRS"
11 | ],
12 | "defaultValue": "Standard_LRS",
13 | "metadata": {
14 | "description": "Storage Account type"
15 | },
16 | "type": "string"
17 | }
18 | },
19 | "resources": [
20 | {
21 | "apiVersion": "2015-06-15",
22 | "location": "[resourceGroup().location]",
23 | "name": "[variables('storageAccountName')]",
24 | "properties": {
25 | "accountType": "[parameters('storageAccountType')]"
26 | },
27 | "type": "Microsoft.Storage/storageAccounts"
28 | },
29 | {
30 | "apiVersion": "2015-04-01",
31 | "location": "[resourceGroup().location]",
32 | "name": "[variables('hostingPlanName')]",
33 | "properties": {
34 | "computeMode": "Dynamic",
35 | "name": "[variables('hostingPlanName')]",
36 | "sku": "Dynamic"
37 | },
38 | "type": "Microsoft.Web/serverfarms"
39 | },
40 | {
41 | "apiVersion": "2015-08-01",
42 | "dependsOn": [
43 | "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]",
44 | "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
45 | ],
46 | "kind": "functionapp",
47 | "location": "[resourceGroup().location]",
48 | "name": "[variables('functionAppName')]",
49 | "properties": {
50 | "name": "[variables('functionAppName')]",
51 | "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]"
52 | },
53 | "resources": [
54 | {
55 | "apiVersion": "2016-03-01",
56 | "dependsOn": [
57 | "[resourceId('Microsoft.Web/sites', variables('functionAppName'))]",
58 | "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
59 | ],
60 | "name": "appsettings",
61 | "properties": {
62 | "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING" : "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listkeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2015-05-01-preview').key1,';')]",
63 | "WEBSITE_CONTENTSHARE" : "[concat(variables('functionAppName'))]",
64 | "AzureWebJobsDashboard": "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listkeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2015-05-01-preview').key1,';')]",
65 | "AzureWebJobsStorage": "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listkeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2015-05-01-preview').key1,';')]",
66 | "FUNCTIONS_EXTENSION_VERSION": "~0.3"
67 | },
68 | "type": "config"
69 | },
70 | {
71 | "apiVersion": "2016-03-01",
72 | "dependsOn": [
73 | "[resourceId('Microsoft.Web/sites', variables('functionAppName'))]",
74 | "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
75 | ],
76 | "name": "[concat(variables('functionAppName'), '/', variables('functionName'))]",
77 | "type": "Microsoft.Web/sites/functions",
78 | "properties": {
79 | "files": {
80 | "index.js": "// function has low usage gets message, reads it count to 1000 and finishes\r\n\r\nmodule.exports = function (context, myBlob) {\r\n context.log(\"Function started with input \" + myBlob);\r\n\r\n for(var i = 0; i < 1000; i++){\r\n context.log(i);\r\n }\r\n \r\n context.done();\r\n}\r\n"
81 | },
82 | "config": {
83 | "bindings": [
84 | {
85 | "type": "blobTrigger",
86 | "name": "myBlob",
87 | "path": "mycontainer/{name}",
88 | "direction": "in"
89 | },
90 | {
91 | "type": "blobTrigger",
92 | "name": "myQueue",
93 | "path": "myresultcontainer/{name}",
94 | "direction": "out"
95 | }
96 | ]
97 | }
98 | }
99 | }
100 | ],
101 | "type": "Microsoft.Web/sites"
102 | }
103 | ],
104 | "variables": {
105 | "functionAppName": "[concat('blob-nodejs-low-usage', uniquestring(resourceGroup().id))]",
106 | "functionName": "function",
107 | "hostingPlanName": "[concat('blob-nodejs-low-usage', uniquestring(resourceGroup().id))]",
108 | "storageAccountName": "[concat(uniquestring(resourceGroup().id), 'azfunctions')]"
109 | }
110 | }
--------------------------------------------------------------------------------
/SampleUsages/TestSamples/Blob-NodeJs-LowUsage/function.json:
--------------------------------------------------------------------------------
1 | {
2 | "bindings": [
3 | {
4 | "type": "httpTrigger",
5 | "name": "req",
6 | "authLevel": "function",
7 | "direction": "in"
8 | }
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/SampleUsages/TestSamples/Blob-NodeJs-LowUsage/index.js:
--------------------------------------------------------------------------------
1 | // function has low usage gets message, reads it count to 1000 and finishes
2 |
3 | module.exports = function (context, myBlob) {
4 | context.log("Function started with input " + myBlob);
5 |
6 | for(var i = 0; i < 1000; i++){
7 | context.log(i);
8 | }
9 |
10 | context.done();
11 | }
--------------------------------------------------------------------------------
/SampleUsages/TestSamples/Http-NodeJs-CPUIntensive/azuredeploy.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://schemas.management.azure.com/schemas/2015-01-01-preview/deploymentTemplate.json#",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "storageAccountType": {
6 | "allowedValues": [
7 | "Standard_LRS",
8 | "Standard_GRS",
9 | "Standard_ZRS",
10 | "Premium_LRS"
11 | ],
12 | "defaultValue": "Standard_LRS",
13 | "metadata": {
14 | "description": "Storage Account type"
15 | },
16 | "type": "string"
17 | }
18 | },
19 | "resources": [
20 | {
21 | "apiVersion": "2015-06-15",
22 | "location": "[resourceGroup().location]",
23 | "name": "[variables('storageAccountName')]",
24 | "properties": {
25 | "accountType": "[parameters('storageAccountType')]"
26 | },
27 | "type": "Microsoft.Storage/storageAccounts"
28 | },
29 | {
30 | "apiVersion": "2015-04-01",
31 | "location": "[resourceGroup().location]",
32 | "name": "[variables('hostingPlanName')]",
33 | "properties": {
34 | "computeMode": "Dynamic",
35 | "name": "[variables('hostingPlanName')]",
36 | "sku": "Dynamic"
37 | },
38 | "type": "Microsoft.Web/serverfarms"
39 | },
40 | {
41 | "apiVersion": "2015-08-01",
42 | "dependsOn": [
43 | "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]",
44 | "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
45 | ],
46 | "kind": "functionapp",
47 | "location": "[resourceGroup().location]",
48 | "name": "[variables('functionAppName')]",
49 | "properties": {
50 | "name": "[variables('functionAppName')]",
51 | "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]"
52 | },
53 | "resources": [
54 | {
55 | "apiVersion": "2016-03-01",
56 | "dependsOn": [
57 | "[resourceId('Microsoft.Web/sites', variables('functionAppName'))]",
58 | "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
59 | ],
60 | "name": "appsettings",
61 | "properties": {
62 | "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING" : "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listkeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2015-05-01-preview').key1,';')]",
63 | "WEBSITE_CONTENTSHARE" : "[concat(variables('functionAppName'))]",
64 | "AzureWebJobsDashboard": "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listkeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2015-05-01-preview').key1,';')]",
65 | "AzureWebJobsStorage": "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listkeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2015-05-01-preview').key1,';')]",
66 | "FUNCTIONS_EXTENSION_VERSION": "~0.3"
67 | },
68 | "type": "config"
69 | },
70 | {
71 | "apiVersion": "2016-03-01",
72 | "dependsOn": [
73 | "[resourceId('Microsoft.Web/sites', variables('functionAppName'))]",
74 | "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
75 | ],
76 | "name": "[concat(variables('functionAppName'), '/', variables('functionName'))]",
77 | "type": "Microsoft.Web/sites/functions",
78 | "properties": {
79 | "files":
80 | {
81 | "index.js": "// function is triggered by queue input. Input ia a number and function generates to random square matixes of input x input size\r\n// then in multiplies matrixes, prints \"Finish.\" when calculation is done.\r\n// This operation is very heavily using CPU resources, concurrent executions on single container cause function to execute slower\r\n\r\nmodule.exports = function (context, req) {\r\n main(context, req);\r\n context.done();\r\n}\r\n\r\nvar multiple_row_and_column = function(row, column){\r\n // assume same length of row and column\r\n var result = 0;\r\n for(var i = 0; i < row.length; i++)\r\n {\r\n result += row[i] * column[i];\r\n }\r\n\r\n return result;\r\n}\r\n\r\nvar create_random_matrix = function(size, seed, value_min, value_max) {\r\n var matrix = [];\r\n\r\n for (var i = 0; i < size; i++) {\r\n var row = [];\r\n for (var j = 0; j < size; j++){\r\n var val = parseInt(Math.random(seed) * (value_max - value_min), 10);\r\n row.push(val);\r\n }\r\n\r\n matrix.push(row);\r\n }\r\n\r\n return matrix;\r\n}\r\n\r\nvar get_row_from_matrix = function(matrix, i){\r\n return matrix[i];\r\n}\r\n\r\nvar get_column_from_matrix = function(matrix, j){\r\n var column = [];\r\n for(var i = 0; i < matrix.length; i++){\r\n column.push(matrix[i][j]);\r\n }\r\n\r\n return column;\r\n}\r\n\r\nvar multiple_matrix = function(matrixA, matrixB) {\r\n var result = [];\r\n\r\n for (var i = 0; i < matrixA.length; i++) {\r\n var result_row = [];\r\n for (var j = 0; j < matrixA[0].length; j++) {\r\n var row = get_row_from_matrix(matrixA, i);\r\n var column = get_column_from_matrix(matrixB, j);\r\n result_row.push(multiple_row_and_column(row, column));\r\n }\r\n result.push(result_row);\r\n }\r\n\r\n return result; \r\n}\r\n\r\nvar print_matrix = function(matrix){\r\n for (var i = 0; i < matrix.length; i++) {\r\n var row = '';\r\n for (var j = 0; j < matrix[0].length; j++) {\r\n row += (' ' + matrix[i][j]);\r\n }\r\n\r\n console.log(row);\r\n }\r\n}\r\n\r\nvar main = function (context, req) {\r\n var seed = 123;\r\n var value_min = 0;\r\n var value_max = 101;\r\n var size = parseInt(req.body);\r\n\r\n var matrix = create_random_matrix(size, seed, value_min, value_max);\r\n seed = 2 * seed;\r\n var matrix2 = create_random_matrix(size, seed, value_min, value_max);\r\n multiple_matrix(matrix, matrix2);\r\n}\r\n"
82 | },
83 | "config": {
84 | "bindings": [
85 | {
86 | "type": "httpTrigger",
87 | "name": "req",
88 | "authLevel": "function",
89 | "direction": "in"
90 | }
91 | ]
92 | }
93 | }
94 | }
95 | ],
96 | "type": "Microsoft.Web/sites"
97 | }
98 | ],
99 | "variables": {
100 | "functionAppName": "[concat('http-nodejs-cpu-intensive', uniquestring(resourceGroup().id))]",
101 | "functionName": "function",
102 | "hostingPlanName": "[concat('http-nodejs-cpu-intensive', uniquestring(resourceGroup().id))]",
103 | "storageAccountName": "[concat(uniquestring(resourceGroup().id), 'azfunctions')]"
104 | }
105 | }
--------------------------------------------------------------------------------
/SampleUsages/TestSamples/Http-NodeJs-CPUIntensive/function.json:
--------------------------------------------------------------------------------
1 | {
2 | "bindings": [
3 | {
4 | "type": "httpTrigger",
5 | "name": "req",
6 | "authLevel": "function",
7 | "direction": "in"
8 | }
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/SampleUsages/TestSamples/Http-NodeJs-CPUIntensive/index.js:
--------------------------------------------------------------------------------
1 | // function is triggered by queue input. Input ia a number and function generates to random square matixes of input x input size
2 | // then in multiplies matrixes, prints "Finish." when calculation is done.
3 | // This operation is very heavily using CPU resources, concurrent executions on single container cause function to execute slower
4 |
5 | module.exports = function (context, req) {
6 | main(context, req);
7 | context.done();
8 | }
9 |
10 | var multiple_row_and_column = function(row, column){
11 | // assume same length of row and column
12 | var result = 0;
13 | for(var i = 0; i < row.length; i++)
14 | {
15 | result += row[i] * column[i];
16 | }
17 |
18 | return result;
19 | }
20 |
21 | var create_random_matrix = function(size, seed, value_min, value_max) {
22 | var matrix = [];
23 |
24 | for (var i = 0; i < size; i++) {
25 | var row = [];
26 | for (var j = 0; j < size; j++){
27 | var val = parseInt(Math.random(seed) * (value_max - value_min), 10);
28 | row.push(val);
29 | }
30 |
31 | matrix.push(row);
32 | }
33 |
34 | return matrix;
35 | }
36 |
37 | var get_row_from_matrix = function(matrix, i){
38 | return matrix[i];
39 | }
40 |
41 | var get_column_from_matrix = function(matrix, j){
42 | var column = [];
43 | for(var i = 0; i < matrix.length; i++){
44 | column.push(matrix[i][j]);
45 | }
46 |
47 | return column;
48 | }
49 |
50 | var multiple_matrix = function(matrixA, matrixB) {
51 | var result = [];
52 |
53 | for (var i = 0; i < matrixA.length; i++) {
54 | var result_row = [];
55 | for (var j = 0; j < matrixA[0].length; j++) {
56 | var row = get_row_from_matrix(matrixA, i);
57 | var column = get_column_from_matrix(matrixB, j);
58 | result_row.push(multiple_row_and_column(row, column));
59 | }
60 | result.push(result_row);
61 | }
62 |
63 | return result;
64 | }
65 |
66 | var print_matrix = function(matrix){
67 | for (var i = 0; i < matrix.length; i++) {
68 | var row = '';
69 | for (var j = 0; j < matrix[0].length; j++) {
70 | row += (' ' + matrix[i][j]);
71 | }
72 |
73 | console.log(row);
74 | }
75 | }
76 |
77 | var main = function (context, req) {
78 | var seed = 123;
79 | var value_min = 0;
80 | var value_max = 101;
81 | var size = parseInt(req.body);
82 |
83 | var matrix = create_random_matrix(size, seed, value_min, value_max);
84 | seed = 2 * seed;
85 | var matrix2 = create_random_matrix(size, seed, value_min, value_max);
86 | multiple_matrix(matrix, matrix2);
87 | }
--------------------------------------------------------------------------------
/SampleUsages/TestSamples/Http-NodeJs-HighMemory/azuredeploy.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://schemas.management.azure.com/schemas/2015-01-01-preview/deploymentTemplate.json#",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "storageAccountType": {
6 | "allowedValues": [
7 | "Standard_LRS",
8 | "Standard_GRS",
9 | "Standard_ZRS",
10 | "Premium_LRS"
11 | ],
12 | "defaultValue": "Standard_LRS",
13 | "metadata": {
14 | "description": "Storage Account type"
15 | },
16 | "type": "string"
17 | }
18 | },
19 | "resources": [
20 | {
21 | "apiVersion": "2015-06-15",
22 | "location": "[resourceGroup().location]",
23 | "name": "[variables('storageAccountName')]",
24 | "properties": {
25 | "accountType": "[parameters('storageAccountType')]"
26 | },
27 | "type": "Microsoft.Storage/storageAccounts"
28 | },
29 | {
30 | "apiVersion": "2015-04-01",
31 | "location": "[resourceGroup().location]",
32 | "name": "[variables('hostingPlanName')]",
33 | "properties": {
34 | "computeMode": "Dynamic",
35 | "name": "[variables('hostingPlanName')]",
36 | "sku": "Dynamic"
37 | },
38 | "type": "Microsoft.Web/serverfarms"
39 | },
40 | {
41 | "apiVersion": "2015-08-01",
42 | "dependsOn": [
43 | "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]",
44 | "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
45 | ],
46 | "kind": "functionapp",
47 | "location": "[resourceGroup().location]",
48 | "name": "[variables('functionAppName')]",
49 | "properties": {
50 | "name": "[variables('functionAppName')]",
51 | "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]"
52 | },
53 | "resources": [
54 | {
55 | "apiVersion": "2016-03-01",
56 | "dependsOn": [
57 | "[resourceId('Microsoft.Web/sites', variables('functionAppName'))]",
58 | "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
59 | ],
60 | "name": "appsettings",
61 | "properties": {
62 | "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING" : "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listkeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2015-05-01-preview').key1,';')]",
63 | "WEBSITE_CONTENTSHARE" : "[concat(variables('functionAppName'))]",
64 | "AzureWebJobsDashboard": "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listkeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2015-05-01-preview').key1,';')]",
65 | "AzureWebJobsStorage": "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listkeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2015-05-01-preview').key1,';')]",
66 | "FUNCTIONS_EXTENSION_VERSION": "~0.3"
67 | },
68 | "type": "config"
69 | },
70 | {
71 | "apiVersion": "2016-03-01",
72 | "dependsOn": [
73 | "[resourceId('Microsoft.Web/sites', variables('functionAppName'))]",
74 | "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
75 | ],
76 | "name": "[concat(variables('functionAppName'), '/', variables('functionName'))]",
77 | "type": "Microsoft.Web/sites/functions",
78 | "properties": {
79 | "files": {
80 | "index.js": "// function is designed to allocate big array depending on input size\r\n\r\nmodule.exports = function (context, req) {\r\n var array = [];\r\n var size = parseInt(req.body);\r\n var seed = size;\r\n\r\n for(var i = 0; i < size; i++){\r\n var x = Math.random(seed) * size;\r\n array.push(x);\r\n }\r\n\r\n for(var j = 1; j < size; j++){\r\n var y = Math.random(seed) * size;\r\n array[j] = array[j - 1] + y;\r\n }\r\n \r\n context.done();\r\n}\r\n"
81 | },
82 | "config": {
83 | "bindings": [
84 | {
85 | "type": "httpTrigger",
86 | "name": "req",
87 | "authLevel": "function",
88 | "direction": "in"
89 | }
90 | ]
91 | }
92 | }
93 | }
94 | ],
95 | "type": "Microsoft.Web/sites"
96 | }
97 | ],
98 | "variables": {
99 | "functionAppName": "[concat('http-nodejs-memory-intensive', uniquestring(resourceGroup().id))]",
100 | "functionName": "function",
101 | "hostingPlanName": "[concat('http-nodejs-memory-intensive', uniquestring(resourceGroup().id))]",
102 | "storageAccountName": "[concat(uniquestring(resourceGroup().id), 'azfunctions')]"
103 | }
104 | }
--------------------------------------------------------------------------------
/SampleUsages/TestSamples/Http-NodeJs-HighMemory/function.json:
--------------------------------------------------------------------------------
1 | {
2 | "bindings": [
3 | {
4 | "type": "httpTrigger",
5 | "name": "req",
6 | "authLevel": "function",
7 | "direction": "in"
8 | }
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/SampleUsages/TestSamples/Http-NodeJs-HighMemory/index.js:
--------------------------------------------------------------------------------
1 | // function is designed to allocate big array depending on input size
2 |
3 | module.exports = function (context, req) {
4 | var array = [];
5 | var size = parseInt(req.body);
6 | var seed = size;
7 |
8 | for(var i = 0; i < size; i++){
9 | var x = Math.random(seed) * size;
10 | array.push(x);
11 | }
12 |
13 | for(var j = 1; j < size; j++){
14 | var y = Math.random(seed) * size;
15 | array[j] = array[j - 1] + y;
16 | }
17 |
18 | context.done();
19 | }
--------------------------------------------------------------------------------
/SampleUsages/TestSamples/Http-NodeJs-LowUsage/azuredeploy.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://schemas.management.azure.com/schemas/2015-01-01-preview/deploymentTemplate.json#",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "storageAccountType": {
6 | "allowedValues": [
7 | "Standard_LRS",
8 | "Standard_GRS",
9 | "Standard_ZRS",
10 | "Premium_LRS"
11 | ],
12 | "defaultValue": "Standard_LRS",
13 | "metadata": {
14 | "description": "Storage Account type"
15 | },
16 | "type": "string"
17 | }
18 | },
19 | "resources": [
20 | {
21 | "apiVersion": "2015-06-15",
22 | "location": "[resourceGroup().location]",
23 | "name": "[variables('storageAccountName')]",
24 | "properties": {
25 | "accountType": "[parameters('storageAccountType')]"
26 | },
27 | "type": "Microsoft.Storage/storageAccounts"
28 | },
29 | {
30 | "apiVersion": "2015-04-01",
31 | "location": "[resourceGroup().location]",
32 | "name": "[variables('hostingPlanName')]",
33 | "properties": {
34 | "computeMode": "Dynamic",
35 | "name": "[variables('hostingPlanName')]",
36 | "sku": "Dynamic"
37 | },
38 | "type": "Microsoft.Web/serverfarms"
39 | },
40 | {
41 | "apiVersion": "2015-08-01",
42 | "dependsOn": [
43 | "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]",
44 | "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
45 | ],
46 | "kind": "functionapp",
47 | "location": "[resourceGroup().location]",
48 | "name": "[variables('functionAppName')]",
49 | "properties": {
50 | "name": "[variables('functionAppName')]",
51 | "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]"
52 | },
53 | "resources": [
54 | {
55 | "apiVersion": "2016-03-01",
56 | "dependsOn": [
57 | "[resourceId('Microsoft.Web/sites', variables('functionAppName'))]",
58 | "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
59 | ],
60 | "name": "appsettings",
61 | "properties": {
62 | "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING" : "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listkeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2015-05-01-preview').key1,';')]",
63 | "WEBSITE_CONTENTSHARE" : "[concat(variables('functionAppName'))]",
64 | "AzureWebJobsDashboard": "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listkeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2015-05-01-preview').key1,';')]",
65 | "AzureWebJobsStorage": "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listkeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2015-05-01-preview').key1,';')]",
66 | "FUNCTIONS_EXTENSION_VERSION": "~0.3"
67 | },
68 | "type": "config"
69 | },
70 | {
71 | "apiVersion": "2016-03-01",
72 | "dependsOn": [
73 | "[resourceId('Microsoft.Web/sites', variables('functionAppName'))]",
74 | "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
75 | ],
76 | "name": "[concat(variables('functionAppName'), '/', variables('functionName'))]",
77 | "type": "Microsoft.Web/sites/functions",
78 | "properties": {
79 | "files": {
80 | "index.js": "// function has low usage gets message, reads it count to 1000 and finishes\r\n\r\nmodule.exports = function (context, req) {\r\n context.log(\"Function started with input \" + req.rawBody);\r\n\r\n for(var i = 0; i < 1000; i++){\r\n context.log(i);\r\n }\r\n \r\n context.done();\r\n}\r\n"
81 | },
82 | "config": {
83 | "bindings": [
84 | {
85 | "type": "httpTrigger",
86 | "name": "req",
87 | "authLevel": "function",
88 | "direction": "in"
89 | }
90 | ]
91 | }
92 | }
93 | }
94 | ],
95 | "type": "Microsoft.Web/sites"
96 | }
97 | ],
98 | "variables": {
99 | "functionAppName": "[concat('http-nodejs-low-usage', uniquestring(resourceGroup().id))]",
100 | "functionName": "function",
101 | "hostingPlanName": "[concat('http-nodejs-low-usage', uniquestring(resourceGroup().id))]",
102 | "storageAccountName": "[concat(uniquestring(resourceGroup().id), 'azfunctions')]"
103 | }
104 | }
--------------------------------------------------------------------------------
/SampleUsages/TestSamples/Http-NodeJs-LowUsage/function.json:
--------------------------------------------------------------------------------
1 | {
2 | "bindings": [
3 | {
4 | "type": "httpTrigger",
5 | "name": "req",
6 | "authLevel": "function",
7 | "direction": "in"
8 | }
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/SampleUsages/TestSamples/Http-NodeJs-LowUsage/index.js:
--------------------------------------------------------------------------------
1 | // function has low usage gets message, reads it count to 1000 and finishes
2 |
3 | module.exports = function (context, req) {
4 | context.log("Function started with input " + req.rawBody);
5 |
6 | for(var i = 0; i < 1000; i++){
7 | context.log(i);
8 | }
9 |
10 | context.done();
11 | }
--------------------------------------------------------------------------------
/SampleUsages/TestSamples/Queue-NodeJs-CPUIntensive/azuredep.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://schemas.management.azure.com/schemas/2015-01-01-preview/deploymentTemplate.json#",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "appName": {
6 | "type": "string",
7 | "metadata": {
8 | "description": "The name of the function app that you wish to create."
9 | }
10 | },
11 | "storageAccountType": {
12 | "type": "string",
13 | "defaultValue": "Standard_LRS",
14 | "allowedValues": [
15 | "Standard_LRS",
16 | "Standard_GRS",
17 | "Standard_ZRS",
18 | "Premium_LRS"
19 | ],
20 | "metadata": {
21 | "description": "Storage Account type"
22 | }
23 | }
24 | },
25 | "variables": {
26 | "functionAppName": "[parameters('appName')]",
27 | "hostingPlanName": "[parameters('appName')]",
28 | "storageAccountName": "[concat(uniquestring(resourceGroup().id), 'azfunctions')]"
29 | },
30 | "resources": [
31 | {
32 | "type": "Microsoft.Storage/storageAccounts",
33 | "name": "[variables('storageAccountName')]",
34 | "apiVersion": "2015-06-15",
35 | "location": "[resourceGroup().location]",
36 | "properties": {
37 | "accountType": "[parameters('storageAccountType')]"
38 | }
39 | },
40 | {
41 | "type": "Microsoft.Web/serverfarms",
42 | "apiVersion": "2015-04-01",
43 | "name": "[variables('hostingPlanName')]",
44 | "location": "[resourceGroup().location]",
45 | "properties": {
46 | "name": "[variables('hostingPlanName')]",
47 | "computeMode": "Dynamic",
48 | "sku": "Dynamic"
49 | }
50 | },
51 | {
52 | "apiVersion": "2015-08-01",
53 | "type": "Microsoft.Web/sites",
54 | "name": "[variables('functionAppName')]",
55 | "location": "[resourceGroup().location]",
56 | "kind": "functionapp",
57 | "properties": {
58 | "name": "[variables('functionAppName')]",
59 | "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]"
60 | },
61 | "dependsOn": [
62 | "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]",
63 | "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
64 | ],
65 | "resources": [
66 | {
67 | "apiVersion": "2016-03-01",
68 | "name": "appsettings",
69 | "type": "config",
70 | "dependsOn": [
71 | "[resourceId('Microsoft.Web/sites', variables('functionAppName'))]",
72 | "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
73 | ],
74 | "properties": {
75 | "AzureWebJobsStorage": "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listkeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2015-05-01-preview').key1,';')]",
76 | "AzureWebJobsDashboard": "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listkeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2015-05-01-preview').key1,';')]",
77 | "FUNCTIONS_EXTENSION_VERSION": "latest"
78 | }
79 | }
80 | ]
81 | }
82 | ]
83 | }
--------------------------------------------------------------------------------
/SampleUsages/TestSamples/Queue-NodeJs-CPUIntensive/azuredeploy.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://schemas.management.azure.com/schemas/2015-01-01-preview/deploymentTemplate.json#",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "storageAccountType": {
6 | "allowedValues": [
7 | "Standard_LRS",
8 | "Standard_GRS",
9 | "Standard_ZRS",
10 | "Premium_LRS"
11 | ],
12 | "defaultValue": "Standard_LRS",
13 | "metadata": {
14 | "description": "Storage Account type"
15 | },
16 | "type": "string"
17 | }
18 | },
19 | "resources": [
20 | {
21 | "apiVersion": "2015-06-15",
22 | "location": "[resourceGroup().location]",
23 | "name": "[variables('storageAccountName')]",
24 | "properties": {
25 | "accountType": "[parameters('storageAccountType')]"
26 | },
27 | "type": "Microsoft.Storage/storageAccounts"
28 | },
29 | {
30 | "apiVersion": "2015-04-01",
31 | "location": "[resourceGroup().location]",
32 | "name": "[variables('hostingPlanName')]",
33 | "properties": {
34 | "computeMode": "Dynamic",
35 | "name": "[variables('hostingPlanName')]",
36 | "sku": "Dynamic"
37 | },
38 | "type": "Microsoft.Web/serverfarms"
39 | },
40 | {
41 | "apiVersion": "2015-08-01",
42 | "dependsOn": [
43 | "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]",
44 | "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
45 | ],
46 | "kind": "functionapp",
47 | "location": "[resourceGroup().location]",
48 | "name": "[variables('functionAppName')]",
49 | "properties": {
50 | "name": "[variables('functionAppName')]",
51 | "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]"
52 | },
53 | "resources": [
54 | {
55 | "apiVersion": "2016-03-01",
56 | "dependsOn": [
57 | "[resourceId('Microsoft.Web/sites', variables('functionAppName'))]",
58 | "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
59 | ],
60 | "name": "appsettings",
61 | "properties": {
62 | "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING" : "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listkeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2015-05-01-preview').key1,';')]",
63 | "WEBSITE_CONTENTSHARE" : "[concat(variables('functionAppName'))]",
64 | "AzureWebJobsDashboard": "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listkeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2015-05-01-preview').key1,';')]",
65 | "AzureWebJobsStorage": "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listkeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2015-05-01-preview').key1,';')]",
66 | "FUNCTIONS_EXTENSION_VERSION": "~0.3"
67 | },
68 | "type": "config"
69 | },
70 | {
71 | "apiVersion": "2016-03-01",
72 | "dependsOn": [
73 | "[resourceId('Microsoft.Web/sites', variables('functionAppName'))]",
74 | "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
75 | ],
76 | "name": "[concat(variables('functionAppName'), '/', variables('functionName'))]",
77 | "type": "Microsoft.Web/sites/functions",
78 | "properties": {
79 | "files":
80 | {
81 | "index.js": "// function is triggered by queue input. Input ia a number and function generates to random square matixes of input x input size\r\n// then in multiplies matrixes, prints \"Finish.\" when calculation is done.\r\n// This operation is very heavily using CPU resources, concurrent executions on single container cause function to execute slower\r\n\r\nmodule.exports = function (context, input) {\r\n main(context, input);\r\n context.done();\r\n }\r\n \r\n var multiple_row_and_column = function(row, column){\r\n // assume same length of row and column\r\n var result = 0;\r\n for(var i = 0; i < row.length; i++)\r\n {\r\n result += row[i] * column[i];\r\n }\r\n \r\n return result;\r\n }\r\n \r\n var create_random_matrix = function(size, seed, value_min, value_max) {\r\n var matrix = [];\r\n \r\n for (var i = 0; i < size; i++) {\r\n var row = [];\r\n for (var j = 0; j < size; j++){\r\n var val = parseInt(Math.random(seed) * (value_max - value_min), 10);\r\n row.push(val);\r\n }\r\n \r\n matrix.push(row);\r\n }\r\n \r\n return matrix;\r\n }\r\n \r\n var get_row_from_matrix = function(matrix, i){\r\n return matrix[i];\r\n }\r\n \r\n var get_column_from_matrix = function(matrix, j){\r\n var column = [];\r\n for(var i = 0; i < matrix.length; i++){\r\n column.push(matrix[i][j]);\r\n }\r\n \r\n return column;\r\n }\r\n \r\n var multiple_matrix = function(matrixA, matrixB) {\r\n var result = [];\r\n \r\n for (var i = 0; i < matrixA.length; i++) {\r\n var result_row = [];\r\n for (var j = 0; j < matrixA[0].length; j++) {\r\n var row = get_row_from_matrix(matrixA, i);\r\n var column = get_column_from_matrix(matrixB, j);\r\n result_row.push(multiple_row_and_column(row, column));\r\n }\r\n result.push(result_row);\r\n }\r\n \r\n return result; \r\n }\r\n \r\n var print_matrix = function(matrix){\r\n for (var i = 0; i < matrix.length; i++) {\r\n var row = '';\r\n for (var j = 0; j < matrix[0].length; j++) {\r\n row += (' ' + matrix[i][j]);\r\n }\r\n \r\n console.log(row);\r\n }\r\n }\r\n \r\n var main = function(context, size) {\r\n var seed = 123;\r\n var value_min = 0;\r\n var value_max = 101;\r\n \r\n var matrix = create_random_matrix(size, seed, value_min, value_max);\r\n seed = 2 * seed;\r\n var matrix2 = create_random_matrix(size, seed, value_min, value_max);\r\n multiple_matrix(matrix, matrix2);\r\n }\r\n"
82 | },
83 | "config": {
84 | "bindings": [
85 | {
86 | "type": "queueTrigger",
87 | "name": "input",
88 | "direction": "in",
89 | "queueName": "samples-node-js-cpu-perf-test"
90 | }]
91 | }
92 | }
93 | }
94 | ],
95 | "type": "Microsoft.Web/sites"
96 | }
97 | ],
98 | "variables": {
99 | "functionAppName": "[concat('queue-nodejs-cpu-intensive', uniquestring(resourceGroup().id))]",
100 | "functionName": "function",
101 | "hostingPlanName": "[concat('queue-nodejs-cpu-intensive', uniquestring(resourceGroup().id))]",
102 | "storageAccountName": "[concat(uniquestring(resourceGroup().id), 'azfunctions')]"
103 | }
104 | }
--------------------------------------------------------------------------------
/SampleUsages/TestSamples/Queue-NodeJs-CPUIntensive/function.json:
--------------------------------------------------------------------------------
1 | {
2 | "bindings": [
3 | {
4 | "type": "queueTrigger",
5 | "name": "input",
6 | "direction": "in",
7 | "queueName": "samples-node-js-cpu-perf-test",
8 | "connection": ""
9 | }
10 | ]
11 | }
12 |
--------------------------------------------------------------------------------
/SampleUsages/TestSamples/Queue-NodeJs-CPUIntensive/index.js:
--------------------------------------------------------------------------------
1 | // function is triggered by queue input. Input ia a number and function generates to random square matixes of input x input size
2 | // then in multiplies matrixes, prints "Finish." when calculation is done.
3 | // This operation is very heavily using CPU resources, concurrent executions on single container cause function to execute slower
4 |
5 | module.exports = function (context, input) {
6 | main(context, input);
7 | context.done();
8 | }
9 |
10 | var multiple_row_and_column = function(row, column){
11 | // assume same length of row and column
12 | var result = 0;
13 | for(var i = 0; i < row.length; i++)
14 | {
15 | result += row[i] * column[i];
16 | }
17 |
18 | return result;
19 | }
20 |
21 | var create_random_matrix = function(size, seed, value_min, value_max) {
22 | var matrix = [];
23 |
24 | for (var i = 0; i < size; i++) {
25 | var row = [];
26 | for (var j = 0; j < size; j++){
27 | var val = parseInt(Math.random(seed) * (value_max - value_min), 10);
28 | row.push(val);
29 | }
30 |
31 | matrix.push(row);
32 | }
33 |
34 | return matrix;
35 | }
36 |
37 | var get_row_from_matrix = function(matrix, i){
38 | return matrix[i];
39 | }
40 |
41 | var get_column_from_matrix = function(matrix, j){
42 | var column = [];
43 | for(var i = 0; i < matrix.length; i++){
44 | column.push(matrix[i][j]);
45 | }
46 |
47 | return column;
48 | }
49 |
50 | var multiple_matrix = function(matrixA, matrixB) {
51 | var result = [];
52 |
53 | for (var i = 0; i < matrixA.length; i++) {
54 | var result_row = [];
55 | for (var j = 0; j < matrixA[0].length; j++) {
56 | var row = get_row_from_matrix(matrixA, i);
57 | var column = get_column_from_matrix(matrixB, j);
58 | result_row.push(multiple_row_and_column(row, column));
59 | }
60 | result.push(result_row);
61 | }
62 |
63 | return result;
64 | }
65 |
66 | var print_matrix = function(matrix){
67 | for (var i = 0; i < matrix.length; i++) {
68 | var row = '';
69 | for (var j = 0; j < matrix[0].length; j++) {
70 | row += (' ' + matrix[i][j]);
71 | }
72 |
73 | console.log(row);
74 | }
75 | }
76 |
77 | var main = function(context, size) {
78 | var seed = 123;
79 | var value_min = 0;
80 | var value_max = 101;
81 |
82 | var matrix = create_random_matrix(size, seed, value_min, value_max);
83 | seed = 2 * seed;
84 | var matrix2 = create_random_matrix(size, seed, value_min, value_max);
85 | multiple_matrix(matrix, matrix2);
86 | }
--------------------------------------------------------------------------------
/SampleUsages/TestSamples/Queue-NodeJs-HighMemory/azuredeploy.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://schemas.management.azure.com/schemas/2015-01-01-preview/deploymentTemplate.json#",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "storageAccountType": {
6 | "allowedValues": [
7 | "Standard_LRS",
8 | "Standard_GRS",
9 | "Standard_ZRS",
10 | "Premium_LRS"
11 | ],
12 | "defaultValue": "Standard_LRS",
13 | "metadata": {
14 | "description": "Storage Account type"
15 | },
16 | "type": "string"
17 | }
18 | },
19 | "resources": [
20 | {
21 | "apiVersion": "2015-06-15",
22 | "location": "[resourceGroup().location]",
23 | "name": "[variables('storageAccountName')]",
24 | "properties": {
25 | "accountType": "[parameters('storageAccountType')]"
26 | },
27 | "type": "Microsoft.Storage/storageAccounts"
28 | },
29 | {
30 | "apiVersion": "2015-04-01",
31 | "location": "[resourceGroup().location]",
32 | "name": "[variables('hostingPlanName')]",
33 | "properties": {
34 | "computeMode": "Dynamic",
35 | "name": "[variables('hostingPlanName')]",
36 | "sku": "Dynamic"
37 | },
38 | "type": "Microsoft.Web/serverfarms"
39 | },
40 | {
41 | "apiVersion": "2015-08-01",
42 | "dependsOn": [
43 | "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]",
44 | "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
45 | ],
46 | "kind": "functionapp",
47 | "location": "[resourceGroup().location]",
48 | "name": "[variables('functionAppName')]",
49 | "properties": {
50 | "name": "[variables('functionAppName')]",
51 | "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]"
52 | },
53 | "resources": [
54 | {
55 | "apiVersion": "2016-03-01",
56 | "dependsOn": [
57 | "[resourceId('Microsoft.Web/sites', variables('functionAppName'))]",
58 | "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
59 | ],
60 | "name": "appsettings",
61 | "properties": {
62 | "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING" : "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listkeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2015-05-01-preview').key1,';')]",
63 | "WEBSITE_CONTENTSHARE" : "[concat(variables('functionAppName'))]",
64 | "AzureWebJobsDashboard": "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listkeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2015-05-01-preview').key1,';')]",
65 | "AzureWebJobsStorage": "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listkeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2015-05-01-preview').key1,';')]",
66 | "FUNCTIONS_EXTENSION_VERSION": "~0.3"
67 | },
68 | "type": "config"
69 | },
70 | {
71 | "apiVersion": "2016-03-01",
72 | "dependsOn": [
73 | "[resourceId('Microsoft.Web/sites', variables('functionAppName'))]",
74 | "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
75 | ],
76 | "name": "[concat(variables('functionAppName'), '/', variables('functionName'))]",
77 | "type": "Microsoft.Web/sites/functions",
78 | "properties": {
79 | "files": {
80 | "index.js": "// function is designed to allocate big array depending on input size\r\n\r\nmodule.exports = function (context, size) {\r\n var array = [];\r\n var seed = size;\r\n\r\n for(var i = 0; i < size; i++){\r\n var x = Math.random(seed) * size;\r\n array.push(x);\r\n }\r\n\r\n for(var j = 1; j < size; j++){\r\n var y = Math.random(seed) * size;\r\n array[j] = array[j - 1] + y;\r\n }\r\n \r\n context.done();\r\n}\r\n"
81 | },
82 | "config": {
83 | "bindings": [
84 | {
85 | "type": "queueTrigger",
86 | "name": "input",
87 | "direction": "in",
88 | "queueName": "samples-node-js-memory-perf-test"
89 | }
90 | ]
91 | }
92 | }
93 | }
94 | ],
95 | "type": "Microsoft.Web/sites"
96 | }
97 | ],
98 | "variables": {
99 | "functionAppName": "[concat('queue-nodejs-memory-intensive', uniquestring(resourceGroup().id))]",
100 | "functionName": "function",
101 | "hostingPlanName": "[concat('queue-nodejs-memory-intensive', uniquestring(resourceGroup().id))]",
102 | "storageAccountName": "[concat(uniquestring(resourceGroup().id), 'azfunctions')]"
103 | }
104 | }
--------------------------------------------------------------------------------
/SampleUsages/TestSamples/Queue-NodeJs-HighMemory/function.json:
--------------------------------------------------------------------------------
1 | {
2 | "bindings": [
3 | {
4 | "type": "queueTrigger",
5 | "name": "input",
6 | "direction": "in",
7 | "queueName": "samples-node-js-memory-perf-test",
8 | "connection": ""
9 | }
10 | ]
11 | }
12 |
--------------------------------------------------------------------------------
/SampleUsages/TestSamples/Queue-NodeJs-HighMemory/index.js:
--------------------------------------------------------------------------------
1 | // function is designed to allocate big array depending on input size
2 |
3 | module.exports = function (context, size) {
4 | var array = [];
5 | var seed = size;
6 |
7 | for(var i = 0; i < size; i++){
8 | var x = Math.random(seed) * size;
9 | array.push(x);
10 | }
11 |
12 | for(var j = 1; j < size; j++){
13 | var y = Math.random(seed) * size;
14 | array[j] = array[j - 1] + y;
15 | }
16 |
17 | context.done();
18 | }
--------------------------------------------------------------------------------
/SampleUsages/TestSamples/Queue-NodeJs-LowUsage/azuredeploy.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://schemas.management.azure.com/schemas/2015-01-01-preview/deploymentTemplate.json#",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "storageAccountType": {
6 | "allowedValues": [
7 | "Standard_LRS",
8 | "Standard_GRS",
9 | "Standard_ZRS",
10 | "Premium_LRS"
11 | ],
12 | "defaultValue": "Standard_LRS",
13 | "metadata": {
14 | "description": "Storage Account type"
15 | },
16 | "type": "string"
17 | }
18 | },
19 | "resources": [
20 | {
21 | "apiVersion": "2015-06-15",
22 | "location": "[resourceGroup().location]",
23 | "name": "[variables('storageAccountName')]",
24 | "properties": {
25 | "accountType": "[parameters('storageAccountType')]"
26 | },
27 | "type": "Microsoft.Storage/storageAccounts"
28 | },
29 | {
30 | "apiVersion": "2015-04-01",
31 | "location": "[resourceGroup().location]",
32 | "name": "[variables('hostingPlanName')]",
33 | "properties": {
34 | "computeMode": "Dynamic",
35 | "name": "[variables('hostingPlanName')]",
36 | "sku": "Dynamic"
37 | },
38 | "type": "Microsoft.Web/serverfarms"
39 | },
40 | {
41 | "apiVersion": "2015-08-01",
42 | "dependsOn": [
43 | "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]",
44 | "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
45 | ],
46 | "kind": "functionapp",
47 | "location": "[resourceGroup().location]",
48 | "name": "[variables('functionAppName')]",
49 | "properties": {
50 | "name": "[variables('functionAppName')]",
51 | "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]"
52 | },
53 | "resources": [
54 | {
55 | "apiVersion": "2016-03-01",
56 | "dependsOn": [
57 | "[resourceId('Microsoft.Web/sites', variables('functionAppName'))]",
58 | "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
59 | ],
60 | "name": "appsettings",
61 | "properties": {
62 | "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING" : "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listkeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2015-05-01-preview').key1,';')]",
63 | "WEBSITE_CONTENTSHARE" : "[concat(variables('functionAppName'))]",
64 | "AzureWebJobsDashboard": "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listkeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2015-05-01-preview').key1,';')]",
65 | "AzureWebJobsStorage": "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listkeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2015-05-01-preview').key1,';')]",
66 | "FUNCTIONS_EXTENSION_VERSION": "~0.3"
67 | },
68 | "type": "config"
69 | },
70 | {
71 | "apiVersion": "2016-03-01",
72 | "dependsOn": [
73 | "[resourceId('Microsoft.Web/sites', variables('functionAppName'))]",
74 | "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
75 | ],
76 | "name": "[concat(variables('functionAppName'), '/', variables('functionName'))]",
77 | "type": "Microsoft.Web/sites/functions",
78 | "properties": {
79 | "files": {
80 | "index.js": "// function has low usage gets message, reads it count to 1000 and finishes\r\n\r\nmodule.exports = function (context, size) {\r\n context.log(\"Function started with input \" + size);\r\n\r\n for(var i = 0; i < 1000; i++){\r\n context.log(i);\r\n }\r\n \r\n context.done();\r\n}\r\n"
81 | },
82 | "config": {
83 | "bindings": [
84 | {
85 | "type": "queueTrigger",
86 | "name": "input",
87 | "direction": "in",
88 | "queueName": "samples-node-js-low-usage-test"
89 | }
90 | ]
91 | }
92 | }
93 | }
94 | ],
95 | "type": "Microsoft.Web/sites"
96 | }
97 | ],
98 | "variables": {
99 | "functionAppName": "[concat('queue-nodejs-low-usage', uniquestring(resourceGroup().id))]",
100 | "functionName": "function",
101 | "hostingPlanName": "[concat('queue-nodejs-low-usage', uniquestring(resourceGroup().id))]",
102 | "storageAccountName": "[concat(uniquestring(resourceGroup().id), 'azfunctions')]"
103 | }
104 | }
--------------------------------------------------------------------------------
/SampleUsages/TestSamples/Queue-NodeJs-LowUsage/function.json:
--------------------------------------------------------------------------------
1 | {
2 | "bindings": [
3 | {
4 | "type": "queueTrigger",
5 | "name": "input",
6 | "direction": "in",
7 | "queueName": "samples-node-js-low-usage-test",
8 | "connection": ""
9 | }
10 | ]
11 | }
12 |
--------------------------------------------------------------------------------
/SampleUsages/TestSamples/Queue-NodeJs-LowUsage/index.js:
--------------------------------------------------------------------------------
1 | // function has low usage gets message, reads it count to 1000 and finishes
2 |
3 | module.exports = function (context, size) {
4 | context.log("Function started with input " + size);
5 |
6 | for(var i = 0; i < 1000; i++){
7 | context.log(i);
8 | }
9 |
10 | context.done();
11 | }
--------------------------------------------------------------------------------
/SampleUsages/TestSamples/README.html:
--------------------------------------------------------------------------------
1 | #Tests samples required to run the according tests.
2 |
3 | ## Queue-Node-Js-CPU-Intensive
4 |
5 |
6 | Function is triggered by queue input. Input ia a number and function generates to random square matixes of input x input size
7 | then in multiplies matrixes, prints "Finish." when calculation is done.
8 | This operation is very heavily using CPU resources, concurrent executions on single container cause function to execute slower
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | ## Queue-Node-Js-High-Memory
20 |
21 |
22 | Function is designed to allocate big array depending on input size.
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | ## Queue-Node-Js-Low-Usage
34 |
35 |
36 | Function has low usage gets message, reads it count to 1000 and finishes.
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/SampleUsages/TestSamples/README.md:
--------------------------------------------------------------------------------
1 | #Tests samples required to run the according tests.
2 |
3 | ## Queue-Node-Js-CPU-Intensive
4 |
5 |
6 | Function is triggered by queue input. Input ia a number and function generates to random square matixes of input x input size
7 | then in multiplies matrixes, prints "Finish." when calculation is done.
8 | This operation is very heavily using CPU resources, concurrent executions on single container cause function to execute slower
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | ## Queue-Node-Js-High-Memory
20 |
21 |
22 | Function is designed to allocate big array depending on input size.
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | ## Queue-Node-Js-Low-Usage
34 |
35 |
36 | Function has low usage gets message, reads it count to 1000 and finishes.
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/SampleUsages/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/ServerlessBenchmark.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2013
4 | VisualStudioVersion = 12.0.40629.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServerlessBenchmark", "ServerlessBenchmark\ServerlessBenchmark.csproj", "{582CC16B-6C75-494B-B27F-7A769DEC0C30}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MiniCommandLineHelper", "MiniCommandLineHelper\MiniCommandLineHelper.csproj", "{600BA962-07EA-46EC-B8F5-9BC5933C5533}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleUsages", "SampleUsages\SampleUsages.csproj", "{6B65B2D7-6344-4B15-A428-483E74E9AF51}"
11 | EndProject
12 | Global
13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
14 | Debug|Any CPU = Debug|Any CPU
15 | Release|Any CPU = Release|Any CPU
16 | EndGlobalSection
17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
18 | {582CC16B-6C75-494B-B27F-7A769DEC0C30}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
19 | {582CC16B-6C75-494B-B27F-7A769DEC0C30}.Debug|Any CPU.Build.0 = Debug|Any CPU
20 | {582CC16B-6C75-494B-B27F-7A769DEC0C30}.Release|Any CPU.ActiveCfg = Release|Any CPU
21 | {582CC16B-6C75-494B-B27F-7A769DEC0C30}.Release|Any CPU.Build.0 = Release|Any CPU
22 | {600BA962-07EA-46EC-B8F5-9BC5933C5533}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
23 | {600BA962-07EA-46EC-B8F5-9BC5933C5533}.Debug|Any CPU.Build.0 = Debug|Any CPU
24 | {600BA962-07EA-46EC-B8F5-9BC5933C5533}.Release|Any CPU.ActiveCfg = Release|Any CPU
25 | {600BA962-07EA-46EC-B8F5-9BC5933C5533}.Release|Any CPU.Build.0 = Release|Any CPU
26 | {6B65B2D7-6344-4B15-A428-483E74E9AF51}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27 | {6B65B2D7-6344-4B15-A428-483E74E9AF51}.Debug|Any CPU.Build.0 = Debug|Any CPU
28 | {6B65B2D7-6344-4B15-A428-483E74E9AF51}.Release|Any CPU.ActiveCfg = Release|Any CPU
29 | {6B65B2D7-6344-4B15-A428-483E74E9AF51}.Release|Any CPU.Build.0 = Release|Any CPU
30 | EndGlobalSection
31 | GlobalSection(SolutionProperties) = preSolution
32 | HideSolutionNode = FALSE
33 | EndGlobalSection
34 | EndGlobal
35 |
--------------------------------------------------------------------------------
/ServerlessBenchmark/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/ServerlessBenchmark/Constants.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace ServerlessBenchmark
4 | {
5 | public static class Constants
6 | {
7 | public const string InsertionTime = "InsertionTime";
8 | public const string Topic = "Topic";
9 | public const string Message = "Message";
10 | public const string Queue = "QueueUrl";
11 | public const int MaxDequeueAmount = 32;
12 |
13 | ///
14 | /// The name of the table where all of the azure function execution logs are stored.
15 | ///
16 | public const string AzureFunctionLogTableName = "AzureFunctionsLogTable";
17 |
18 | ///
19 | /// Partition key of the execution logs that carries information such as container and etc.
20 | ///
21 | public const string AzureFunctionLogExecutionPartitionKey = "R";
22 |
23 | ///
24 | /// Timeout in milliseconds for each http request
25 | ///
26 | public const int HttpTriggerTimeoutMilliseconds = 300 * 1000;
27 |
28 | public const int LoadCoolDownTimeout = 180 * 1000;
29 | }
30 |
31 | public enum TriggerTypes { Blob, Queue, Http}
32 | }
33 |
--------------------------------------------------------------------------------
/ServerlessBenchmark/LoadProfiles/LinearLoad.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading;
3 |
4 | namespace ServerlessBenchmark.LoadProfiles
5 | {
6 | ///
7 | /// This load profile just follows the basic definition of linear.
8 | /// y = mx + b
9 | ///
10 | public class LinearLoad:TriggerTestLoadProfile
11 | {
12 | private int _totalNumberOfPostItems;
13 | private readonly int _targetEps;
14 | private int _isFinished;
15 |
16 | ///
17 | /// Given some duration, run linear pattern load against a function.
18 | ///
19 | ///
20 | /// This is target executions per second
21 | public LinearLoad(TimeSpan loadDuration, int eps) : base(loadDuration)
22 | {
23 | _targetEps = eps;
24 | }
25 |
26 | ///
27 | /// Run linear pattern load against a function.
28 | ///
29 | ///
30 | /// This is target executions per second
31 | public LinearLoad(int totalNumberOfPostItems, int eps) : base(TimeSpan.FromMilliseconds(Int32.MaxValue))
32 | {
33 | _targetEps = eps;
34 | _totalNumberOfPostItems = totalNumberOfPostItems;
35 | }
36 |
37 | protected override int ExecuteRate(int t)
38 | {
39 | if (_totalNumberOfPostItems > 0 && _targetEps > 0)
40 | {
41 | _totalNumberOfPostItems = Math.Max(_targetEps, _totalNumberOfPostItems) - Math.Min(_targetEps, _totalNumberOfPostItems);
42 | if (_totalNumberOfPostItems <= 0)
43 | {
44 | Interlocked.Increment(ref _isFinished);
45 | }
46 | }
47 | const int slope = 0;
48 | return slope*t + _targetEps;
49 | }
50 |
51 | protected override bool IsFinished()
52 | {
53 | return _isFinished == 1;
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/ServerlessBenchmark/LoadProfiles/TriggerTestLoadProfile.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------
2 | // Copyright (c) Microsoft Corporation. All rights reserved.
3 | //------------------------------------------------------------
4 | using System;
5 |
6 | using System.Collections.Generic;
7 | using System.Threading;
8 | using System.Threading.Tasks;
9 |
10 | namespace ServerlessBenchmark.LoadProfiles
11 | {
12 | ///
13 | /// Base class for load profiles
14 | ///
15 | public abstract class TriggerTestLoadProfile:IDisposable
16 | {
17 | protected TimeSpan LoadDuration;
18 | private Timer _calculateRateTimer;
19 | private int _timeCounter = -1;
20 | private List _runningTasks;
21 |
22 | protected TriggerTestLoadProfile(TimeSpan loadDuration)
23 | {
24 | LoadDuration = loadDuration;
25 | _runningTasks = new List();
26 | }
27 |
28 | ///
29 | /// Given a duration and action, calculate rate of publishing items and execute the given action.
30 | ///
31 | ///
32 | public async Task ExecuteRateAsync(Func action)
33 | {
34 | TimerCallback callback = async t =>
35 | {
36 | Interlocked.Increment(ref _timeCounter);
37 | int rate = ExecuteRate(_timeCounter);
38 | var loadAction = action(rate);
39 | _runningTasks.Add(loadAction);
40 | await loadAction;
41 | };
42 | _calculateRateTimer = new Timer(callback, null, 0, 1000 * 1);
43 | var isLoadFinishedTask = Task.Run(() =>
44 | {
45 | while (!IsFinished())
46 | {
47 | //keep cycling
48 | Task.Delay(TimeSpan.FromSeconds(1));
49 | }
50 | });
51 |
52 | var loadDurationTimerTask = Task.Delay(LoadDuration + TimeSpan.FromSeconds(1));
53 |
54 | await Task.WhenAny(loadDurationTimerTask, isLoadFinishedTask);
55 | }
56 |
57 | protected abstract int ExecuteRate(int t);
58 |
59 | protected abstract bool IsFinished();
60 |
61 | public void Dispose()
62 | {
63 | _calculateRateTimer.Dispose();
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/ServerlessBenchmark/MetricInfo/Metric.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace ServerlessBenchmark.MetricInfo
4 | {
5 | public sealed class Metric:IEquatable
6 | {
7 | public string Name { get; private set; }
8 | public Metric(string metricName)
9 | {
10 | if (!string.IsNullOrEmpty(metricName))
11 | {
12 | Name = metricName;
13 | }
14 | else
15 | {
16 | throw new ArgumentNullException("metricName");
17 | }
18 | }
19 |
20 | public bool Equals(Metric other)
21 | {
22 | return Name.Equals(other.Name, StringComparison.CurrentCultureIgnoreCase);
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/ServerlessBenchmark/MetricInfo/PerfMetrics.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace ServerlessBenchmark.MetricInfo
8 | {
9 | public enum PerfMetrics
10 | {
11 | ExecutionTimeStandardDeviation,
12 | ExecutionCount,
13 | FunctionClockTime,
14 | AverageExecutionTime,
15 | Throughput,
16 | HostConcurrency,
17 | ThroughputGraph
18 | }
19 |
20 | [AttributeUsage(AttributeTargets.Method)]
21 | public sealed class PerfMetric : Attribute
22 | {
23 | public string MetricName { get; private set; }
24 | public PerfMetric(PerfMetrics metric)
25 | {
26 | MetricName = Enum.GetName(typeof (PerfMetrics), metric);
27 | }
28 |
29 | public PerfMetric(string metricName)
30 | {
31 | MetricName = metricName;
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/ServerlessBenchmark/PerfResultProviders/AwsGenericPerformanceResultsProvider.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using Amazon.CloudWatchLogs.Model;
4 | using ServerlessBenchmark.MetricInfo;
5 |
6 | namespace ServerlessBenchmark.PerfResultProviders
7 | {
8 | public sealed class AwsGenericPerformanceResultsProvider:AwsPerformanceResultProviderBase
9 | {
10 | protected override Dictionary ObtainAdditionalPerfMetrics(PerfTestResult genericPerfTestResult,
11 | string functionName, DateTime testStartTime, DateTime testEndTime, List lambdaExecutionLogs)
12 | {
13 | return null;
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/ServerlessBenchmark/PerfResultProviders/AzureGenericPerformanceResultsProvider.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace ServerlessBenchmark.PerfResultProviders
8 | {
9 | public class AzureGenericPerformanceResultsProvider : AzurePerformanceResultProviderBase
10 | {
11 | protected override Dictionary ObtainAdditionalPerfMetrics(PerfTestResult genericPerfTestResult, string functionName, DateTime testStartTime,
12 | DateTime testEndTime)
13 | {
14 | return null;
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/ServerlessBenchmark/PerfResultProviders/FunctionLogs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Configuration;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading;
7 | using System.Threading.Tasks;
8 | using Amazon.CloudWatchLogs;
9 | using Amazon.CloudWatchLogs.Model;
10 | using Microsoft.WindowsAzure.Storage;
11 | using Microsoft.WindowsAzure.Storage.Table;
12 |
13 | namespace ServerlessBenchmark.PerfResultProviders
14 | {
15 | internal class FunctionLogs
16 | {
17 | private static List _azurefunctionLogs;
18 | public static List GetAzureFunctionLogs(string functionName, DateTime? startTime, DateTime? endTime, bool update = false, int expectedExecutionCount = 0)
19 | {
20 | return GetAzureFunctionLogsInternal(functionName, startTime, endTime, update, expectedExecutionCount);
21 | }
22 |
23 | public static List GetAzureFunctionLogs(DateTime? startTime, DateTime? endTime, bool update = false, int expectedExecutionCount = 0)
24 | {
25 | return GetAzureFunctionLogsInternal(string.Empty, startTime, endTime, update, expectedExecutionCount);
26 | }
27 |
28 | public static List GetAzureFunctionLogs(string functionName, bool allLogs = false)
29 | {
30 | return GetAzureFunctionLogsInternal(functionName, null, null);
31 | }
32 |
33 | public static bool RemoveAllCLoudWatchLogs(string functionName)
34 | {
35 | bool isEmpty;
36 | using (var cwClient = new AmazonCloudWatchLogsClient())
37 | {
38 | var logStreams = GetAllLogStreams(functionName, cwClient);
39 | Console.WriteLine("Deleting Log Streams");
40 | logStreams.ForEach(s => cwClient.DeleteLogStream(new DeleteLogStreamRequest("/aws/lambda/" + functionName, s.LogStreamName)));
41 | isEmpty = GetAllLogStreams(functionName, cwClient).Count == 0;
42 | }
43 | return isEmpty;
44 | }
45 |
46 | private static List GetAzureFunctionLogsInternal(string functionName, DateTime? startTime, DateTime? endTime, bool update = false, int expectedExecutionCount = 0, int waitForAllLogsTimeoutInMinutes = 5)
47 | {
48 | Console.WriteLine("Getting Azure Function logs from Azure Storage Tables..");
49 | var connectionString = ConfigurationManager.AppSettings["AzureStorageConnectionString"];
50 |
51 | if (!string.IsNullOrEmpty(connectionString))
52 | {
53 | var storageAccount = CloudStorageAccount.Parse(connectionString);
54 | var tableClient = storageAccount.CreateCloudTableClient();
55 | var table = tableClient.GetTableReference("AzureFunctionsLogTable");
56 | var query = new TableQuery();
57 | int size = 0;
58 | var latestNewLog = DateTime.UtcNow;
59 | var lastSize = 0;
60 |
61 | do
62 | {
63 | _azurefunctionLogs = table.ExecuteQuery(query).Where(log => string.IsNullOrEmpty(functionName) || (!string.IsNullOrEmpty(log.FunctionName) &&
64 | log.FunctionName.Equals(functionName, StringComparison.CurrentCultureIgnoreCase) && !string.IsNullOrEmpty(log.ContainerName))).ToList();
65 | size = _azurefunctionLogs.Count();
66 |
67 | if (lastSize != size)
68 | {
69 | lastSize = size;
70 | latestNewLog = DateTime.UtcNow;
71 | }
72 | else
73 | {
74 | var secondsSinceLastNewLog = (DateTime.UtcNow - latestNewLog).TotalSeconds;
75 | var secondsStillToWait = 60*waitForAllLogsTimeoutInMinutes - secondsSinceLastNewLog;
76 | Console.WriteLine(
77 | "No new log for {0} seconds. Waiting another {1}s to finish.",
78 | secondsSinceLastNewLog,
79 | secondsStillToWait
80 | );
81 | }
82 |
83 | if (expectedExecutionCount == 0)
84 | {
85 | break;
86 | }
87 |
88 | Console.WriteLine("Log count {0} expected {1}", size, expectedExecutionCount);
89 |
90 | if ((DateTime.UtcNow - latestNewLog).TotalMinutes >= waitForAllLogsTimeoutInMinutes)
91 | {
92 | Console.WriteLine("Not all result logs have been found! No new logs appeared in last {0} minutes. Finishing wait to present results.", waitForAllLogsTimeoutInMinutes);
93 | break;
94 | }
95 |
96 | Thread.Sleep(1000);
97 | } while (size < expectedExecutionCount);
98 | }
99 |
100 | return _azurefunctionLogs;
101 | }
102 |
103 | private static List GetAllLogStreams(string functionName, AmazonCloudWatchLogsClient cwClient)
104 | {
105 | var logStreams = new List();
106 | DescribeLogStreamsResponse lResponse;
107 | string nextToken = null;
108 | do
109 | {
110 | lResponse =
111 | cwClient.DescribeLogStreams(new DescribeLogStreamsRequest("/aws/lambda/" + functionName)
112 | {
113 | NextToken = nextToken
114 | });
115 | logStreams.AddRange(lResponse.LogStreams);
116 | } while (!string.IsNullOrEmpty(nextToken = lResponse.NextToken));
117 | return logStreams;
118 | }
119 |
120 | public class AzureFunctionLogs : TableEntity
121 | {
122 | public string FunctionName { get; set; }
123 | public DateTime StartTime { get; set; }
124 | public DateTime EndTime { get; set; }
125 | public string ContainerName { get; set; }
126 | public Int32 TotalFail { get; set; }
127 | public Int32 TotalPass { get; set; }
128 | }
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/ServerlessBenchmark/PerfResultProviders/PerfResultProvider.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Reflection;
6 | using System.Text;
7 | using OxyPlot;
8 | using OxyPlot.Axes;
9 | using OxyPlot.Series;
10 | using ServerlessBenchmark.MetricInfo;
11 |
12 | namespace ServerlessBenchmark.PerfResultProviders
13 | {
14 | public abstract class PerfResultProvider
15 | {
16 | protected void PrintThrouputGraph(Dictionary data, string fileName, int timeResolutionInSeconds)
17 | {
18 | var stringBuffer = new StringBuilder();
19 |
20 | var model = new PlotModel { Title = "AWS throuput in time (items finished/second)" };
21 | var timeAxis = new DateTimeAxis
22 | {
23 | StringFormat = "hh:mm:ss"
24 | };
25 |
26 | model.Axes.Add(timeAxis);
27 | var series = new LineSeries();
28 |
29 | foreach (var log in data.OrderBy(l => l.Key))
30 | {
31 | stringBuffer.AppendFormat("{0},{1}{2}", log.Value / timeResolutionInSeconds, log.Key, Environment.NewLine);
32 | series.Points.Add(new DataPoint(DateTimeAxis.ToDouble(log.Key), log.Value / timeResolutionInSeconds));
33 | }
34 |
35 | model.Series.Add(series);
36 |
37 | using (var stream = File.Create(fileName))
38 | {
39 | var pdfExporter = new PdfExporter { Width = 600, Height = 400 };
40 | pdfExporter.Export(model, stream);
41 | }
42 | }
43 |
44 | protected abstract Dictionary ObtainAdditionalPerfMetrics(PerfTestResult genericPerfTestResult, string functionName, DateTime testStartTime, DateTime testEndTime);
45 |
46 | public virtual PerfTestResult GetPerfMetrics(string functionName, DateTime testStartTime, DateTime testEndTime,string inputTriggerName = null, string outputTriggerName = null, int expectedExecutionCount = 0)
47 | {
48 | var perfResults = new PerfTestResult();
49 | var perfCalculatingMethods = GetType().GetRuntimeMethods().Where(m => m.IsDefined(typeof (PerfMetric)));
50 | foreach (var method in perfCalculatingMethods)
51 | {
52 | var result = method.Invoke(this, new object[]{functionName, testStartTime, testEndTime}).ToString();
53 | var perfMetricAttribute = method.GetCustomAttribute(typeof (PerfMetric)) as PerfMetric;
54 | var metricName = perfMetricAttribute.MetricName;
55 | perfResults.AddMetric(metricName, result);
56 | }
57 |
58 | var additionalPerfResults = ObtainAdditionalPerfMetrics(perfResults, functionName, testStartTime, testEndTime) ?? new Dictionary();
59 | var additionalPerfResultsList = additionalPerfResults.ToList();
60 | foreach (var additionalPerfResult in additionalPerfResultsList)
61 | {
62 | perfResults.AddMetric(additionalPerfResult.Key, additionalPerfResult.Value);
63 | }
64 | return perfResults;
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/ServerlessBenchmark/PerfTestResult.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using ServerlessBenchmark.MetricInfo;
6 |
7 | namespace ServerlessBenchmark
8 | {
9 | public class PerfTestResult : SortedList
10 | {
11 | public void AddMetric(string metricName, string val)
12 | {
13 | Add(metricName, val);
14 | }
15 |
16 | public override string ToString()
17 | {
18 | var sb = new StringBuilder();
19 | var list = this.ToList();
20 | foreach (var metric in list)
21 | {
22 | sb.AppendFormat("{0} {1}\n", metric.Key, metric.Value);
23 | }
24 | return sb.ToString();
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/ServerlessBenchmark/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("ServerlessBenchmark")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("ServerlessBenchmark")]
13 | [assembly: AssemblyCopyright("Copyright © 2016")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("e232a8ea-2118-46bd-9264-0b5d32348387")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/ServerlessBenchmark/ServerlessBenchmark.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {582CC16B-6C75-494B-B27F-7A769DEC0C30}
8 | Library
9 | Properties
10 | ServerlessBenchmark
11 | ServerlessBenchmark
12 | v4.5
13 | 512
14 |
15 |
16 | true
17 | full
18 | false
19 | bin\Debug\
20 | DEBUG;TRACE
21 | prompt
22 | 4
23 |
24 |
25 | pdbonly
26 | true
27 | bin\Release\
28 | TRACE
29 | prompt
30 | 4
31 |
32 |
33 |
34 | ..\packages\AWSSDK.CloudWatch.3.1.0.7\lib\net45\AWSSDK.CloudWatch.dll
35 |
36 |
37 | ..\packages\AWSSDK.CloudWatchLogs.3.1.2.6\lib\net45\AWSSDK.CloudWatchLogs.dll
38 |
39 |
40 | ..\packages\AWSSDK.Core.3.1.7.0\lib\net45\AWSSDK.Core.dll
41 |
42 |
43 | ..\packages\AWSSDK.Lambda.3.1.4.2\lib\net45\AWSSDK.Lambda.dll
44 |
45 |
46 | ..\packages\AWSSDK.S3.3.1.7.2\lib\net45\AWSSDK.S3.dll
47 |
48 |
49 | ..\packages\AWSSDK.SimpleNotificationService.3.1.0.7\lib\net45\AWSSDK.SimpleNotificationService.dll
50 |
51 |
52 | ..\packages\AWSSDK.SQS.3.1.0.10\lib\net45\AWSSDK.SQS.dll
53 |
54 |
55 | ..\packages\Microsoft.Azure.KeyVault.Core.1.0.0\lib\net40\Microsoft.Azure.KeyVault.Core.dll
56 |
57 |
58 | False
59 | ..\packages\Microsoft.Data.Edm.5.6.4\lib\net40\Microsoft.Data.Edm.dll
60 |
61 |
62 | False
63 | ..\packages\Microsoft.Data.OData.5.6.4\lib\net40\Microsoft.Data.OData.dll
64 |
65 |
66 | False
67 | ..\packages\Microsoft.Data.Services.Client.5.6.4\lib\net40\Microsoft.Data.Services.Client.dll
68 |
69 |
70 | False
71 | ..\packages\WindowsAzure.Storage.7.0.0\lib\net40\Microsoft.WindowsAzure.Storage.dll
72 |
73 |
74 | ..\packages\Newtonsoft.Json.6.0.8\lib\net45\Newtonsoft.Json.dll
75 |
76 |
77 | ..\packages\OxyPlot.Core.1.0.0-unstable2100\lib\net45\OxyPlot.dll
78 | True
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 | False
87 | ..\packages\System.Spatial.5.6.4\lib\net40\System.Spatial.dll
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
144 |
--------------------------------------------------------------------------------
/ServerlessBenchmark/ServerlessPlatformControllers/AWS/AWS_CloudPlatformResponse.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Amazon.Runtime;
3 |
4 | namespace ServerlessBenchmark.ServerlessPlatformControllers.AWS
5 | {
6 | public class AwsCloudPlatformResponse:CloudPlatformResponse
7 | {
8 | public static AwsCloudPlatformResponse PopulateFrom(AmazonWebServiceResponse response)
9 | {
10 | if (response == null)
11 | {
12 | return null;
13 | }
14 | string insertionTime;
15 | DateTime insertionDateTime;
16 | response.ResponseMetadata.Metadata.TryGetValue(Constants.InsertionTime, out insertionTime);
17 | DateTime.TryParse(insertionTime, out insertionDateTime);
18 | var genericPlatformReponse = new AwsCloudPlatformResponse()
19 | {
20 | HttpStatusCode = response.HttpStatusCode,
21 | TimeStamp = insertionDateTime
22 | };
23 | return genericPlatformReponse;
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/ServerlessBenchmark/ServerlessPlatformControllers/CloudPlatformController.cs:
--------------------------------------------------------------------------------
1 | using System.Threading.Tasks;
2 |
3 | namespace ServerlessBenchmark.ServerlessPlatformControllers
4 | {
5 | ///
6 | /// Interface that serverless benchmark uses to communicate with the serverless platform.
7 | ///
8 | public interface ICloudPlatformController
9 | {
10 | CloudPlatformResponse PostMessage(CloudPlatformRequest request);
11 | CloudPlatformResponse PostMessages(CloudPlatformRequest request);
12 | Task PostMessagesAsync(CloudPlatformRequest request);
13 | CloudPlatformResponse GetMessage(CloudPlatformRequest request);
14 | CloudPlatformResponse GetMessages(CloudPlatformRequest request);
15 | CloudPlatformResponse DeleteMessages(CloudPlatformRequest request);
16 | Task EnqueueMessagesAsync(CloudPlatformRequest request);
17 | Task DequeueMessagesAsync(CloudPlatformRequest request);
18 | CloudPlatformResponse PostBlob(CloudPlatformRequest request);
19 | Task PostBlobAsync(CloudPlatformRequest request);
20 | Task PostBlobsAsync(CloudPlatformRequest request);
21 | CloudPlatformResponse ListBlobs(CloudPlatformRequest request);
22 | CloudPlatformResponse DeleteBlobs(CloudPlatformRequest request);
23 | CloudPlatformResponse GetFunctionName(string inputContainerName);
24 | CloudPlatformResponse GetInputOutputTriggers(string functionName);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/ServerlessBenchmark/ServerlessPlatformControllers/CloudPlatformRequest.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 |
5 | namespace ServerlessBenchmark.ServerlessPlatformControllers
6 | {
7 | public class CloudPlatformRequest
8 | {
9 | public DateTime TimeStamp { get; set; }
10 | public int RequestId { get; set; }
11 | public Dictionary Data { get; set; }
12 | public string Source { get; set; }
13 | public Stream DataStream { get; set; }
14 | public string Key { get; set; }
15 | public int MessageCount { get; set; }
16 | public bool Retry { get; set; }
17 | public int RetryAttempts { get; set; }
18 | public int? TimeoutMilliseconds { get; set; }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/ServerlessBenchmark/ServerlessPlatformControllers/CloudPlatformResponse.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace ServerlessBenchmark.ServerlessPlatformControllers
5 | {
6 | public class CloudPlatformResponse
7 | {
8 | public int ResponseId { get; set; }
9 | public System.Net.HttpStatusCode HttpStatusCode { get; set; }
10 | public DateTime TimeStamp { get; set; }
11 | public Dictionary TimeStamps { get; set; }
12 | public object Data { get; set; }
13 |
14 | public Dictionary ErrorDetails { get; private set; }
15 |
16 | public CloudPlatformResponse()
17 | {
18 | ErrorDetails = new Dictionary();
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/ServerlessBenchmark/SupplementalPerfTestResult.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace ServerlessBenchmark
5 | {
6 | sealed internal class SupplementalPerfTestResult:PerfTestResult
7 | {
8 | private Dictionary _supplementalPerformanceTestResults;
9 | internal Dictionary SupplementalPerformanceTestResults {
10 | get
11 | {
12 | if (_supplementalPerformanceTestResults == null)
13 | {
14 | _supplementalPerformanceTestResults = new Dictionary();
15 | }
16 | return _supplementalPerformanceTestResults;
17 | }
18 | }
19 |
20 | public override string ToString()
21 | {
22 | var perfResults = base.ToString();
23 | foreach (var metric in SupplementalPerformanceTestResults)
24 | {
25 | perfResults += String.Format("{0} {1}\n", metric.Key, metric.Value);
26 | }
27 | return perfResults;
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/ServerlessBenchmark/TestRequest.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace ServerlessBenchmark
4 | {
5 | public class TestRequest
6 | {
7 | private const int DefaultRetries = 5;
8 | private int _retries = 0;
9 | public IEnumerable Messages { get; set; }
10 | public string SrcQueue { get; set; }
11 | public string DstQueue { get; set; }
12 | public int[] DistributedBatchMessageSizes { get; set; }
13 | public string CloudPlatform { get; set; }
14 |
15 | public int Retries
16 | {
17 | get
18 | {
19 | if (_retries == 0)
20 | {
21 | return DefaultRetries;
22 | }
23 | return _retries;
24 | }
25 | set { _retries = value; }
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/ServerlessBenchmark/TriggerTests/AWS/AmazonApiGatewayTriggerTest.cs:
--------------------------------------------------------------------------------
1 | using ServerlessBenchmark.PerfResultProviders;
2 | using ServerlessBenchmark.ServerlessPlatformControllers;
3 | using ServerlessBenchmark.ServerlessPlatformControllers.AWS;
4 | using ServerlessBenchmark.TriggerTests.BaseTriggers;
5 |
6 | namespace ServerlessBenchmark.TriggerTests.AWS
7 | {
8 | public class AmazonApiGatewayTriggerTest:HttpTriggerTest
9 | {
10 | public AmazonApiGatewayTriggerTest(string functionName, string[] urls) : base(functionName, urls)
11 | {
12 | }
13 |
14 | protected override bool Setup()
15 | {
16 | return FunctionLogs.RemoveAllCLoudWatchLogs(FunctionName);
17 | }
18 |
19 | protected override ICloudPlatformController CloudPlatformController
20 | {
21 | get { return new AwsController(); }
22 | }
23 |
24 | protected override PerfResultProvider PerfmormanceResultProvider
25 | {
26 | get { return new AwsGenericPerformanceResultsProvider(); }
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/ServerlessBenchmark/TriggerTests/AWS/AmazonS3TriggerTest.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using ServerlessBenchmark.PerfResultProviders;
4 | using ServerlessBenchmark.ServerlessPlatformControllers;
5 | using ServerlessBenchmark.ServerlessPlatformControllers.AWS;
6 | using ServerlessBenchmark.TriggerTests.BaseTriggers;
7 |
8 | namespace ServerlessBenchmark.TriggerTests.AWS
9 | {
10 | public class AmazonS3TriggerTest:BlobTriggerTest
11 | {
12 |
13 | public AmazonS3TriggerTest(string functionName, IEnumerable blobs, string sourceBlobContainer,
14 | string destinationBlobContainer)
15 | : base(functionName, blobs.ToArray(), sourceBlobContainer, destinationBlobContainer)
16 | {
17 |
18 | }
19 |
20 | protected override bool Setup()
21 | {
22 | return FunctionLogs.RemoveAllCLoudWatchLogs(FunctionName);
23 | }
24 |
25 | protected override ICloudPlatformController CloudPlatformController
26 | {
27 | get { return new AwsController(); }
28 | }
29 |
30 | protected override PerfResultProvider PerfmormanceResultProvider
31 | {
32 | get { return new AwsGenericPerformanceResultsProvider(); }
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/ServerlessBenchmark/TriggerTests/AWS/AmazonSnsToSqs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Net;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using ServerlessBenchmark.ServerlessPlatformControllers;
8 |
9 | namespace ServerlessBenchmark.TriggerTests.AWS
10 | {
11 | public class AmazonSnsToSqs : AmazonSqsTriggerTest
12 | {
13 | private string _sourceTopic;
14 | public AmazonSnsToSqs(string functionName, IEnumerable messages, string sourceTopic, string destinationQueue) : base(functionName, messages, sourceTopic, destinationQueue)
15 | {
16 | _sourceTopic = sourceTopic;
17 | }
18 |
19 | protected override string StorageType
20 | {
21 | get { return "SnsToQueue"; }
22 | }
23 |
24 | protected override List CleanUpStorageResources()
25 | {
26 | var responses = new List();
27 | List cloudPlatformResponses = null;
28 | try
29 | {
30 | cloudPlatformResponses = new List
31 | {
32 | {CloudPlatformController.DeleteMessages(new CloudPlatformRequest() {Source = TargetQueue})}
33 | };
34 | responses.AddRange(cloudPlatformResponses);
35 | }
36 | catch (Exception e)
37 | {
38 | Console.WriteLine(e);
39 | throw;
40 | }
41 | return responses;
42 | }
43 |
44 | protected async override Task UploadItems(IEnumerable items)
45 | {
46 | //instead of sending messages to queue send to SNS topic
47 | await CloudPlatformController.PostMessagesAsync(new CloudPlatformRequest()
48 | {
49 | Data = new Dictionary()
50 | {
51 | {Constants.Message, items},
52 | {Constants.Topic, _sourceTopic}
53 | },
54 | Retry = true,
55 | RetryAttempts = 3,
56 | TimeoutMilliseconds = (int?) TimeSpan.FromSeconds(45).TotalMilliseconds
57 | });
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/ServerlessBenchmark/TriggerTests/AWS/AmazonSqsTriggerTest.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using ServerlessBenchmark.PerfResultProviders;
4 | using ServerlessBenchmark.ServerlessPlatformControllers;
5 | using ServerlessBenchmark.ServerlessPlatformControllers.AWS;
6 | using ServerlessBenchmark.TriggerTests.BaseTriggers;
7 |
8 | namespace ServerlessBenchmark.TriggerTests.AWS
9 | {
10 | public class AmazonSqsTriggerTest:QueueTriggerTest
11 | {
12 | public AmazonSqsTriggerTest(string functionName, IEnumerable queueMessages, string sourceBlobContainer,
13 | string destinationBlobContainer)
14 | : base(functionName, queueMessages.ToArray(), sourceBlobContainer, destinationBlobContainer)
15 | {
16 |
17 | }
18 |
19 | protected override bool Setup()
20 | {
21 | return FunctionLogs.RemoveAllCLoudWatchLogs(FunctionName);
22 | }
23 |
24 | protected override ICloudPlatformController CloudPlatformController
25 | {
26 | get { return new AwsController(); }
27 | }
28 |
29 | protected override PerfResultProvider PerfmormanceResultProvider
30 | {
31 | get { return new AwsGenericPerformanceResultsProvider(); }
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/ServerlessBenchmark/TriggerTests/Azure/AzureBlobTriggerTest.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Configuration;
3 | using System.Linq;
4 | using Microsoft.WindowsAzure.Storage;
5 | using Microsoft.WindowsAzure.Storage.Table;
6 | using ServerlessBenchmark.PerfResultProviders;
7 | using ServerlessBenchmark.ServerlessPlatformControllers;
8 | using ServerlessBenchmark.ServerlessPlatformControllers.Azure;
9 | using ServerlessBenchmark.TriggerTests.BaseTriggers;
10 |
11 | namespace ServerlessBenchmark.TriggerTests.Azure
12 | {
13 | public class AzureBlobTriggerTest:BlobTriggerTest
14 | {
15 | public AzureBlobTriggerTest(string functionName, IEnumerable blobs, string inputContainer,
16 | string outputContainer) : base(functionName, blobs.ToArray(), inputContainer, outputContainer)
17 | {
18 |
19 | }
20 |
21 | public AzureBlobTriggerTest(string functionName, IEnumerable blobs)
22 | {
23 | //todo find the input and output container given the container name
24 | }
25 |
26 | protected override bool Setup()
27 | {
28 | return RemoveAzureFunctionLogs() && EnableLoggingIfDisabled();
29 | }
30 |
31 | protected override ICloudPlatformController CloudPlatformController
32 | {
33 | get { return new AzureController(); }
34 | }
35 |
36 | protected override PerfResultProvider PerfmormanceResultProvider
37 | {
38 | get { return new AzureGenericPerformanceResultsProvider(); }
39 | }
40 |
41 | private bool RemoveAzureFunctionLogs()
42 | {
43 | var connectionString = ConfigurationManager.AppSettings["AzureStorageConnectionString"];
44 | if (!string.IsNullOrEmpty(connectionString))
45 | {
46 | var operationContext = new OperationContext();
47 | var storageAccount = CloudStorageAccount.Parse(connectionString);
48 | var tableClient = storageAccount.CreateCloudTableClient();
49 | var logs = FunctionLogs.GetAzureFunctionLogs(FunctionName);
50 | var table = tableClient.GetTableReference("AzureFunctionsLogTable");
51 | logs.ForEach(entity => table.Execute(TableOperation.Delete(entity)));
52 | return true;
53 | }
54 | return false;
55 | }
56 |
57 | private bool EnableLoggingIfDisabled()
58 | {
59 | var connectionString = ConfigurationManager.AppSettings["AzureStorageConnectionString"];
60 | var operationContext = new OperationContext();
61 | var storageAccount = CloudStorageAccount.Parse(connectionString);
62 | var blobClient = storageAccount.CreateCloudBlobClient();
63 | var currentServiceProperties = blobClient.GetServiceProperties();
64 | return true;
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/ServerlessBenchmark/TriggerTests/Azure/AzureHttpTriggerTest.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Configuration;
3 | using System.Linq;
4 | using ServerlessBenchmark.PerfResultProviders;
5 | using ServerlessBenchmark.ServerlessPlatformControllers;
6 | using ServerlessBenchmark.ServerlessPlatformControllers.Azure;
7 | using ServerlessBenchmark.TriggerTests.BaseTriggers;
8 |
9 | namespace ServerlessBenchmark.TriggerTests.Azure
10 | {
11 | public class AzureHttpTriggerTest:HttpTriggerTest
12 | {
13 | public AzureHttpTriggerTest(string functionName, IEnumerable urls) : base(functionName, urls.ToArray())
14 | {
15 |
16 | }
17 |
18 | protected override bool Setup()
19 | {
20 | return Utility.RemoveAzureFunctionLogs(FunctionName,
21 | ConfigurationManager.AppSettings["AzureStorageConnectionString"]);
22 | }
23 |
24 | protected override ICloudPlatformController CloudPlatformController
25 | {
26 | get { return new AzureController(); }
27 | }
28 |
29 | protected override PerfResultProvider PerfmormanceResultProvider
30 | {
31 | get { return new AzureGenericPerformanceResultsProvider(); }
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/ServerlessBenchmark/TriggerTests/Azure/AzureQueueTriggerTest.cs:
--------------------------------------------------------------------------------
1 | using System.Configuration;
2 | using ServerlessBenchmark.PerfResultProviders;
3 | using ServerlessBenchmark.ServerlessPlatformControllers;
4 | using ServerlessBenchmark.ServerlessPlatformControllers.Azure;
5 | using ServerlessBenchmark.TriggerTests.BaseTriggers;
6 |
7 | namespace ServerlessBenchmark.TriggerTests.Azure
8 | {
9 | public class AzureQueueTriggerTest:QueueTriggerTest
10 | {
11 | public AzureQueueTriggerTest(string functionName, string[] messages, string sourceQueue, string targetQueue) : base(functionName, messages, sourceQueue, targetQueue)
12 | {
13 | }
14 |
15 | protected override ICloudPlatformController CloudPlatformController
16 | {
17 | get { return new AzureController(); }
18 | }
19 |
20 | protected override PerfResultProvider PerfmormanceResultProvider
21 | {
22 | get { return new AzureGenericPerformanceResultsProvider(); }
23 | }
24 |
25 | protected override bool Setup()
26 | {
27 | return Utility.RemoveAzureFunctionLogs(FunctionName,
28 | ConfigurationManager.AppSettings["AzureStorageConnectionString"]);
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/ServerlessBenchmark/TriggerTests/BaseTriggers/BlobTriggerTest.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Threading;
6 | using System.Threading.Tasks;
7 | using ServerlessBenchmark.ServerlessPlatformControllers;
8 |
9 | namespace ServerlessBenchmark.TriggerTests.BaseTriggers
10 | {
11 | public abstract class BlobTriggerTest:StorageTriggerTest
12 | {
13 | protected readonly string SrcBlobContainer;
14 | protected readonly string DstBlobContainer;
15 | protected readonly string _functionName;
16 |
17 | protected BlobTriggerTest(string functionName, string[] blobs, string sourceBlobContainer, string destinationBlobContainer):base(functionName, blobs)
18 | {
19 | if (string.IsNullOrEmpty(functionName) || string.IsNullOrEmpty(sourceBlobContainer) || string.IsNullOrEmpty(destinationBlobContainer)
20 | || blobs == null)
21 | {
22 | throw new ArgumentException("Not all of the arguments are met");
23 | }
24 |
25 | DstBlobContainer = destinationBlobContainer;
26 | SrcBlobContainer = sourceBlobContainer;
27 | _functionName = functionName;
28 | }
29 |
30 | public BlobTriggerTest():base(null, null) { }
31 |
32 | protected virtual string WarmUpBlob
33 | {
34 | get
35 | {
36 | return SourceItems.First();
37 | }
38 | }
39 |
40 | protected override string StorageType
41 | {
42 | get { return "Blob"; }
43 | }
44 |
45 | protected override List CleanUpStorageResources()
46 | {
47 | var cloudPlatformResponses = new List
48 | {
49 | {CloudPlatformController.DeleteBlobs(new CloudPlatformRequest() {Source = SrcBlobContainer})},
50 | {CloudPlatformController.DeleteBlobs(new CloudPlatformRequest() {Source = DstBlobContainer})}
51 | };
52 | return cloudPlatformResponses;
53 | }
54 |
55 | protected override async Task UploadItems(IEnumerable items)
56 | {
57 | await UploadBlobs(items);
58 | }
59 |
60 | protected override Task VerifyTargetDestinationStorageCount(int expectedCount)
61 | {
62 | return Task.FromResult(VerifyBlobItemsExistInTargetDestination(expectedCount));
63 | }
64 |
65 | private async Task UploadBlobs(IEnumerable blobs)
66 | {
67 | Parallel.ForEach(blobs, async blobPath =>
68 | {
69 | using (FileStream stream = new FileStream(blobPath, FileMode.Open, FileAccess.Read, FileShare.Read))
70 | {
71 | await CloudPlatformController.PostBlobAsync(new CloudPlatformRequest()
72 | {
73 | Key = Guid.NewGuid().ToString(),
74 | Source = SrcBlobContainer,
75 | DataStream = stream
76 | });
77 | }
78 | });
79 | }
80 |
81 | protected override Task TestCoolDown()
82 | {
83 | return Task.FromResult(true);
84 | }
85 |
86 | private bool VerifyBlobItemsExistInTargetDestination(int expected)
87 | {
88 | IEnumerable