Async db call - slower than sync

1.2k Views Asked by At

The program is written in C#. It gets data one by one sequentially from event hub and makes an entry to sql db.

To improve is performance, I made the sql insert async.

In my local machine 8 GB ram and 4 core, Async version of code performs faster than the sync version.

Where as in Dev server/environment (single core, 1.75 GB). Async version performs slower than sync version.

I scaled up Dev server/environment (2 cores, 3.5 gb). Async version is improved but still performs slower than sync version.

My understanding irrespective of the CPU cores and ram size, async version should perform better than sync version.

Your thoughts on this?

Code snippet

// ManageGeoSpetialData method will be called for every event that will be //pulled from event hub.

public class EventConsumer : IEventConsumer
{
    private static readonly ILog4NetService Log = new Log4NetService(MethodBase.GetCurrentMethod().DeclaringType);
    private readonly IConsumerFactory _consumerFactory;
    private readonly IPublisherFactory _publisherFactory;
    private readonly IDataAccessLayer _dataAccess;
    private IPublisher _ehPublisher;

    public EventConsumer(IConsumerFactory consumerFactory, IPublisherFactory publisherFactory, IDataAccessLayer dataAccess)
    {
        _consumerFactory = consumerFactory;
        _publisherFactory = publisherFactory;
        _dataAccess = dataAccess;
    }

    public void Process()
    {
        Log.Info("CheckPointLogic Process Called ");
        try
        {
            ManageGeoSpetialLogic("Eventhub","Eventhub");
        }
        catch (Exception ex)
        {
            Log.Error("Error in CheckPointLogic Process Method : " + ex.Message);
        }
    }

    private void ManageGeoSpetialLogic(string consumerName, string publisherName)
    {
        Log.Info("Manage CheckPointLogic Called with Consumer : " + consumerName);
        _ehPublisher = _publisherFactory.Get(publisherName);
        var consumer = _consumerFactory.Get(consumerName);
        consumer.Consume(ManageGeoSpetialData);
        Log.Info("Consumer Method called ");
    }

    public async void ManageGeoSpetialData(object data)
    {
            try
            {
                _ehPublisher = _ehPublisher ?? _publisherFactory.Get(Apps.Terra.Messaging.Publisher.Constants.PublisherTypes.Eventhub);
                GeoBoundaryEvent geoBoundaryInfo = null;
                object transactionID = new object();
                if (data is EventData eventInfo)
                {
                    var value = Encoding.UTF8.GetString(eventInfo.Body.ToArray());
                    geoBoundaryInfo = JsonConvert.DeserializeObject<GeoBoundaryEvent>(value);
                    geoBoundaryInfo.SetEventType();
                    eventInfo.Properties.TryGetValue(EventProperties.TransactionIdProperty, out transactionID);
                }

                if (geoBoundaryInfo != null)
                {
                    geoBoundaryInfo.AssetLocationTimestamp = DateTime.ParseExact(geoBoundaryInfo.AssetLocationTimestamp.ToString("yyyy-MM-dd HH:mm:ss.fff"), "yyyy-MM-dd HH:mm:ss.fff", null);
                    geoBoundaryInfo.AssetLocationTimestamp = DateTime.SpecifyKind(geoBoundaryInfo.AssetLocationTimestamp, DateTimeKind.Utc);

                    // geoBoundaryInfo.AssetGeofenceID = _dataAccess.AddGeofenceEventInfo(geoBoundaryInfo); //Db Call

                    geoBoundaryInfo.AssetGeofenceID = await _dataAccess.AddGeofenceEventInfoAsync(geoBoundaryInfo);

                    EventData eventData = new EventData(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(geoBoundaryInfo)));
                    _ehPublisher.Publish(eventData);   //EH publish
                }
            }
            catch (Exception ex)
            {
                Log.Error($"Error in ManageGeoSpetialData {ex.Message}");
            }
    }
}


//Business layer method
public async Task<long> AddGeofenceEventInfoAsync(GeoBoundaryEvent geoBoundaryEvent)
    {
        //Need to change query for update
        var query = @"INSERT INTO AssetGeofence(AssetType,AssetDSN,AssetLocationDatetime,AlertDateTime,GeoBoundaryAssetType,GeoBoundaryAssetDSN,fk_EventTypeID,GeoFenceName,GeoFenceID,IsActive) Output Inserted.AssetGeofenceID values 
                     (@AssetType,@AssetDeviceSerialNumber,@AssetLocationTimestamp,@AlertTimestamp,@GeoBoundaryAssetType,@GeoBoundaryAssetDeviceSerialNumber,@fk_EventTypeID,@GeoFenceName,@GeoFenceId,1);";
        var task = _dbConnection.ExecuteQueryAsync<long>(query, geoBoundaryEvent);
        var result = await task;
        return result[0];


    }

//Data layer method
    public async Task<List<T>> ExecuteQueryAsync<T>(string sql, object param)
    {
         using (var connection = GetConnection())
         {
            connection.Open();
            var task = connection.QueryAsync<T>(sql, param, commandTimeout: 100);
            await task;
            var result = task.GetAwaiter().GetResult().ToList();
            connection.Close();
            return result;
        }
    }
0

There are 0 best solutions below