Асинхронный вызов БД - медленнее, чем синхронизация - PullRequest
0 голосов
/ 30 ноября 2018

Программа написана на C #.Он последовательно получает данные из концентратора событий и создает запись в sql db.

Чтобы улучшить производительность, я сделал sql insert async.

На моем локальном компьютере, 8 ГБ оперативной памяти и 4 ядра, асинхронная версия кода работает быстрее, чем версия синхронизации.

Где, как в Dev сервере / среде (одноядерный, 1,75 ГБ).Асинхронная версия работает медленнее, чем синхронная версия.

Я увеличил масштаб сервера / среды разработки (2 ядра, 3,5 ГБ).Асинхронная версия улучшена, но по-прежнему работает медленнее, чем синхронная версия.

Насколько я понимаю, независимо от ядер процессора и размера оперативной памяти, асинхронная версия должна работать лучше, чем версия синхронизации.

Ваши мысли по этому поводу?

Фрагмент кода

// Метод ManageGeoSpetialData будет вызываться для каждого события, которое будет // извлечено из концентратора событий.

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;
        }
    }
...