首页 > 其他分享 >网络发包的优化

网络发包的优化

时间:2022-11-18 15:23:01浏览次数:48  
标签:count Console socket int sw 网络 发包 new 优化

网络发送数据包,现成的接口Socket.Send在我的电脑上大概会有700us左右的耗时,如果使用SendAsync开销会更大,并且会导致数据包的乱序。
Send阻塞接口慢的原因一方面底层会跑很多代码,另一方面有线程就有竞争,有竞争就有加锁。
于是写了一个轻量的Queue来加速网络发包,平均耗时从70us降低到300ns。

public static void Main1()
{
    // create the socket
    Socket listenSocket = new Socket(AddressFamily.InterNetwork,
                                     SocketType.Stream,
                                     ProtocolType.Tcp);

    // bind the listening socket to the port
    IPAddress hostIP = IPAddress.Any;
    IPEndPoint endpoint = new IPEndPoint(hostIP, 10042);
    listenSocket.Bind(endpoint);

    // start listening
    listenSocket.Listen(2);

    var socket = listenSocket.Accept();
    ConfigureTcpSocket(socket);

    int count = 0;

    Stopwatch sw = new Stopwatch();

    for (int i = 0; i < 100; i++)
    {
        count++;

        sw.Restart();
        sw.Stop();

        Console.WriteLine($"{count} stopwatch empty body, time {sw.Elapsed.Ticks}");

    }

    SuperQueue<byte[]> superQueue = new SuperQueue<byte[]>(100);

    Task.Factory.StartNew(() =>
    {
        while (true)
        {
            if (superQueue.Count == 0)
            {
                Thread.Sleep(0);
                continue;
            }

            superQueue.TryDequeue(out byte[] data);
            var byteSent = socket.Send(data);

            Console.WriteLine($"{count} socket send {byteSent}");
            Console.Out.Flush();
        }
    });
    for (int i = 0; i < 100; i++)
    {
        count++;

        sw.Restart();
        superQueue.TryEnqueue(new byte[1024]);
        sw.Stop();

        Console.WriteLine($"{count} stopwatch superQueue, time {sw.Elapsed.Ticks}");

    }

    count = 0;
    for (int i = 0; i < 100; i++)
    {
        count++;

        sw.Restart();
        int nSent = socket.Send(new byte[1024]);
        sw.Stop();

        Console.WriteLine($"{count} socket send {nSent} bytes, time {sw.Elapsed.Ticks}");

    }

    count = 0;
    for (int i = 0; i < 100; i++)
    {
        int newCount = count++;

        sw.Restart();
        socket.SendAsync(new ArraySegment<byte>(new byte[1024]), SocketFlags.None).ContinueWith(task =>
        {
            Console.WriteLine($"{newCount} socket send {task.Result}");
        });
        sw.Stop();
        
        Console.WriteLine($"ASYNC: {newCount} socket send, time {sw.Elapsed.Ticks}");

    }


    Console.ReadLine();
}

public class SuperQueue<T>
    where T : class
    {
        private T[] array;
        private int head;       // The index from which to dequeue if the queue isn't empty.

        //tail只跟生产者有关
        private int tail;       // The index at which to enqueue if the queue isn't full.
        private int size;       // Number of elements.

        public int Count => size;

        public SuperQueue(int capacity)
        {
            if (capacity < 0)
                throw new ArgumentOutOfRangeException(nameof(capacity), capacity, "ArgumentOutOfRange_NeedNonNegNum");
            array = new T[capacity];
        }


        //生产者线程
        public bool TryEnqueue(T item)
        {
            if (size == array.Length)
            {
                return false;
            }

            array[tail] = item;
            MoveNext(ref tail);
            Interlocked.Increment(ref size);
            return true;
        }


        public bool TryDequeue(out T result)
        {
            if (size == 0)
            {
                result = default;
                return false;
            }

            result = array[head];
            if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
            {
                array[head] = default;
            }
            MoveNext(ref head);
            Interlocked.Decrement(ref size);
            return true;
        }


        // Increments the index wrapping it if necessary.
        private void MoveNext(ref int index)
        {
            // It is tempting to use the remainder operator here but it is actually much slower
            // than a simple comparison and a rarely taken branch.
            // JIT produces better code than with ternary operator ?:
            int tmp = index + 1;
            if (tmp == array.Length)
            {
                tmp = 0;
            }
            index = tmp;
        }

    }

标签:count,Console,socket,int,sw,网络,发包,new,优化
From: https://www.cnblogs.com/dewxin/p/16903335.html

相关文章

  • 从机器学习到图神经网络,inductive和transductive的区别
    目录机器学习归纳式学习(inductivelearning)转导式学习(transductivelearning)图表示学习归纳式学习(inductivelearning)节点表示图表示转导式学习(transductivelearning)节点......
  • 素数筛法及其优化策略
    暴力算法寻找素数的效率是底下的,可以通过素数筛法来在一个自然数表中标记处素数。Eratosthenes筛法首先是Eratosthenes筛法,基本方法就是首先排除所有大于2的偶数,然后从3......
  • 63:循环代码优化技巧(极其重要)
    ###循环代码优化虽然计算机越来越快,空间也越来越大,我们仍然要在性能问题上“斤斤计较”。编写循环时,遵守下面三个原则可以大大提高运行效率,避免不必要的低效计算:1.尽量......
  • 运筹优化在地服人员派工系统中的应用简介
    运筹优化在地服人员派工系统中的应用简介——以HCC项目为例人员派工是运筹优化的一个常见的应用领域,本文结合目前正在进行的项目对这方面的内容进行一个简单的介绍。概......
  • 实验四:神经网络算法
    姓名:冯莹学号:201613305【实验目的】理解神经网络原理,掌握神经网络前向推理和后向传播方法;掌握神经网络模型的编程实现方法。【实验内容】1.1981年生物学家格若根(W.Gr......
  • BSN-DDC基础网络DDC SDK详细设计五:官方合约BSN-DDC-1155
    2022年1月25日,区块链服务网络发展联盟(简称“BSN联盟”)推出了“BSN-DDC基础网络”(简称DDC网络)。DDC网络的推出,为NFT技术在我国的落地提供基础设施能力支撑,并为其合规发展保驾......
  • 【必看】网络安全入门必刷的靶场合集!
    在信息安全领域,靶场是非常重要的存在,为安全从业人员提供了很大的帮助。当我们初学网络安全时,很多小白也会刷靶场,那么网络安全入门必刷的靶场有哪些?本文为大家介绍一下......
  • 实验四:神经网络算法实验
    |班级链接|https://edu.cnblogs.com/campus/czu/classof2020BigDataClass3-MachineLearning||作业链接|https://edu.cnblogs.com/campus/czu/classof2020BigDataClass3-Ma......
  • 关于VMware的将主机虚拟适配器连接到次网络无法选中的问题
    这个问题的原因可能是,你之前卸载VMware的时候,没有卸载完全,所以注册表还存在一些相关的垃圾这里需要用到CCleaner  然后就可以勾上了  ......
  • 详解webpack构建优化
    当项目越来越复杂时,会面临着构建速度慢和构建出来的文件体积大的问题。webapck构建优化对于大项目是必须要考虑的一件事,下面我们就从速度和体积两方面来探讨构建优化的策略......