Skip to content

Commit aaa0465

Browse files
committed
IoT Samrt Grig v2 - 1.4M rows/sec
1 parent e0268de commit aaa0465

File tree

19 files changed

+614
-489
lines changed

19 files changed

+614
-489
lines changed

samples/applications/iot-smart-grid/App.config

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,26 @@
44
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
55
</startup>
66
<connectionStrings>
7-
<!--<add name="Db" connectionString="Server=tcp:<server>.database.windows.net,1433;Database=PowerConsumption;User ID=<user>;Password=<password>;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;"/>-->
7+
<clear />
8+
<!--<add name="Db" connectionString="Server=tcp:(YOUR_SQLSERVERNAME).database.windows.net,1433;Database=(YOUR_DATABASE_NAME);User ID=(YOUR_USERNAME);Password=(YOUR_PASSWORD);Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;"/>-->
89
<add name="Db" connectionString="Server=.;Database=PowerConsumption;Integrated Security=True"/>
910
</connectionStrings>
1011
<appSettings>
11-
<add key="insertSPName" value="InsertMeterMeasurement"/> <!--Stored Procedure Name-->
12-
<add key="numberOfTasks" value="50"/> <!--Number of concurrent async tasks that the Data Generator will use-->
13-
<add key="numberOfMeters" value="1000000"/> <!--Number of unique meter Ids-->
14-
<add key="batchSize" value="1000"/> <!--Row Batch Size that every task produces-->
15-
<add key="commandDelay" value="1500"/> <!--Delay between sql commands. You can set this to 0 for max high volume workload-->
16-
<add key="commandTimeout" value="600"/> <!--SQL Command Timeout-->
17-
<add key="enableShock" value="1"/> <!--Flag that turns on/off the data shock. This should be set to 0 for max high volume workload-->
18-
<add key="shockFrequency" value="35000"/> <!--The Frequency that the code sets the commandDelay to 0-->
19-
<add key="shockDuration" value="4000"/> <!--The Duration that the code keeps the commandDelay to 0-->
20-
<add key="rpsFrequency" value="2000"/> <!--How frequently the Data Generator Rows Per Second(RPS) is polled-->
21-
<add key="logFileName" value="log.txt"/> <!--Log File Path-->
22-
<add key="powerBIDesktopPath" value="C:\Program Files\Microsoft Power BI Desktop\bin\PBIDesktop.exe"/><!--PowerBIDesktop.exe path-->
12+
<add key="insertSPName" value="InsertMeterMeasurement"/> <!--Stored Procedure Name-->
13+
<add key="numberOfDataLoadTasks" value="70"/> <!--Number of concurrent async tasks that the Data Generator will use (per SQL Connection)-->
14+
<add key="dataLoadCommandDelay" value="2000"/> <!--Delay between sql commands. You can set this to 0 for max high volume workload-->
15+
<add key="batchSize" value="70000"/> <!--Insert: Row Batch Size that every task produces-->
16+
<add key="deleteSPName" value="InsertMeterMeasurementHistory"/> <!--Stored Procedure Name-->
17+
<add key="numberOfOffLoadTasks" value="50"/> <!--Number of concurrent async tasks that the Data Generator will use (per SQL Connection)-->
18+
<add key="offLoadCommandDelay" value="0"/> <!--Delay between sql commands. You can set this to 0 for max high volume workload-->
19+
<add key="deleteBatchSize" value="1000000"/> <!--Delete: Row Batch Size that every task produces-->
20+
<add key="numberOfMeters" value="75000000"/> <!--Number of unique meters-->
21+
<add key="commandTimeout" value="600"/> <!--SQL Command Timeout-->
22+
<add key="rpsFrequency" value="500"/> <!--How frequently the Data Generator Rows Per Second(RPS) is polled-->
23+
<add key="logFileName" value="log.txt"/> <!--Log File Path-->
24+
<add key="delayStart" value="0"/> <!--Delay Graph Interval-->
25+
<add key="appRunDuration" value="1800000"/> <!--Run App Time: 30 mins-->
26+
<add key="numberOfRowsOfloadLimit" value="1400000"/> <!--Number Of Rows Ofload Limit-->
27+
<add key="powerBIDesktopPath" value="C:\Program Files\Microsoft Power BI Desktop\bin\PBIDesktop.exe"/> <!--PowerBIDesktop.exe path-->
2328
</appSettings>
2429
</configuration>

samples/applications/iot-smart-grid/ConsoleClient/Program.cs

Lines changed: 36 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -36,40 +36,39 @@ This code sample simulates an IoT Smart Grid scenario where multiple IoT power m
3636
shock absorber scenario: https://blogs.technet.microsoft.com/dataplatforminsider/2013/09/19/in-memory-oltp-common-design-pattern-high-data-input-rateshock-absorber/.
3737
Every async task in the Data Generator produces a batch of records with random values in order to simulate the data of an IoT power meter.
3838
It then calls a natively compiled stored procedure, that accepts an memory optimized table valued parameter (TVP), to insert the data into an memory optimized SQL Server table.
39-
In addition to the in-memory features, the sample is leveraging System-Versioned Temporal Tables: https://msdn.microsoft.com/en-us/library/dn935015.aspx for building version history,
40-
Clustered Columnstore Index: https://msdn.microsoft.com/en-us/library/dn817827.aspx) for enabling real time operational analytics, and
39+
In addition to the in-memory features, the sample is offloading historical values to a Clustered Columnstore Index: https://msdn.microsoft.com/en-us/library/dn817827.aspx) for enabling real time operational analytics, and
4140
Power BI: https://powerbi.microsoft.com/en-us/desktop/ for data visualization.
4241
*/
4342
namespace ConsoleClient
4443
{
4544
class Program
4645
{
4746
static SqlDataGenerator dataGenerator;
48-
static string connection;
47+
static string[] connection;
4948
static string spName;
5049
static string logFileName;
5150
static string powerBIDesktopPath;
52-
static int tasks;
5351
static int meters;
5452
static int batchSize;
55-
static int delay;
5653
static int commandTimeout;
57-
static int shockFrequency;
58-
static int shockDuration;
59-
static int rpsFrequency;
60-
static int enableShock;
61-
static Timer mainTimer = new Timer();
54+
static int rpsFrequency;
55+
static int numberOfDataLoadTasks;
56+
static int numberOfOffLoadTasks;
57+
static int deleteBatchSize;
58+
static string deleteSPName;
59+
static int dataLoadCommandDelay;
60+
static int offLoadCommandDelay;
61+
static int delayStart;
62+
static int appRunDuration;
63+
static int numberOfRowsOfloadLimit;
6264
static Timer rpsTimer = new Timer();
63-
static Timer shockTimer = new Timer();
6465

6566
static void Main(string[] args)
6667
{
6768
Init();
68-
dataGenerator = new SqlDataGenerator(connection, spName, commandTimeout, meters, tasks, delay, batchSize, ExceptionCallback);
69-
70-
mainTimer.Elapsed += mainTimer_Tick;
69+
dataGenerator = new SqlDataGenerator(connection, spName, commandTimeout, meters, numberOfDataLoadTasks, dataLoadCommandDelay, batchSize, deleteSPName, numberOfOffLoadTasks, offLoadCommandDelay, deleteBatchSize, numberOfRowsOfloadLimit, ExceptionCallback);
7170
rpsTimer.Elapsed += rpsTimer_Tick;
72-
shockTimer.Elapsed += shockTimer_Tick;
71+
7372

7473
string commandString = string.Empty;
7574
Console.ForegroundColor = ConsoleColor.White;
@@ -129,9 +128,7 @@ static async void Start()
129128
{
130129
if (!dataGenerator.IsRunning)
131130
{
132-
if(enableShock == 1) mainTimer.Start();
133131
rpsTimer.Start();
134-
135132
await dataGenerator.RunAsync();
136133
}
137134
}
@@ -144,10 +141,7 @@ static async void Stop()
144141
{
145142
if (dataGenerator.IsRunning)
146143
{
147-
if (enableShock == 1) mainTimer.Stop();
148144
rpsTimer.Stop();
149-
if (enableShock == 1) shockTimer.Stop();
150-
151145
await dataGenerator.StopAsync();
152146
dataGenerator.RpsReset();
153147
}
@@ -177,47 +171,47 @@ static void Init()
177171
{
178172
try
179173
{
174+
int numberOfSqlConnections = ConfigurationManager.ConnectionStrings.Count;
175+
connection = new string[numberOfSqlConnections];
180176
// Read Config Settings
181-
connection = ConfigurationManager.ConnectionStrings["Db"].ConnectionString;
177+
for (int i = 0; i < numberOfSqlConnections; i++)
178+
{
179+
connection[i] = ConfigurationManager.ConnectionStrings[i].ConnectionString;
180+
}
181+
182182
spName = ConfigurationManager.AppSettings["insertSPName"];
183183
logFileName = ConfigurationManager.AppSettings["logFileName"];
184-
powerBIDesktopPath = ConfigurationManager.AppSettings["powerBIDesktopPath"];
185-
tasks = int.Parse(ConfigurationManager.AppSettings["numberOfTasks"]);
186-
meters = int.Parse(ConfigurationManager.AppSettings["numberOfMeters"]);
184+
numberOfDataLoadTasks = int.Parse(ConfigurationManager.AppSettings["numberOfDataLoadTasks"]);
185+
dataLoadCommandDelay = int.Parse(ConfigurationManager.AppSettings["dataLoadCommandDelay"]);
187186
batchSize = int.Parse(ConfigurationManager.AppSettings["batchSize"]);
188-
delay = int.Parse(ConfigurationManager.AppSettings["commandDelay"]);
187+
deleteSPName = ConfigurationManager.AppSettings["deleteSPName"];
188+
numberOfOffLoadTasks = int.Parse(ConfigurationManager.AppSettings["numberOfOffLoadTasks"]);
189+
offLoadCommandDelay = int.Parse(ConfigurationManager.AppSettings["offLoadCommandDelay"]);
190+
deleteBatchSize = int.Parse(ConfigurationManager.AppSettings["deleteBatchSize"]);
191+
meters = int.Parse(ConfigurationManager.AppSettings["numberOfMeters"]);
189192
commandTimeout = int.Parse(ConfigurationManager.AppSettings["commandTimeout"]);
190-
shockFrequency = int.Parse(ConfigurationManager.AppSettings["shockFrequency"]);
191-
shockDuration = int.Parse(ConfigurationManager.AppSettings["shockDuration"]);
192-
enableShock = int.Parse(ConfigurationManager.AppSettings["enableShock"]);
193-
193+
delayStart = int.Parse(ConfigurationManager.AppSettings["delayStart"]);
194+
appRunDuration = int.Parse(ConfigurationManager.AppSettings["appRunDuration"]);
194195
rpsFrequency = int.Parse(ConfigurationManager.AppSettings["rpsFrequency"]);
196+
numberOfRowsOfloadLimit = int.Parse(ConfigurationManager.AppSettings["numberOfRowsOfloadLimit"]);
197+
powerBIDesktopPath = ConfigurationManager.AppSettings["powerBIDesktopPath"];
195198

196199
// Initialize Timers
197-
mainTimer.Interval = shockFrequency;
198-
shockTimer.Interval = shockDuration;
199200
rpsTimer.Interval = rpsFrequency;
200201

201202
if (batchSize <= 0) throw new SqlDataGeneratorException("The Batch Size cannot be less or equal to zero.");
202203

203-
if (tasks <= 0) throw new SqlDataGeneratorException("Number Of Tasks cannot be less or equal to zero.");
204+
if (numberOfDataLoadTasks <= 0) throw new SqlDataGeneratorException("Number Of Tasks cannot be less or equal to zero.");
204205

205-
if (delay < 0) throw new SqlDataGeneratorException("Delay cannot be less than zero");
206+
if (dataLoadCommandDelay < 0) throw new SqlDataGeneratorException("Delay cannot be less than zero");
206207

207208
if (meters <= 0) throw new SqlDataGeneratorException("Number Of Meters cannot be less than zero");
208209

209-
if (meters < batchSize * tasks) throw new SqlDataGeneratorException("Number Of Meters cannot be less than (Tasks * BatchSize).");
210+
if (meters < batchSize * numberOfDataLoadTasks) throw new SqlDataGeneratorException("Number Of Meters cannot be less than (Tasks * BatchSize).");
211+
210212
}
211213
catch (Exception exception) { HandleException(exception); }
212214
}
213-
static void mainTimer_Tick(object sender, ElapsedEventArgs e)
214-
{
215-
if (dataGenerator.IsRunning)
216-
{
217-
dataGenerator.Delay = 0;
218-
shockTimer.Start();
219-
}
220-
}
221215
static void rpsTimer_Tick(object sender, ElapsedEventArgs e)
222216
{
223217
try
@@ -236,11 +230,5 @@ static void rpsTimer_Tick(object sender, ElapsedEventArgs e)
236230
}
237231
catch (Exception exception) { HandleException(exception); }
238232
}
239-
static void shockTimer_Tick(object sender, ElapsedEventArgs e)
240-
{
241-
Random rand = new Random();
242-
dataGenerator.Delay = rand.Next(1500, 3000);
243-
shockTimer.Stop();
244-
}
245233
}
246234
}

0 commit comments

Comments
 (0)