Shiv
Shiv

Reputation: 201

High CPU usage after using Redis cache in c# async

I am using https://github.com/StackExchange/StackExchange.Redis. (StackExchange.Redis.StrongName.1.2.1)

I have a async function like this which causes CPU to 100% and start getting timeout error after 4-5 min after serving 400 requests

 public async Task<T> GetOrSetAsync<T>(string cacheKey, Func<Task<T>> getItemCallback) where T : class
         {
             T item = null;
             IDatabase cache = Connection.GetDatabase();
             var cacheValue = await cache.StringGetAsync(cacheKey);
            if (cacheValue.IsNull)
            {
                item = await getItemCallback();
                await cache.StringSetAsync(cacheKey, JsonConvert.SerializeObject(item));
            }
            else
            {
                item = await Task.Factory.StartNew(() => JsonConvert.DeserializeObject<T>(cacheValue));
            }
             return item;
         }

If i stop using redis cache and return direct values from DB, I am able to execute a load of 1300 request in 2 min 20 sec. CPU high still able to complete load.

 public async Task<T> GetOrSetAsync<T>(string cacheKey, Func<Task<T>> getItemCallback) where T : class
         {
            return await getItemCallback();
         }

If i just modify function below to getDatabase and do nothing. it cause the CPU to goto 100% immediately and stuck after 200 requests in 2 min , which is because of high CPU.

 public async Task<T> GetOrSetAsync<T>(string cacheKey, Func<Task<T>> getItemCallback) where T : class
         {
           IDatabase cache = Connection.GetDatabase();
            return await getItemCallback();
         }

But question is why CPU usage increased only with addition of

IDatabase cache = Connection.GetDatabase(); ?

Upvotes: 2

Views: 2390

Answers (1)

Carl Dacosta
Carl Dacosta

Reputation: 891

How is your "Connection" property implemented? Is it creating a new connection to Redis on each call? If so, that would not be recommended. You should share a single connection across your calls.

private static Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() =>
{
    return ConnectionMultiplexer.Connect("<your connection string here>");
});

public static ConnectionMultiplexer Connection
{
    get
    {
        return lazyConnection.Value;
    }
}

Upvotes: 2

Related Questions