サービス間でログ メッセージを送信するために protobuf-net を使用しています。ストレス テストをプロファイリングすると、高い同時実行性の下で CPU 使用率が非常に高くなり、RuntimeTypeModel の TakeLock が原因であることがわかります。ホット コール スタックは次のようになります。
*Our code...*
ProtoBuf.Serializer.SerializeWithLengthPrefix(class System.IO.Stream,!!0,valuetype ProtoBuf.PrefixStyle)
ProtoBuf.Serializer.SerializeWithLengthPrefix(class System.IO.Stream,!!0,valuetype ProtoBuf.PrefixStyle,int32)
ProtoBuf.Meta.TypeModel.SerializeWithLengthPrefix(class System.IO.Stream,object,class System.Type,valuetype ProtoBuf.PrefixStyle,int32)
ProtoBuf.Meta.TypeModel.SerializeWithLengthPrefix(class System.IO.Stream,object,class System.Type,valuetype ProtoBuf.PrefixStyle,int32,class ProtoBuf.SerializationContext)
ProtoBuf.ProtoWriter.WriteObject(object,int32,class ProtoBuf.ProtoWriter,valuetype ProtoBuf.PrefixStyle,int32)
ProtoBuf.BclHelpers.WriteNetObject(object,class ProtoBuf.ProtoWriter,int32,valuetype
ProtoBuf.BclHelpers/NetObjectOptions)
ProtoBuf.Meta.TypeModel.GetKey(class System.Type&)
ProtoBuf.Meta.RuntimeTypeModel.GetKey(class System.Type,bool,bool)
ProtoBuf.Meta.RuntimeTypeModel.FindOrAddAuto(class System.Type,bool,bool,bool)
ProtoBuf.Meta.RuntimeTypeModel.TakeLock(int32&)
[clr.dll]
新しいプリコンパイラを使用して速度を向上できることがわかりましたが、それで問題が解決するかどうか疑問に思っています (リフレクションを使用していないように聞こえます)。これを統合するのは少し面倒なので、まだテストしていません。Serializer.PrepareSerializer を呼び出すオプションも表示されます。私の最初の(小規模な)テストでは、準備が有望に見えませんでした。
シリアライズしている型に関するもう少しの情報:
[ProtoContract]
public class SomeMessage
{
[ProtoMember(1)]
public SomeEnumType SomeEnum { get; set; }
[ProtoMember(2)]
public long SomeId{ get; set; }
[ProtoMember(3)]
public string SomeString{ get; set; }
[ProtoMember(4)]
public DateTime SomeDate { get; set; }
[ProtoMember(5, DynamicType = true, OverwriteList = true)]
public Collection<object> SomeArguments
}
ご協力いただきありがとうございます!
9/17更新
ご返信ありがとうございます!ご提案の回避策を試して、問題が解決するかどうかを確認します。
このコードはロギング システムに存在するため、SomeMessage の例では、SomeString は実際にはフォーマット文字列 (例: "Hello {0}") であり、SomeArguments コレクションは、String と同様に、フォーマット文字列を埋めるために使用されるオブジェクトのリストです。フォーマット。シリアル化する前に、各引数を調べて を呼び出しますDynamicSerializer.IsKnownType(argument.GetType())
。不明な場合は、最初に文字列に変換します。データの比率は見ていませんが、引数としてさまざまな文字列が多数入っていることは確かです。
これが役立つかどうか教えてください。必要があれば、詳細を調べてみます。