CoreWCF / CoreWCF

Main repository for the Core WCF project
MIT License
1.62k stars 280 forks source link

why corewcf slower than .netframework wcf #395

Open wp0372176 opened 2 years ago

wp0372176 commented 2 years ago

basically, .net core webapi 2x faster than .net framework webapi 。 but corewcf slower than .net framework wcf

TestDemo:

[System.ServiceModel.ServiceContract]
[CoreWCF.ServiceContract]
public interface ITest
{
    [System.ServiceModel.OperationContract]
    [CoreWCF.OperationContract]
     string GetTest1();

}

[CoreWCF.ServiceBehavior(ConcurrencyMode = CoreWCF.ConcurrencyMode.Multiple, InstanceContextMode = CoreWCF.InstanceContextMode.Single)]

public partial class Test : ITest
{
    public string GetTest1()
    {
        return "1234567890";
    }
}
birojnayak commented 2 years ago

@wp0372176 could you please provide more details ? If possible list down more details on component level . We have an issue #337 which we are planning to fix by end of year and above information would definitely help

fbenoit-coexya commented 1 month ago

I am encountering a slowness problem as well: On localhost, a net.tcp call that AFAIK doesn't attempt any security negotiation, for a method that simply returns an array containing a single integer, takes about two seconds per call. Not only on the first call, but also on each subsequent one.

Edit: Due to bank holidays where I live I won't be available for a few days. In the meantime I'll see if I can try and make a minimal example that reproduces the problem.

mconnew commented 1 month ago

This is an ipv4 vs ipv6 issue. Server is only listening on ipv4, client is trying ipv6, timing out, then trying ipv4. Modify your service to listen on ipv6 instead, and it will listen on ipv6 and ipv4.

fbenoit-coexya commented 1 month ago

This is an ipv4 vs ipv6 issue. Server is only listening on ipv4, client is trying ipv6, timing out, then trying ipv4. Modify your service to listen on ipv6 instead, and it will listen on ipv6 and ipv4.

Thank you very much! Replacing IPAddress.Any with IPAddress.IPv6Any in my UseNetTcp() call fixed the problem indeed.

fbenoit-coexya commented 1 month ago

Still I'm a bit at a loss as to why the client times out rather than getting an instant WSAECONNREFUSED: I have DisableStealthMode configured on both Standard/Private and Domain, in both HKLM\SYSTEM\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\ and HKLM\SOFTWARE\Policies\Microsoft\WindowsFirewall\ Is there yet another separate setting to disable stealth mode for IPv6?

mconnew commented 1 month ago

@fbenoit-coexya, I noticed a subtlety I had missed in an earlier comment. The 2 second delay on each call suggests you are creating a new socket connection for every call. Are you using Streamed transfer mode as that initiates a new connection for every request. That still wouldn't completely explain the 2 second delay on every request though as WCF/CoreWCF enable connection reuse. When a client channel is closed, it gets placed into an idle connection pool and when another connection is needed to the same host, it grabs one from the pool. Unless you've made some connection pool setting changes, this is odd behavior.

What exception are you getting? What's the error message?

fbenoit-coexya commented 1 month ago

I had no visible error at any point, only the (then-)slowdown.

What my code does: I noticed when I said "second call" it was ambiguous. The client code creates a new ChannelFactory and Channel for each call (to reflect the final product, which will have several servers behind a load balancer).

Before I replaced IPAddress.Any with IPAddress.IPv6Any on the server side, each connection would take two second to establish (but showed no error message). After I replaced it, the slowness disappeared: Three consecutive calls went from 6s to 60ms, a hundred times faster.

It only dawned on me afterwards that "client is trying ipv6, timing out, then trying ipv4" conflicted with "wait, i've disabled that thrice-damned stealth mode, why was the ipv6 attempt timing out instead of getting rejected?"

When a client channel is closed, it gets placed into an idle connection pool and when another connection is needed to the same host, it grabs one from the pool. Unless you've made some connection pool setting changes, this is odd behavior.

This is where a subtlety I hadn't mentioned comes into play. The program was a proof-of-concept for a master/slave architecture. Browser → OpenAPI server → Master server ⇶ 3×Slave server I opened my browser, started all five server processes (everything on localhost), and each "call" was me F5-ing the browser tab with the request. Each time I F5'd, the master server would connect and call the three slave servers in sequence (because it was a simple PoC), so it would be three consecutive calls but to different ports. (which used to take a total of 6s until I fixed the IPv6 issue).

I do not know whether I am "using Streamed transfer mode". I have set a bindingConfiguration but all it does is change the readerQuotas and (for now) disable security.