RevenantX / LiteNetLib

Lite reliable UDP library for Mono and .NET
https://revenantx.github.io/LiteNetLib/index.html
MIT License
3.01k stars 490 forks source link

Implement sliding window scale logic. #110

Open lzaiats opened 6 years ago

lzaiats commented 6 years ago

I have been testing LiteNetLib, Lidgren-gen3 and Lidgren-old (the one from Google Code) and Lidgren-old is beating the competitors by far... On my test I have 750 clients connected to a single server instance, receiving ~15 reliable msgs/s and ~100 unreliable msgs/s and Lidgren-old can handle all this data perfectly! Using the same "game code" but using Lidgren-gen3 or LiteNetLib the test "fails" between 100 and 120 clients... Maybe I am missing something with LiteNetLib API, so I can achieve better performance... Do you have any idea where I am doing wrong with your Lib? If you need I can share the code :)

Thanks and keep the awesome work!

DanisJoyal commented 6 years ago

@RevenantX There is a huge difference running the application via Visual Studio or by launching the application from explorer. Even if you are in release. Or, you may run without debugging. CTRL-F5

nxrighthere commented 6 years ago

Strange... It's must be more than enough.

RevenantX commented 6 years ago

@DanisJoyal ok i will test as separate application.

RevenantX commented 6 years ago

@nxrighthere @DanisJoyal received better results withou merge. As separate application. Clients failed both on 714. But CPU usage was lower before fixes. @nxrighthere can you please check on you machine both branches(https://github.com/RevenantX/LiteNetLib/tree/master and https://github.com/RevenantX/LiteNetLib/tree/optimisation) and test?

nxrighthere commented 6 years ago

Sure, give me some time.

DanisJoyal commented 6 years ago

@RevenantX Wow! It really surprises me. Im testing with your new reliable optimisation. Maybe CPU usage its higher on mine. I have improve that, but it failed at 714 ??? ... very strange. I didnt trick the screenshot !! Anyway ... thats fine.

RevenantX commented 6 years ago

@DanisJoyal 714 peers.

DanisJoyal commented 6 years ago

@RevenantX I know. The ??? means that Im very confused about your results. I dont know what to think.

nxrighthere commented 6 years ago

Well, the master branch: 652 started, 638 connected, 0 dropped (CPU usage 57%). Everything going well, but after some time the application is crashed with the error:

System.NullReferenceException: in LiteNetLib.NetPeer.SendRawData(NetPacket packet) in LiteNetLib.ReliableChannel.SendNextPackets()) in LiteNetLib.NetPeer.Flush() in LiteNetLib.NetPeer.Update(Int32 deltaTime) in LiteNetLib.NetManager.UpdateLogic() in System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) in System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) in System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) in System.Threading.ThreadHelper.ThreadStart() System.NullReferenceException: Ссылка на объект не указыinает на экземпляр объекта. in LiteNetLib.NetPeer.SendRawData(NetPacket packet) in LiteNetLib.ReliableChannel.SendNextPackets() in LiteNetLib.NetPeer.Flush() in LiteNetLib.NetPeer.Update(Int32 deltaTime) in LiteNetLib.NetManager.UpdateLogic() in System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) in System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)

The second branch: 1000 started, 1000 connected, 0 dropped (CPU usage 87%). A test has been completed in 6 minutes (must be completed in 2 minutes), but it's passed with 99.9% result. At the end of the process, almost the all clients are dropped for some reason.

DanisJoyal commented 6 years ago

@nxrighthere Previously, you wasnt able to reach 1000 clients ? Now, you can ?

nxrighthere commented 6 years ago

Yes, that's true.

RevenantX commented 6 years ago

@nxrighthere yeah there is bug (very rare o_o) in reliable channel after optimisation. I will try fix.

DanisJoyal commented 6 years ago

@RevenantX Do we have access to your application test ? Seriously, the way to test does all the difference. From, @lzaiats UDPCLientBench to benchmarkNet .... there is a huge difference.

RevenantX commented 6 years ago

@DanisJoyal i am using BenchmarkNet.

DanisJoyal commented 6 years ago

@RevenantX Ok. But, I didnt use the source code. Im using the binary application. Im just replacing the litenetlib.dll in the folder. Otherwise, be sure that its compiling in x64.

nxrighthere commented 6 years ago

I recompiling the application and references every time with Roslyn.

RevenantX commented 6 years ago

@nxrighthere @DanisJoyal fixed reliable channel.

nxrighthere commented 6 years ago

After 900 connections, the clients are starts dropping and the process slowly freezes.

RevenantX commented 6 years ago

@nxrighthere @DanisJoyal checked both versions after fix. Got almost same results in both cases (1000 clients work without drops 50-58% cpu usage).

nxrighthere commented 6 years ago

I have no idea why we got the different results...

RevenantX commented 6 years ago

@nxrighthere @DanisJoyal better will be continue this conversation in some messenger (skype, telegram, etc.)

nxrighthere commented 6 years ago

It looks like the search in Skype is broken right now... I unable to find you.

RevenantX commented 6 years ago

@nxrighthere same thing.

RevenantX commented 6 years ago

@nxrighthere i will partially implement your optimizations. And compare to all optimizations later.

DanisJoyal commented 6 years ago

@nxrighthere @RevenantX you can use mattermost.

https://about.mattermost.com/download/#mattermostApps

the url server is https://demo.mattermost.com/

The room or channel is https://demo.mattermost.com/space-motors/channels/litenetlib

mattermost

DanisJoyal commented 6 years ago

Hi, sorry, I changed the room name:

https://demo.mattermost.com/space-motors/channels/litenetlib-discussion

DanisJoyal commented 6 years ago

@RevenantX Hi, I was comparing Enet with C# SendTo. Enet uses WSASendTo that it does buffer management in none blocking mode. You may send 1K byte and it will immediately return 1K sent even if its not sent. It will send it later.

C# Use UnsafeNclNativeMethods.OSSOCK.sendto instead of UnsafeNclNativeMethods.OSSOCK.WSASendTo.

Its unfair :) Ive tried in none blocking mode. Doesnt change anything except that SendTo is faster, but ReceiveFrom is sucking. ReceiveFrom is none blocking too ... always have to check.

Cheers

https://github.com/Microsoft/referencesource/blob/master/System/net/System/Net/Sockets/Socket.cs

http://labs.developerfusion.co.uk/SourceViewer/browse.aspx?assembly=SSCLI&namespace=System.Net&type=UnsafeNclNativeMethods

RevenantX commented 6 years ago

@DanisJoyal this will work for windows (for now without implementation for linux, osx, android, etc.). I've added winsock usage. So you can test this by selecting WIN32_UNSAFE build type in LiteNetLib project.

RevenantX commented 6 years ago

@DanisJoyal @nxrighthere added ReleseUnsafeWin32 version. And fixed reliable channel. So now just release version almost hit 1000 clients (~990). And ReleaseUnsafeWin32 (with just native sendto, receivefrom) passes test. @DanisJoyal so don't optimize not bottleneck places) This is just socket calls)

RevenantX commented 6 years ago

@nxrighthere you can add to bench unsafe version separately)

nxrighthere commented 6 years ago

@RevenantX Great work! I'll update it now.

nxrighthere commented 6 years ago

Okay, unsafe version is working much better! But, after 700 connections CPU usage raises 92% and the whole process becomes unresponsive. I monitored what's was happening and I found that more than 60% of the time is spent in GC and my CPU just can't handle it. Generation zero grows dramatically. With enabled Sustained Low Latency, it works better, but GC is still killing the performance.

RevenantX commented 6 years ago

@nxrighthere

Compared to ENet time in GC is 5%.

C library -> GC :) But this is strange anyway. I slightly reduced possible place in "receive" method.

nxrighthere commented 6 years ago

Yes, you are right, this comparison is inappropriate.

nxrighthere commented 6 years ago

Works better, now 750 connections is reached. The overall CPU usage and the generation zero are more stable. No drops by the way. The result with 700 clients. The old version can't complete the test with more than 550 clients. Very nice progress!

nxrighthere commented 6 years ago

I'm so confused right now... I did a test with the old version of Lidgren as @lzaiats suggested, and you know what? It's passed the test with 1000 clients... CPU usage 60%, memory consumption 360 megabytes.

lzaiats commented 6 years ago

@nxrighthere Bingo! :) The old lidgren version is far better than the gen3, and its also almost the same performance than ENet... Amazing ;)

DanisJoyal commented 6 years ago

Thats funny. So, you re telling me that google are so dumb to create a new version of the lib worst than the first one. I think that it s an issue from the .Net Framework. Maybe you can try the old Lidgren to use .Net Framework > 4.5. I didnt have time since 1 week to continue my investigation. But, I saw that the framework its not using the same sendto function as Enet. I will check that this week end. Cheers.

nxrighthere commented 6 years ago

I'm using .NET Framework 4.7.1 for all libraries.

DanisJoyal commented 6 years ago

You re overwriting the framework set by default ? The old lidgren is using .Net Framework 2.0. Anyway, if Lidgren is able to do it. LiteNetLib should be able too.

nxrighthere commented 6 years ago

I'm not using the csproj at all, I compile everything directly with Roslyn.

RevenantX commented 6 years ago

@nxrighthere @DanisJoyal added DISABLE_IPV6 ifdef. So you can disable ipv6 thread (so this is 1000 less threads in that test). Passed test with 1200 clients.

nxrighthere commented 6 years ago

Yea, works better now. 900 clients are connected and after that the CPU usage raises 92% and the application becomes unresponsive. But very nice anyway.

nxrighthere commented 6 years ago

GC is still the biggest performance killer. I tried to build the library with built-in Roslyn's optimization logic and now 950 connections is reached, but the server thread just crashed.

nxrighthere commented 6 years ago

[Link removed] @DanisJoyal @RevenantX!

RevenantX commented 6 years ago

@nxrighthere O_o. There is crash and bytes count is diffferent...

nxrighthere commented 6 years ago

Yea, it breaks for some reason.

nxrighthere commented 6 years ago

Now it works much better.

RevenantX commented 6 years ago

@nxrighthere how?

nxrighthere commented 6 years ago

https://github.com/DanisJoyal/LiteNetLib/commit/69e8244fd48076b52e1503ad9cf7b624e8c31ce5 https://github.com/DanisJoyal/LiteNetLib/commit/104fbf20b31d1f394e27c1ba9dc74a1feae1d371