1 // Licensed to the .NET Foundation under one or more agreements. 2 // The .NET Foundation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System.IO; 6 using System.Collections.Generic; 7 using System.Linq; 8 using Microsoft.Xunit.Performance; 9 using System.Xml; 10 using SerializationTypes; 11 12 namespace System.Runtime.Serialization 13 { 14 #region Performance tests configuration types 15 16 public enum TestType 17 { 18 SimpleType, 19 ISerializable, 20 Dictionary, 21 ListOfInt, 22 String, 23 ByteArray, 24 XmlElement, 25 DateTimeArray, 26 ArrayOfSimpleType, 27 ListOfSimpleType, 28 DictionaryOfSimpleType, 29 SimpleStructWithProperties, 30 SimpleTypeWithFields 31 } 32 33 public interface IPerfTestSerializer 34 { Init(object obj)35 void Init(object obj); Serialize(object obj, Stream s)36 void Serialize(object obj, Stream s); Deserialize(Stream s)37 void Deserialize(Stream s); 38 } 39 40 public interface ISerializerFactory 41 { GetSerializer()42 IPerfTestSerializer GetSerializer(); 43 } 44 45 public class PerfTestConfig 46 { 47 public readonly int NumberOfRuns; 48 public readonly TestType PerfTestType; 49 public readonly int TestSize; 50 PerfTestConfig()51 public PerfTestConfig() { } 52 PerfTestConfig(int numOfRuns, TestType testType, int testSize)53 public PerfTestConfig(int numOfRuns, TestType testType, int testSize) 54 { 55 NumberOfRuns = numOfRuns; 56 PerfTestType = testType; 57 TestSize = testSize; 58 } 59 ToObjectArray()60 public object[] ToObjectArray() 61 { 62 return new object[] { NumberOfRuns, PerfTestType, TestSize }; 63 } 64 } 65 66 #endregion 67 68 public class PerformanceTestCommon 69 { 70 #region Performance test configuration 71 PerformanceTestConfigurations()72 public static IEnumerable<PerfTestConfig> PerformanceTestConfigurations() 73 { 74 yield return new PerfTestConfig(100, TestType.ByteArray, 1024); 75 yield return new PerfTestConfig(5, TestType.ByteArray, 1024 * 1024); 76 yield return new PerfTestConfig(10000, TestType.String, 128); 77 yield return new PerfTestConfig(10000, TestType.String, 1024); 78 yield return new PerfTestConfig(1000, TestType.ListOfInt, 128); 79 yield return new PerfTestConfig(100, TestType.ListOfInt, 1024); 80 yield return new PerfTestConfig(1, TestType.ListOfInt, 1024 * 1024); 81 yield return new PerfTestConfig(1000, TestType.Dictionary, 128); 82 yield return new PerfTestConfig(100, TestType.Dictionary, 1024); 83 yield return new PerfTestConfig(10, TestType.SimpleType, 1); 84 yield return new PerfTestConfig(1, TestType.SimpleType, 15); 85 yield return new PerfTestConfig(1, TestType.SimpleTypeWithFields, 15); 86 yield return new PerfTestConfig(10000, TestType.SimpleStructWithProperties, 1); 87 yield return new PerfTestConfig(10000, TestType.ISerializable, -1); 88 yield return new PerfTestConfig(10000, TestType.XmlElement, -1); 89 yield return new PerfTestConfig(100, TestType.DateTimeArray, 1024); 90 yield return new PerfTestConfig(1000, TestType.ArrayOfSimpleType, 128); 91 yield return new PerfTestConfig(100, TestType.ArrayOfSimpleType, 1024); 92 yield return new PerfTestConfig(1000, TestType.ListOfSimpleType, 128); 93 yield return new PerfTestConfig(100, TestType.ListOfSimpleType, 1024); 94 yield return new PerfTestConfig(1000, TestType.DictionaryOfSimpleType, 128); 95 yield return new PerfTestConfig(100, TestType.DictionaryOfSimpleType, 1024); 96 } 97 PerformanceMemberData()98 public static IEnumerable<object[]> PerformanceMemberData() 99 { 100 foreach (PerfTestConfig config in PerformanceTestConfigurations()) 101 { 102 yield return config.ToObjectArray(); 103 } 104 } 105 106 #endregion 107 108 #region Methods to create object for serialization tests 109 CreateSimpleTypeWihtMoreProperties(int height, int parentId, int currentId, int collectionSize, int childListSize)110 public static SimpleTypeWihtMoreProperties CreateSimpleTypeWihtMoreProperties(int height, int parentId, int currentId, int collectionSize, int childListSize) 111 { 112 int index = parentId * childListSize + (currentId + 1); 113 var obj = new SimpleTypeWihtMoreProperties() 114 { 115 IntProperty = index, 116 StringProperty = index + " string value", 117 EnumProperty = (MyEnum)(index % (Enum.GetNames(typeof(MyEnum)).Length)), 118 CollectionProperty = new List<string>(collectionSize), 119 SimpleTypeList = new List<SimpleTypeWihtMoreProperties>(childListSize) 120 }; 121 for (int i = 0; i < collectionSize; ++i) 122 { 123 obj.CollectionProperty.Add(index + "." + i); 124 } 125 if (height > 1) 126 { 127 for (int i = 0; i < childListSize; ++i) 128 { 129 obj.SimpleTypeList.Add(CreateSimpleTypeWihtMoreProperties(height - 1, index, i, collectionSize, childListSize)); 130 } 131 } 132 return obj; 133 } 134 CreateSimpleTypeWithFields(int height, int parentId, int currentId, int collectionSize, int childListSize)135 public static SimpleTypeWithMoreFields CreateSimpleTypeWithFields(int height, int parentId, int currentId, int collectionSize, int childListSize) 136 { 137 int index = parentId * childListSize + (currentId + 1); 138 var obj = new SimpleTypeWithMoreFields() 139 { 140 IntField = index, 141 StringField = index + " string value", 142 EnumField = (MyEnum)(index % (Enum.GetNames(typeof(MyEnum)).Length)), 143 CollectionField = new List<string>(collectionSize), 144 SimpleTypeList = new List<SimpleTypeWithMoreFields>(childListSize) 145 }; 146 for (int i = 0; i < collectionSize; ++i) 147 { 148 obj.CollectionField.Add(index + "." + i); 149 } 150 if (height > 1) 151 { 152 for (int i = 0; i < childListSize; ++i) 153 { 154 obj.SimpleTypeList.Add(CreateSimpleTypeWithFields(height - 1, index, i, collectionSize, childListSize)); 155 } 156 } 157 return obj; 158 } 159 CreateByteArray(int size)160 public static byte[] CreateByteArray(int size) 161 { 162 byte[] obj = new byte[size]; 163 for (int i = 0; i < obj.Length; ++i) 164 { 165 unchecked 166 { 167 obj[i] = (byte)i; 168 } 169 } 170 return obj; 171 } 172 CreateDictionaryOfIntString(int count)173 public static Dictionary<int, string> CreateDictionaryOfIntString(int count) 174 { 175 Dictionary<int, string> dictOfIntString = new Dictionary<int, string>(count); 176 for (int i = 0; i < count; ++i) 177 { 178 dictOfIntString[i] = i.ToString(); 179 } 180 181 return dictOfIntString; 182 } 183 CreateDictionaryOfIntSimpleType(int count)184 public static Dictionary<int, SimpleType> CreateDictionaryOfIntSimpleType(int count) 185 { 186 var dictOfIntSimpleType = new Dictionary<int, SimpleType>(count); 187 for (int i = 0; i < count; ++i) 188 { 189 dictOfIntSimpleType[i] = new SimpleType() { P1 = i.ToString(), P2 = i }; 190 } 191 192 return dictOfIntSimpleType; 193 } 194 CreateListOfSimpleType(int count)195 public static List<SimpleType> CreateListOfSimpleType(int count) 196 { 197 var listOfSimpleType = new List<SimpleType>(count); 198 for(int i = 0; i < count; i++) 199 { 200 listOfSimpleType.Add(new SimpleType() { P1 = i.ToString(), P2 = i }); 201 } 202 203 return listOfSimpleType; 204 } 205 CreateArrayOfSimpleType(int count)206 public static SimpleType[] CreateArrayOfSimpleType(int count) 207 { 208 var arrayOfSimpleType = new SimpleType[count]; 209 for(int i = 0; i < count; i++) 210 { 211 arrayOfSimpleType[i] = new SimpleType() { P1 = i.ToString(), P2 = i }; 212 } 213 214 return arrayOfSimpleType; 215 } 216 CreateListOfInt(int count)217 public static List<int> CreateListOfInt(int count) 218 { 219 return Enumerable.Range(0, count).ToList(); 220 } 221 CreateDateTimeArray(int count)222 public static DateTime[] CreateDateTimeArray(int count) 223 { 224 DateTime[] arr = new DateTime[count]; 225 int kind = (int)DateTimeKind.Unspecified; 226 int maxDateTimeKind = (int) DateTimeKind.Local; 227 DateTime val = DateTime.Now.AddHours(count/2); 228 for (int i = 0; i < count; i++) 229 { 230 arr[i] = DateTime.SpecifyKind(val, (DateTimeKind)kind); 231 val = val.AddHours(1); 232 kind = (kind + 1)%maxDateTimeKind; 233 } 234 235 return arr; 236 } 237 GetSerializationObject(TestType testType, int testSize)238 public static object GetSerializationObject(TestType testType, int testSize) 239 { 240 Object obj = null; 241 switch (testType) 242 { 243 case TestType.ByteArray: 244 obj = CreateByteArray(testSize); 245 break; 246 case TestType.Dictionary: 247 obj = CreateDictionaryOfIntString(testSize); 248 break; 249 case TestType.ISerializable: 250 obj = new ClassImplementingIXmlSerialiable() { StringValue = "Hello world" }; 251 break; 252 case TestType.ListOfInt: 253 obj = CreateListOfInt(testSize); 254 break; 255 case TestType.SimpleType: 256 obj = CreateSimpleTypeWihtMoreProperties(testSize, 0, -1, 7, 2); 257 break; 258 case TestType.SimpleTypeWithFields: 259 obj = CreateSimpleTypeWithFields(testSize, 0, -1, 7, 2); 260 break; 261 case TestType.String: 262 obj = new string('k', testSize); 263 break; 264 case TestType.XmlElement: 265 XmlDocument xmlDoc = new XmlDocument(); 266 xmlDoc.LoadXml(@"<html></html>"); 267 XmlElement xmlElement = xmlDoc.CreateElement("Element"); 268 xmlElement.InnerText = "Element innertext"; 269 obj = xmlElement; 270 break; 271 case TestType.DateTimeArray: 272 obj = CreateDateTimeArray(testSize); 273 break; 274 case TestType.ArrayOfSimpleType: 275 obj = CreateArrayOfSimpleType(testSize); 276 break; 277 case TestType.ListOfSimpleType: 278 obj = CreateListOfSimpleType(testSize); 279 break; 280 case TestType.DictionaryOfSimpleType: 281 obj = CreateDictionaryOfIntSimpleType(testSize); 282 break; 283 case TestType.SimpleStructWithProperties: 284 obj = new SimpleStructWithProperties() { Num = 1, Text = "Foo" }; 285 break; 286 default: 287 throw new ArgumentException(); 288 } 289 return obj; 290 } 291 292 #endregion 293 294 #region Methods to run serialization performance tests 295 RunSerializationPerformanceTest(int numberOfRuns, TestType testType, int testSize, ISerializerFactory serializerFactory)296 public static void RunSerializationPerformanceTest(int numberOfRuns, TestType testType, int testSize, ISerializerFactory serializerFactory) 297 { 298 var obj = GetSerializationObject(testType, testSize); 299 300 var serializer = serializerFactory.GetSerializer(); 301 serializer.Init(obj); 302 303 using (var stream = new MemoryStream()) 304 { 305 foreach (var iteration in Benchmark.Iterations) 306 { 307 using (iteration.StartMeasurement()) 308 { 309 for (int i = 0; i < numberOfRuns; i++) 310 { 311 serializer.Serialize(obj, stream); 312 stream.Position = 0; 313 } 314 } 315 } 316 } 317 } 318 RunDeserializationPerformanceTest(int numberOfRuns, TestType testType, int testSize, ISerializerFactory serializerFactory)319 public static void RunDeserializationPerformanceTest(int numberOfRuns, TestType testType, int testSize, ISerializerFactory serializerFactory) 320 { 321 var obj = GetSerializationObject(testType, testSize); 322 323 var serializer = serializerFactory.GetSerializer(); 324 serializer.Init(obj); 325 326 using (var stream = new MemoryStream()) 327 { 328 serializer.Serialize(obj, stream); 329 stream.Position = 0; 330 foreach (var iteration in Benchmark.Iterations) 331 { 332 using (iteration.StartMeasurement()) 333 { 334 for (int i = 0; i < numberOfRuns; i++) 335 { 336 serializer.Deserialize(stream); 337 stream.Position = 0; 338 } 339 } 340 } 341 } 342 } 343 344 #endregion 345 } 346 } 347