C〓Protobufはどのようにして0をやり遂げてメモリの順序を割り当てますか?
タイトルは簡単ですが、IMessgeの対象がBytte[]にどうなりますか?
答え1:
答え2:
要求に合わない
答え3:
MemoryStreamにbyte[]sliceを伝えて、MemoryStreamに直接byte[/]を使わせるという人がいます。
ですから、CodedOutputStream類をよく見てみましょう。
答え4:
ここではコードは書かれていません。プライベートコンストラクタを反射してCodedOutputStreamオブジェクトを構築することで、MemoryStreamと彼の内部のbyte[]を省きます。
今は答えに近いです。
私たちの問題は、CodedOutputStreamも省けますか?
答え5来ました
よく観察してみると、このクラスはStreamを使用していない場合、バグ、limit、およびpositionのメンバー数だけを修正してもいいです。prvateメンバーですが、C〓〓は修正できます。
来たらすぐ実践しなさい
だから次の問題は:
1.CodedOutputStreamオブジェクトスレッドの安全を保証する方法
2.var buffer=new byte[msg.ClateSize];これも省きます
この二つの問題は読者に考えさせている。
Github: http://github.com/egmkang
ここでは、C(ハ)Protobufをどうやって0メモリを割り当てるかについての序文を紹介します。C(ハ)Protobuf序列化の内容については、以前の文章を検索したり、下記の関連記事を引き続き閲覧したりしてください。これからもよろしくお願いします。
答え1:
msg.ToByteArray()
これはきっと私たちの要求に合わないです。答え2:
using var memoryStream = new MemoryStream();
using var codedOutputStream = new CodedOutputStream(memoryStream);
msg.WriteTo(codedOutputStream);
codedOutputStream.Flush();
memoryStream.ToArray();
この中にはmemoryStream、codedOutputStream、そしてToArayが一つの対象を作っています。また、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();
今回のニュースは直接的にBtesに整理されましたが、memoryStreamオブジェクト、codecOutputStream、そしてmemoryStream内部のbyte[]がまだあります。一つの対象を順番に並べましたが、三つのゴミの対象が生まれました。 ですから、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を使用していない場合、バグ、limit、およびpositionのメンバー数だけを修正してもいいです。prvateメンバーですが、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.ClateSize];これも省きます
この二つの問題は読者に考えさせている。
Github: http://github.com/egmkang
ここでは、C(ハ)Protobufをどうやって0メモリを割り当てるかについての序文を紹介します。C(ハ)Protobuf序列化の内容については、以前の文章を検索したり、下記の関連記事を引き続き閲覧したりしてください。これからもよろしくお願いします。