I am currently working on a C# Azure Function that is triggered by an HTTP request. The function's purpose is to extract raw data from Azure Table Storage and output it to the user in the form of a large JSON object. However, I have observed that as the amount of data I am processing grows, it takes an increasingly long time for the API to complete the extraction process.
To provide some context, I have IoT sensors that send messages to my storage once every minute. When I attempt to extract data spanning multiple days, I have noticed significant performance issues compared to extracting data directly from Azure Table Storage.
I am now seeking input from others who have encountered similar issues. Specifically, I am wondering whether using a List object could be contributing to the slowdown. I have read that List objects can be resource-intensive compared to simple preset arrays.
However, I am hesitant to switch to using an array, since I do not know the size I will need to allocate in advance of downloading the data.
Any insights or advice would be greatly appreciated. Thank you in advance for your help!
This an example of my code:
public static List<AzureTableSensorPlotData> Read_Azure_IoT_Device_For_App_Graph_View(bool average_data,string tableid, string partitionKey_start, string partitionKey_end, string rowKey_start, string rowKey_end, string id, ILogger log)
{
CloudStorageAccount storageAccount;
storageAccount = CloudStorageAccount.Parse(Environment.GetEnvironmentVariable("AzureTableAccount"));
CloudTableClient tableClient = storageAccount.CreateCloudTableClient(new TableClientConfiguration());
// Create a table client for interacting with the table service
CloudTable table = tableClient.GetTableReference(tableid);
TableOperation retrieveOperation = TableOperation.Retrieve<IoTDeviceEntity>(partitionKey_start, rowKey_start);
string PartitionKey_filter1 = TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.GreaterThanOrEqual, partitionKey_start);
string PartitionKey_filter2 = TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.LessThanOrEqual, partitionKey_end);
string PartitionKey_combinedFilter = TableQuery.CombineFilters(PartitionKey_filter1, TableOperators.And, PartitionKey_filter1);
string RowKey_filter1 = TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.GreaterThanOrEqual, rowKey_start);
string RowKey_filter2 = TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.LessThanOrEqual, rowKey_end);
string RowKey_combinedFilter = TableQuery.CombineFilters(RowKey_filter1, TableOperators.And, RowKey_filter2);
string total_combinedFilter = TableQuery.CombineFilters(PartitionKey_combinedFilter, TableOperators.And, RowKey_combinedFilter);
log.LogWarning("Azure Table Query:" + total_combinedFilter);
TableQuery<IoTDeviceEntity> myquery = new TableQuery<IoTDeviceEntity>().Where(total_combinedFilter);
//List<IoTDeviceEntity> Read_device_data = new List<IoTDeviceEntity>();
List<AzureTableSensorPlotData> Read_device_data_plot_data = new List<AzureTableSensorPlotData>();
foreach (IoTDeviceEntity item in table.ExecuteQuery<IoTDeviceEntity>(myquery))
{
AzureTableSensorPlotData temp_data = new AzureTableSensorPlotData();
temp_data.Timestamp = item.Timestamp;
temp_data.iot_battery = item.iot_battery;
temp_data.iot_signal = item.iot_signal;
….
Read_device_data_plot_data.Add(temp_data);
}
return Read_device_data_plot_data;
}
List<AzureTableSensorPlotData> data_device = AzureTable.Read_Azure_IoT_Device_For_App_Graph_View(average_data, "AzureDevice" + device_plot, year_month_start, year_month_end, End_ticks, Start_ticks, id, log);
var result = data_device.OrderByDescending(d => d.Timestamp);
jsonToReturn = JsonConvert.SerializeObject(result);
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
return id != null
? (ActionResult)new OkObjectResult(jsonToReturn)
: new BadRequestObjectResult("Please pass a name on the query string or in the request body")
I am downloading about 20-30K rows of sensor data. Each Day will have 1 row for each min
List<>
can be sufficient if the use-case isn't performance-sensitive, but it sounds like yours is. That said, a better choice might depend on exactly what you need from the collection -- for example, a linked-list would tend to be efficient to add to, though it can have trade-offs such as no default-indexing and higher memory-usage.