I want to optimize My server side speed and performance to manage clients, I think I have two way to mange them:
1.Create manually one thread per client connection
2.create SynchronizationContext per client (this will manage threads on background)
Suppose We have one million users connected:
The first way is faster but I don't know is optimize and better way to manage send/receive data from client or not?
What is your suggestion to make better performance and speed to manage all of clients without lags and hangs?
My example to test SynchronizationContext and multi thread on console:
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace SynchronizationContextForMethod
{
public class ServiceClass
{
public void Login(string name)
{
OperationContext<ClientInfo>.Current = new ClientInfo() { Name = name };
}
public string WhatIsMyName()
{
return OperationContext<ClientInfo>.Current.Name;
}
}
public class ClientInfo
{
public string Name { get; set; }
public string UserName { get; set; }
}
public class OperationContext<T>
{
static ConcurrentDictionary<SynchronizationContext, T> ContextByThread = new ConcurrentDictionary<SynchronizationContext, T>();
public static T Current
{
get
{
ContextByThread.TryGetValue(SynchronizationContext.Current, out T value);
return value;
}
set
{
ContextByThread.TryAdd(SynchronizationContext.Current, value);
}
}
public static void EncContext()
{
ContextByThread.TryRemove(SynchronizationContext.Current, out T value);
}
}
class Program
{
static List<SynchronizationContext> _contexts = new List<SynchronizationContext>();
static void Main(string[] args)
{
ThreadPool.GetMaxThreads(out int worker, out int ports);
ThreadPool.SetMaxThreads(int.MaxValue, int.MaxValue);
Console.WriteLine("thread count : " + Process.GetCurrentProcess().Threads.Count);
SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
_contexts.Add(SynchronizationContext.Current);
var service = new ServiceClass();
for (int i = 0; i < 20; i++)
{
//PostWithNewThread((state) =>
PostNormally((state) =>
{
GC.Collect();
if (SynchronizationContext.Current == null)
{
SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
}
else
{
//no run ever
}
Console.WriteLine("thread count : " + Process.GetCurrentProcess().Threads.Count);
var name = state.ToString();
service.Login(name);
var isTrue = name == service.WhatIsMyName();
if (!isTrue)
{
//if false this is wrong code!
}
Console.WriteLine($"service login {name}: " + isTrue);
Thread.Sleep(5000);
Console.WriteLine($"service " + name + " finished");
OperationContext<ClientInfo>.EncContext();
}, "ali" + i);
Console.WriteLine("thread count : " + Process.GetCurrentProcess().Threads.Count);
//PostWithNewThread((state) =>
PostNormally((state) =>
{
GC.Collect();
if (SynchronizationContext.Current == null)
{
SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
}
else
{
//no run ever
}
Console.WriteLine("thread count : " + Process.GetCurrentProcess().Threads.Count);
var name = state.ToString();
service.Login(name);
var isTrue = name == service.WhatIsMyName();
if (!isTrue)
{
//if false this is wrong code!
}
Console.WriteLine($"service login {name}: " + isTrue);
Console.WriteLine($"service " + name + " finished");
OperationContext<ClientInfo>.EncContext();
}, "reza" + i);
Console.WriteLine("thread count : " + Process.GetCurrentProcess().Threads.Count);
//PostWithNewThread((state) =>
PostNormally((state) =>
{
GC.Collect();
if (SynchronizationContext.Current == null)
{
SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
}
else
{
//no run ever
}
Console.WriteLine("thread count : " + Process.GetCurrentProcess().Threads.Count);
Thread.Sleep(2000);
var name = state.ToString();
service.Login(name);
var isTrue = name == service.WhatIsMyName();
if (!isTrue)
{
//if false this is wrong code!
}
Console.WriteLine($"service login {name}: " + (isTrue));
Console.WriteLine($"service " + name + " finished");
OperationContext<ClientInfo>.EncContext();
}, "hassan" + i);
}
Console.WriteLine("thread count : " + Process.GetCurrentProcess().Threads.Count);
while (true)
{
GC.Collect();
Thread.Sleep(1000);
Console.WriteLine("thread count : " + Process.GetCurrentProcess().Threads.Count);
}
}
public static void PostNormally(SendOrPostCallback run, object state)
{
SynchronizationContext.Current.Post(run, state);
}
public static void PostWithNewThread(SendOrPostCallback run, object state)
{
Thread thread = new Thread(() =>
{
run(state);
});
thread.IsBackground = true;
thread.Start();
}
}
}