Where possible, avoid explicit static ctors. They add overhead when accessing statics on a type. PGO can help avoid this overhead, but it's still better to avoid it by design.
Where relevant, use switch instead of frozen dictionary/set. The frozen collections are great, but when all the data is known at compile time, optimizations performed by switch are generally as good (I confirmed they are in these cases), and switches have less memory overhead.
Use readonly on static fields that never change. The JIT can optimize static readonly fields better than mutable statics.
Using StartsWith is better than IndexOf != 0, as the latter needs to search the whole input rather than just checking the beginning.
Delete unused methods.
Using List<T> instead of ICollection<T>, IReadOnlyList<T>, or IList<T> in internal APIs allows better optimization, e.g. foreach'ing won't allocate, indexing can be inlined without help from dynamic PGO, etc.
Use an array instead of a dictionary when the only consumers are enumerating.
Use Length on an array instead of Count().
Use !Any(predicate) instead of Count(predicate) == 0, as the latter needs to enumerate everything whereas the former can early exit.
Where possible, avoid explicit static ctors. They add overhead when accessing statics on a type. PGO can help avoid this overhead, but it's still better to avoid it by design.
Where relevant, use switch instead of frozen dictionary/set. The frozen collections are great, but when all the data is known at compile time, optimizations performed by switch are generally as good (I confirmed they are in these cases), and switches have less memory overhead.
Use readonly on static fields that never change. The JIT can optimize static readonly fields better than mutable statics.
Using StartsWith is better than IndexOf != 0, as the latter needs to search the whole input rather than just checking the beginning.
Delete unused methods.
Using
List<T>
instead ofICollection<T>
,IReadOnlyList<T>
, orIList<T>
in internal APIs allows better optimization, e.g. foreach'ing won't allocate, indexing can be inlined without help from dynamic PGO, etc.Use an array instead of a dictionary when the only consumers are enumerating.
Use Length on an array instead of Count().
Use !Any(predicate) instead of Count(predicate) == 0, as the latter needs to enumerate everything whereas the former can early exit.