‘晋’中网:C# Protobuf【如何做到】0分配内存的序列化

admin 3周前 (09-30) 科技 56 1

sunbet 「申」官网 下载[[

「欢迎进入」sunbet 「申」官网 下载[[!Sunbet 申[博提供申博<开户>(sunbet<开户>)、SunbetAPP 下载[、Sunbet客户端 下载[、Sunbet“代理合作等业务”。

,

‘题目很简’单, ‘就《是》’IMessage【‘《 对[象》’怎么变】成Byte[]

 

「{‘【〖答案〗】’}」1:

msg.ToByteArray()

(这肯定不符合我们的要)(求)

 

「{‘【〖答案〗】’}」2:

using var memoryStream = new MemoryStream();
using var codedOutputStream = new CodedOutputStream(memoryStream);
msg.WriteTo(codedOutputStream);
codedOutputStream.Flush();
memoryStream.ToArray();

(这里面)memoryStream, codedOutputStream, <还>有ToArray‘都产生了’一‘个’‘《 对[象》’, MemoryStream(内部还会)多产生一‘个’byte[]‘《 对[象》’

不符合要(求)

 

「{‘【〖答案〗】’}」3:

『有人说』你可以给MemoryStream〖传〗递一‘个’byte[] slice, “让”MemoryStream「直接用」byte[]

var bytes = new byte[msg.CalculateSize()];
using var memoryStream = new MemoryStream();
using var codedOutputStream = new CodedOutputStream(memoryStream);
msg.WriteTo(codedOutputStream);
codedOutputStream.Flush();

〖这次〗<消息>「直接被序列化到」bytes(里面去了), ‘但《是》’memoryStream‘《 对[象》’, codecOutputStream<还>有memoryStream(内)部的byte[]【都还在】, 我就序列化了一‘个’‘《 对[象》’, {却产生了}3‘个’垃圾‘《 对[象》’

 

「所」以, 【来仔细看看】CodedOutputStream‘类’:

        /// <summary>
        /// Creates a new CodedOutputStream that writes directly to the given
        /// byte array. If more bytes are written than fit in the array,
        /// OutOfSpaceException will be thrown.
        /// </summary>
        public CodedOutputStream(byte[] flatArray) : this(flatArray, 0, flatArray.Length)
        {
        }

        /// <summary>
        /// Creates a new CodedOutputStream that writes directly to the given
        /// byte array slice. If more bytes are written than fit in the array,
        /// OutOfSpaceException will be thrown.
        /// </summary>
        private CodedOutputStream(byte[] buffer, int offset, int length)
        {
            this.output = null;
            this.buffer = buffer;
            this.position = offset;
            this.limit = offset + length;
            leaveOpen = true; // Simple way of avoiding trying to dispose of a null reference
        }

提供了一‘个’[byte[]『 的构造【函数】[』, ‘但《是》’没提供slice『 的构造【函数】[』, 好在有一‘个’私有『 的构造【函数】[』

 

「{‘【〖答案〗】’}」4:

‘这边’就不写代码了, 大概意思‘就《是》’通过反射私有构造【函数】来构造一‘个’CodedOutputStream‘《 对[象》’, <来省掉>MemoryStream「和」他(内)部的byte[]

现在离「{‘【〖答案〗】’}」已经比较接『近了』

 

〖那我们〗的<问题>《是》, 「能不」能连CodedOutputStream『也省掉呢』?

 

「{‘【〖答案〗】’}」5(来)了:

〖经过仔细观察〗, 发现这‘个’‘类’没有使用Stream“的情况下”, 【就】只需要修改buffer, limit, 「和」position几‘个’(成)员就行了, 虽然《是》private(成)员, ‘但《是》’C#还《是》能修改

「下来立」马实践

        delegate void ClearCodedOutputStream(CodedOutputStream stream, byte[] buffer, int offset, int count);
        static ClearCodedOutputStream ResetCodedOutputStream;
        static CodedOutputStream codedOutputStream = new CodedOutputStream(new byte[10]);

        static unsafe void Encode(IMessage msg, byte[] buffer)
        {
            ResetCodedOutputStream(codedOutputStream, buffer, 0, buffer.Length);
            msg.WriteTo(codedOutputStream);
            codedOutputStream.Flush();
        }

        static Action<T, TValue> MakeSetter<T, TValue>(FieldInfo field)
        {
            DynamicMethod m = new DynamicMethod(
                "setter", typeof(void), new Type[] { typeof(T), typeof(TValue) }, typeof(Program));
            ILGenerator cg = m.GetILGenerator();

            cg.Emit(OpCodes.Ldarg_0);
            cg.Emit(OpCodes.Ldarg_1);
            cg.Emit(OpCodes.Stfld, field);
            cg.Emit(OpCodes.Ret);

            return (Action<T, TValue>)m.CreateDelegate(typeof(Action<T, TValue>));
        }

        static void Main(string[] args)
        {
            var bufferField = typeof(CodedOutputStream).GetField("buffer", BindingFlags.NonPublic | BindingFlags.Instance);
            var limitField = typeof(CodedOutputStream).GetField("limit", BindingFlags.NonPublic | BindingFlags.Instance);
            var positionField = typeof(CodedOutputStream).GetField("position", BindingFlags.NonPublic | BindingFlags.Instance);

            var setLimit = MakeSetter<CodedOutputStream, int>(limitField);
            var setPosition = MakeSetter<CodedOutputStream, int>(positionField);
            var setBuffer = MakeSetter<CodedOutputStream, byte[]>(bufferField);

            ResetCodedOutputStream = (stream, buffer, offset, length) => 
            {
                //this.buffer = buffer;
                //this.position = offset;
                //this.limit = offset + length;
                setBuffer(stream, buffer);
                setPosition(stream, offset);
                setLimit(stream, offset + length);
            };

var buffer = new byte[msg.CalculateSize()]; Encode(msg, buffer); }

这‘个’实例代码里面, 用了一‘个’static〖的全局〗CodedOutputStream, “真正用的时候”, 《肯》定要保证线程安全.

 

「所」以接下来的<问题>《是》:

1. ‘如何保证’CodedOutputStream‘《 对[象》’线程安全

2. <如何把>var buffer = new byte[msg.CalculateSize()];这‘个’也省掉

 

这俩<问题>就留给读者思〖考〗.

Sunbet声明:该文看法仅代表作者自己,与本平台无关。转载请注明:‘晋’中网:C# Protobuf【如何做到】0分配内存的序列化

网友评论

  • (*)

最新评论

  • UG环球注册 2020-09-30 00:15:09 回复

    欧博亚洲APP下载欢迎进入欧博亚洲APP下载(Allbet Game):www.aLLbetgame.us,欧博官网是欧博集团的官方网站。欧博官网开放Allbet注册、Allbe代理、Allbet电脑客户端、Allbet手机版下载等业务。最喜欢这个网站

    1

标签列表

    文章归档

      站点信息

      • 文章总数:621
      • 页面总数:0
      • 分类总数:8
      • 标签总数:995
      • 评论总数:254
      • 浏览总数:9141