C# api slow to open bucket in dot net core

I am using the c# api for connecting to CouchBase. On full framework it runs fine. On dot net core, the exact same code takes 10 seconds to open a bucket. Any ideas why it’s so slow?

My code looks like this:

LoggerFactory loggerFactory = new LoggerFactory();
loggerFactory.AddNLog(new NLogProviderOptions {
	CaptureMessageTemplates = true, CaptureMessageProperties = true
});
NLog.LogManager.LoadConfiguration("nlog.config");

var config = new ClientConfiguration
{
	LoggerFactory = loggerFactory, Servers = new List<Uri> { new Uri("http://127.0.0.1:8091") }, UseSsl = false,
	BucketConfigs = new Dictionary<string, BucketConfiguration> { {
		"test", new BucketConfiguration {
			Username = "test", Password = "xxx", BucketName = "test", 
			PoolConfiguration = new PoolConfiguration {
				MaxSize = 10, MinSize = 2
			}
		}
	}},
	ConfigurationProviders = ServerConfigurationProviders.HttpStreaming
};

var cluster = new Cluster(config);
cluster.Authenticate(new PasswordAuthenticator("test", "testtest"));
var bucket = cluster.OpenBucket("test");

The issue seems to be with “Waiting to check configs”… it takes ten seconds.

If I set

ConfigPollEnabled = false 

It still hangs for 10 seconds:

Hi @rocklan,

Thanks for posting some more details here!

First, I’m trying to reproduce this in console app(s). I think I installed the correct logging/NLog packages (Microsoft.Extensions.Logging 3.1.2 and NLog.Extensions.Logging 1.6.1). Is that correct, and if not, could you spell those out for me (and which versions you’re using?

Secondly, LoggerFactory does not appear to be a property of ClientConfiguration, at least with Couchbase .NET SDK version 2.7.16 (latest version). Which version of the .NET SDK are you using?

If you have a repo handy with the smallest simple examples of your code in .NET Core and .NET Framework that are reproducing the issue, and can post that to GitHub or something, that would also be tremendously helpful, especially if this turns out to be a bug, I can just add your example to the JIRA ticket.

@rocklan -

The slowness is likely related to the bucket type being Memcached and the bootstrap routine. The SDK by default tries to bootstrap using CCCP and then falls back to HTTP Streaming if it cannot connect; Memcached buckets only support HTTP Streaming, so there is a delay.

The easiest fix if this is the case is to set the ClientConfiguration.ConfigurationProviders to only use HttpStreaming.

-Jeff

Hi @jmorris if you take a look at the code that I took the time to post you can see that I am already setting ClientConfiguration.ConfigurationProviders to HttpStreaming. But I don’t understand why it’s only happening in dot net core.

@matthew.groves version 2.7.16 of the client library. It sure seems like LoggerFactory is a property of ClientConfiguration to me. I am using 1.6.1 of NLog.Extensions.Logging.

Code available here: https://github.com/rocklan/couchbase-example

Ah, missed that @rocklan. The “Waiting to check configs” part is from the asynchronous config-monitoring component and not directly related to bootstrapping. More likely the delay is from this being the initial call to HttpClient; I suspect warming up the end-point would speed up subsequent requests. Why this is only on Core is not clear; Core is a completely different code-base though, so perhaps its the implementation.

-Jeff

@jmorris can someone look into it?

@rocklan -

What I meant was that the Couchbase SDK code for HTTP Streaming is the same for .NET Full and for Core, however, .NET Core and Full have their own implementation of System.Net.Http.HttpClient - that may be the difference. We have seen in the past (and others) that the initial call to service endpoint is slow, but subsequent requests are fast. I suspect that this is what you are seeing.

In some cases, a proxy may also slow things down, but would suspect that its not tied to the runtime version; you would see it both with .NET Core and Full Frameworks. You may need to do some sleuthing on your own too see where the bottleneck is.

If you would like, you can file an NCBC as well: Loading.... Which will be triaged, back-logged and assigned to a future release; from experience I doubt it’s going to be resolvable at the SDK level for you.

Additionally, I would suggest using a Couchbase (persistent) bucket as they bootstrap faster and have far more fetaures than Memcached buckets.

-Jeff

Thanks @jmorris, I’m only investigating Couchbase to use it as an in-memory cache for my dot net apps. I’m not going to do any more sleuthing on my own, I’ve added logging and reported a fully reproducible issue and spent enough time on this… adding 10 seconds to startup of all of my apps and api’s is not going to be workable.

@rocklan nonetheless, I created a Jira ticket, thanks for reporting! Note that Couchbase buckets use Memcached as a cache, so writing and reading will always be from memory for basic K/V operations. The API is the same as Memcached, but you also have N1QL, Analytics, Views and Search capability and Search capabilities.

Somewhat related: you can use “Ephemeral” buckets in Couchbase instead of memcached buckets. Like Couchbase buckets, these provide all the scaling/services benefits that @jmorris mentioned, but they are memory-only.

Independent of the actual cause, there is arguably a benefit to moving slower external calls out of the direct start up of your application. Personally I run opening the bucket in .NET Core on a hosted service as a ‘background warm-up step’. .NET Core is also increasingly hating on synchronous long running tasks, so using cluster.OpenBucketAsync should be a default go-to.

Since I happened to have a project open with Couchbase I looked at the start up time, I am seeing around 130 milliseconds for OpenBucketAsync to complete in a .NET Core 3.1 project.