http://thenextweb.com/insider/2015/02/18/http2-first-major-update-http-sixteen-years-finalized/
https://www.mnot.net/blog/2014/01/30/http2_expectations
http://gizmodo.com/what-is-http-2-1686537168
List<T> to return collections from a public API. However, there are several reasons not to do so; instead return a ReadOnlyCollection<T>. The are several benefits of
using a ReadOnlyCollection<T>:
ReadOnlyCollection<T> does not mean that the elements within the collection are "readonly"; they can still be modified. To protect
the items in it, you’d probably have to have private “setters” on any properties
for the reference object in the collection – which is generally recommended.
However, items that are declared as [DataMember] must have both public getters
and setters. So if you are in that case, you can’t do the private setter, but
you can still use the ReadOnlyCollection<T>. Using this as a Design
paradigm can prevent subtle bugs from popping up. One case that comes to mind is the case of a HashSet<T>. It is recommended to avoid having mutable properties on class or struct types that are going to be used in any collection that utilizes the types hash code to refer to an object of that type - e.g. HashSet<T>,
List<T> class is essentially a wrapper around a strongly-typed array. Since arrays are immutable (cannot be re-sized), any modifications made to a List<T> must create a complete copy of the List<T> and add the new item. Note that in the case of value types, a copy of the value type is created whereas, in the case of reference types, a copy of the reference to the object is created. The performance impact for reference types is negligible.
The initial capacity for a List<T> is 4 unless specified thru the overloaded constructor - see here.
https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.collectionsmarshal.getvaluereforadddefault
Obviously, this can be very bad for memory and performance. Don’t forget that not only the items directly within the List<T>
itself are copied – but every value and object with the entire object graph for that reference type.
This could easily contain other references types, collections, etc. This is why it is recommended to create/initialize a List<T> instance with the overloaded constructor which takes an int denoting the size of the List<T> to be created when possible. This can often be done since you are typically iterating on a "known" size value at runtime. For example, creating a List<T> of objects from a "Repository or DataService" method may iterate/read from a IDataReader object which has a property of RecordsAffected. If you are going to be putting an item in the List<T> based on the number of times the IDataReader is read: e.g. while(reader.Read()) you can easily create the list like so:
if (reader != null && reader.RecordsAffected > 0)
{
// initialize the list with a pre-defined size
List<Foo> someList = new List<Foo>(reader.RecordsAffected);
while (reader.Read())
{
someList.Add(...);
...
}
}
List<T> needs to grow in size (its new size would exceed its current Capactity, the size is *doubled*. So,
if you happen to add just one more item to a List<T> that wasn’t
constructed with a pre-determined size, and the List<T> expands to
accommodate the new item, there will be a whole lot of unused space at the end
of the List<T> even though there aren’t any items in it – bad for memory
and performance.
void Main() { var HasDebuggableAttribute = false; var IsJITOptimized = false; var IsJITTrackingEnabled = false; var BuildType = ""; var DebugOutput = ""; var ReflectedAssembly = Assembly.LoadFile(@"C:\src\TMDE\Git\RedisScalingTest\bin\Release\netcoreapp3.1\RedisScalingTest.dll"); // var ReflectedAssembly = Assembly.LoadFile(@"path to the dll you are testing"); object[] attribs = ReflectedAssembly.GetCustomAttributes(typeof(DebuggableAttribute), false); // If the 'DebuggableAttribute' is not found then it is definitely an OPTIMIZED build if (attribs.Length > 0) { // Just because the 'DebuggableAttribute' is found doesn't necessarily mean // it's a DEBUG build; we have to check the JIT Optimization flag // i.e. it could have the "generate PDB" checked but have JIT Optimization enabled DebuggableAttribute debuggableAttribute = attribs[0] as DebuggableAttribute; if (debuggableAttribute != null) { HasDebuggableAttribute = true; IsJITOptimized = !debuggableAttribute.IsJITOptimizerDisabled; // IsJITTrackingEnabled - Gets a value that indicates whether the runtime will track information during code generation for the debugger. IsJITTrackingEnabled = debuggableAttribute.IsJITTrackingEnabled; BuildType = debuggableAttribute.IsJITOptimizerDisabled ? "Debug" : "Release"; // check for Debug Output "full" or "pdb-only" DebugOutput = (debuggableAttribute.DebuggingFlags & DebuggableAttribute.DebuggingModes.Default) != DebuggableAttribute.DebuggingModes.None ? "Full" : "pdb-only"; } } else { IsJITOptimized = true; BuildType = "Release"; } Console.WriteLine($"{nameof(HasDebuggableAttribute)}: {HasDebuggableAttribute}"); Console.WriteLine($"{nameof(IsJITOptimized)}: {IsJITOptimized}"); Console.WriteLine($"{nameof(IsJITTrackingEnabled)}: {IsJITTrackingEnabled}"); Console.WriteLine($"{nameof(BuildType)}: {BuildType}"); Console.WriteLine($"{nameof(DebugOutput)}: {DebugOutput}"); }