Skip to content

Commit

Permalink
Reduce enumerator and list allocations (#3786)
Browse files Browse the repository at this point in the history
  • Loading branch information
lahma authored Dec 9, 2021
1 parent 5ab9a78 commit 33011cd
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 69 deletions.
32 changes: 19 additions & 13 deletions src/NSwag.CodeGeneration/ClientGeneratorBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ protected virtual IEnumerable<CodeArtifact> GenerateAllClientTypes()

if (BaseSettings.OperationNameGenerator.SupportsMultipleClients)
{
var controllerOperationsGroups = operations.GroupBy(o => o.ControllerName).ToList();
var controllerOperationsGroups = operations.GroupBy(o => o.ControllerName);
foreach (var controllerOperations in controllerOperationsGroups)
{
var controllerName = controllerOperations.Key;
Expand Down Expand Up @@ -149,12 +149,16 @@ private List<TOperationModel> GetOperations(OpenApiDocument document)
{
document.GenerateOperationIds();

return document.Paths
.SelectMany(pair => pair.Value.ActualPathItem
.Select(p => new { Path = pair.Key.TrimStart('/'), HttpMethod = p.Key, Operation = p.Value }))
.Select(tuple =>
var result = new List<TOperationModel>();
foreach (var pair in document.Paths)
{
foreach (var p in pair.Value.ActualPathItem)
{
var operationName = BaseSettings.OperationNameGenerator.GetOperationName(document, tuple.Path, tuple.HttpMethod, tuple.Operation);
var path = pair.Key.TrimStart('/');
var httpMethod = p.Key;
var operation = p.Value;

var operationName = BaseSettings.OperationNameGenerator.GetOperationName(document, path, httpMethod, operation);

if (operationName.Contains("."))
{
Expand All @@ -166,14 +170,16 @@ private List<TOperationModel> GetOperations(OpenApiDocument document)
operationName = operationName.Substring(0, operationName.Length - "Async".Length);
}

var operationModel = CreateOperationModel(tuple.Operation, BaseSettings);
operationModel.ControllerName = BaseSettings.OperationNameGenerator.GetClientName(document, tuple.Path, tuple.HttpMethod, tuple.Operation);
operationModel.Path = tuple.Path;
operationModel.HttpMethod = tuple.HttpMethod;
var operationModel = CreateOperationModel(operation, BaseSettings);
operationModel.ControllerName = BaseSettings.OperationNameGenerator.GetClientName(document, path, httpMethod, operation);
operationModel.Path = path;
operationModel.HttpMethod = httpMethod;
operationModel.OperationName = operationName;
return operationModel;
})
.ToList();

result.Add(operationModel);
}
}
return result;
}
}
}
102 changes: 48 additions & 54 deletions src/NSwag.Core/Collections/ObservableDictionary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,51 +22,53 @@ public class ObservableDictionary<TKey, TValue> :
IDictionary<TKey, TValue>, INotifyCollectionChanged,
INotifyPropertyChanged, IDictionary, IReadOnlyDictionary<TKey, TValue>
{
private Dictionary<TKey, TValue> _dictionary;

/// <summary>Initializes a new instance of the <see cref="ObservableDictionary{TKey, TValue}"/> class. </summary>
public ObservableDictionary()
{
Dictionary = new Dictionary<TKey, TValue>();
_dictionary = new Dictionary<TKey, TValue>();
}

/// <summary>Initializes a new instance of the <see cref="ObservableDictionary{TKey, TValue}"/> class. </summary>
/// <param name="dictionary">The dictionary to initialize this dictionary. </param>
public ObservableDictionary(IDictionary<TKey, TValue> dictionary)
{
Dictionary = new Dictionary<TKey, TValue>(dictionary);
_dictionary = new Dictionary<TKey, TValue>(dictionary);
}

/// <summary>Initializes a new instance of the <see cref="ObservableDictionary{TKey, TValue}"/> class. </summary>
/// <param name="comparer">The comparer. </param>
public ObservableDictionary(IEqualityComparer<TKey> comparer)
{
Dictionary = new Dictionary<TKey, TValue>(comparer);
_dictionary = new Dictionary<TKey, TValue>(comparer);
}

/// <summary>Initializes a new instance of the <see cref="ObservableDictionary{TKey, TValue}"/> class. </summary>
/// <param name="capacity">The capacity. </param>
public ObservableDictionary(int capacity)
{
Dictionary = new Dictionary<TKey, TValue>(capacity);
_dictionary = new Dictionary<TKey, TValue>(capacity);
}

/// <summary>Initializes a new instance of the <see cref="ObservableDictionary{TKey, TValue}"/> class. </summary>
/// <param name="dictionary">The dictionary to initialize this dictionary. </param>
/// <param name="comparer">The comparer. </param>
public ObservableDictionary(IDictionary<TKey, TValue> dictionary, IEqualityComparer<TKey> comparer)
{
Dictionary = new Dictionary<TKey, TValue>(dictionary, comparer);
_dictionary = new Dictionary<TKey, TValue>(dictionary, comparer);
}

/// <summary>Initializes a new instance of the <see cref="ObservableDictionary{TKey, TValue}"/> class. </summary>
/// <param name="capacity">The capacity. </param>
/// <param name="comparer">The comparer. </param>
public ObservableDictionary(int capacity, IEqualityComparer<TKey> comparer)
{
Dictionary = new Dictionary<TKey, TValue>(capacity, comparer);
_dictionary = new Dictionary<TKey, TValue>(capacity, comparer);
}

/// <summary>Gets the underlying dictonary. </summary>
protected IDictionary<TKey, TValue> Dictionary { get; private set; }
protected Dictionary<TKey, TValue> Dictionary => _dictionary;

/// <summary>Adds multiple key-value pairs the the dictionary. </summary>
/// <param name="items">The key-value pairs. </param>
Expand All @@ -79,21 +81,21 @@ public void AddRange(IDictionary<TKey, TValue> items)

if (items.Count > 0)
{
if (Dictionary.Count > 0)
if (_dictionary.Count > 0)
{
if (items.Keys.Any(k => Dictionary.ContainsKey(k)))
if (items.Keys.Any(k => _dictionary.ContainsKey(k)))
{
throw new ArgumentException("An item with the same key has already been added.");
}

foreach (var item in items)
foreach (var pair in items)
{
Dictionary.Add(item);
_dictionary.Add(pair.Key, pair.Value);
}
}
else
{
Dictionary = new Dictionary<TKey, TValue>(items);
_dictionary = new Dictionary<TKey, TValue>(items);
}

OnCollectionChanged(NotifyCollectionChangedAction.Add, items.ToArray());
Expand All @@ -107,7 +109,7 @@ public void AddRange(IDictionary<TKey, TValue> items)
protected virtual void Insert(TKey key, TValue value, bool add)
{
TValue item;
if (Dictionary.TryGetValue(key, out item))
if (_dictionary.TryGetValue(key, out item))
{
if (add)
{
Expand All @@ -119,12 +121,12 @@ protected virtual void Insert(TKey key, TValue value, bool add)
return;
}

Dictionary[key] = value;
_dictionary[key] = value;
OnCollectionChanged(NotifyCollectionChangedAction.Replace, new KeyValuePair<TKey, TValue>(key, value), new KeyValuePair<TKey, TValue>(key, item));
}
else
{
Dictionary[key] = value;
_dictionary[key] = value;
OnCollectionChanged(NotifyCollectionChangedAction.Add, new KeyValuePair<TKey, TValue>(key, value));
}
}
Expand Down Expand Up @@ -214,23 +216,20 @@ public void Add(TKey key, TValue value)
/// <returns></returns>
public bool ContainsKey(TKey key)
{
return Dictionary.ContainsKey(key);
return _dictionary.ContainsKey(key);
}

/// <summary>Gets an <see cref="T:System.Collections.Generic.ICollection`1" /> containing the keys of the <see cref="T:System.Collections.Generic.IDictionary`2" />.</summary>
public ICollection<TKey> Keys
{
get { return Dictionary.Keys; }
get { return _dictionary.Keys; }
}

ICollection IDictionary.Values { get { return ((IDictionary)Dictionary).Values; } }
ICollection IDictionary.Values => _dictionary.Values;

ICollection IDictionary.Keys { get { return ((IDictionary)Dictionary).Keys; } }
ICollection IDictionary.Keys => _dictionary.Keys;

IEnumerable<TValue> IReadOnlyDictionary<TKey, TValue>.Values
{
get { return Values; }
}
IEnumerable<TValue> IReadOnlyDictionary<TKey, TValue>.Values => Values;

/// <summary>Removes the specified key.</summary>
/// <param name="key">The key.</param>
Expand All @@ -243,10 +242,7 @@ public virtual bool Remove(TKey key)
throw new ArgumentNullException("key");
}

TValue value;
Dictionary.TryGetValue(key, out value);

var removed = Dictionary.Remove(key);
var removed = _dictionary.Remove(key);
if (removed)
{
OnCollectionChanged();
Expand All @@ -261,7 +257,7 @@ public virtual bool Remove(TKey key)
/// <returns></returns>
public bool TryGetValue(TKey key, out TValue value)
{
return Dictionary.TryGetValue(key, out value);
return _dictionary.TryGetValue(key, out value);
}

IEnumerable<TKey> IReadOnlyDictionary<TKey, TValue>.Keys
Expand All @@ -270,19 +266,16 @@ IEnumerable<TKey> IReadOnlyDictionary<TKey, TValue>.Keys
}

/// <summary>Gets an <see cref="T:System.Collections.Generic.ICollection`1" /> containing the values in the <see cref="T:System.Collections.Generic.IDictionary`2" />.</summary>
public ICollection<TValue> Values
{
get { return Dictionary.Values; }
}
public ICollection<TValue> Values => _dictionary.Values;

/// <summary>Gets or sets the TValue with the specified key.</summary>
/// <value>The TValue.</value>
/// <param name="key">The key.</param>
/// <returns></returns>
public TValue this[TKey key]
{
get { return Dictionary[key]; }
set { Insert(key, value, false); }
get => _dictionary[key];
set => Insert(key, value, false);
}

#endregion
Expand All @@ -304,9 +297,9 @@ void IDictionary.Add(object key, object value)
/// <summary>Removes all items from the <see cref="T:System.Collections.Generic.ICollection`1" />.</summary>
public void Clear()
{
if (Dictionary.Count > 0)
if (_dictionary.Count > 0)
{
Dictionary.Clear();
_dictionary.Clear();
OnCollectionChanged();
}
}
Expand All @@ -318,12 +311,12 @@ public void Initialize(IEnumerable<KeyValuePair<TKey, TValue>> keyValuePairs)
var pairs = keyValuePairs.ToList();
foreach (var pair in pairs)
{
Dictionary[pair.Key] = pair.Value;
_dictionary[pair.Key] = pair.Value;
}

foreach (var key in Dictionary.Keys.Where(k => !pairs.Any(p => Equals(p.Key, k))).ToArray())
foreach (var key in _dictionary.Keys.Where(k => !pairs.Any(p => Equals(p.Key, k))).ToArray())
{
Dictionary.Remove(key);
_dictionary.Remove(key);
}

OnCollectionChanged();
Expand All @@ -346,7 +339,7 @@ public bool Contains(object key)

IDictionaryEnumerator IDictionary.GetEnumerator()
{
return ((IDictionary)Dictionary).GetEnumerator();
return ((IDictionary) _dictionary).GetEnumerator();
}

/// <summary>Removes the specified key.</summary>
Expand All @@ -364,30 +357,27 @@ public void Remove(object key)
/// <returns></returns>
public bool Contains(KeyValuePair<TKey, TValue> item)
{
return Dictionary.Contains(item);
return _dictionary.Contains(item);
}

/// <summary>Copies to.</summary>
/// <param name="array">The array.</param>
/// <param name="arrayIndex">Index of the array.</param>
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
{
Dictionary.CopyTo(array, arrayIndex);
((IDictionary) _dictionary).CopyTo(array, arrayIndex);
}

/// <summary>Copies to.</summary>
/// <param name="array">The array.</param>
/// <param name="index">The index.</param>
public void CopyTo(Array array, int index)
{
((IDictionary)Dictionary).CopyTo(array, index);
((IDictionary)_dictionary).CopyTo(array, index);
}

/// <summary>Gets the number of elements contained in the <see cref="T:System.Collections.Generic.ICollection`1" />.</summary>
public int Count
{
get { return Dictionary.Count; }
}
public int Count => _dictionary.Count;

/// <summary>Gets a value indicating whether access to the <see cref="T:System.Collections.ICollection" /> is synchronized (thread safe).</summary>
public bool IsSynchronized { get; private set; }
Expand All @@ -396,10 +386,7 @@ public int Count
public object SyncRoot { get; private set; }

/// <summary>Gets a value indicating whether the <see cref="T:System.Collections.Generic.ICollection`1" /> is read-only.</summary>
public bool IsReadOnly
{
get { return Dictionary.IsReadOnly; }
}
public bool IsReadOnly => ((IDictionary) _dictionary).IsReadOnly;

object IDictionary.this[object key]
{
Expand All @@ -421,9 +408,16 @@ public bool Remove(KeyValuePair<TKey, TValue> item)

/// <summary>Returns an enumerator that iterates through the collection.</summary>
/// <returns>A <see cref="T:System.Collections.Generic.IEnumerator`1" /> that can be used to iterate through the collection.</returns>
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()
{
return _dictionary.GetEnumerator();
}

/// <summary>Returns an enumerator that iterates through the collection.</summary>
/// <returns>A <see cref="T:System.Collections.Generic.IEnumerator`1" /> that can be used to iterate through the collection.</returns>
public Dictionary<TKey, TValue>.Enumerator GetEnumerator()
{
return Dictionary.GetEnumerator();
return _dictionary.GetEnumerator();
}

#endregion
Expand All @@ -432,7 +426,7 @@ public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()

IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)Dictionary).GetEnumerator();
return ((IDictionary) _dictionary).GetEnumerator();
}

#endregion
Expand Down
2 changes: 1 addition & 1 deletion src/NSwag.Core/OpenApiDocument.cs
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ public IEnumerable<OpenApiOperationDescription> Operations
{
get
{
foreach (var p in Paths)
foreach (var p in _paths)
{
foreach (var o in p.Value.ActualPathItem)
{
Expand Down
2 changes: 1 addition & 1 deletion src/NSwag.Core/OpenApiHeaders.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
namespace NSwag
{
/// <summary>A collection of headers.</summary>
public class OpenApiHeaders : ObservableDictionary<string, OpenApiHeader>
public sealed class OpenApiHeaders : ObservableDictionary<string, OpenApiHeader>
{
}
}

0 comments on commit 33011cd

Please sign in to comment.