Skip to content

Commit a7cdf52

Browse files
committed
C#: Improve performance by mapping directly from entities to labels.
1 parent 5956341 commit a7cdf52

File tree

1 file changed

+19
-29
lines changed

1 file changed

+19
-29
lines changed

csharp/extractor/Semmle.Extraction/Context.cs

Lines changed: 19 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -50,20 +50,30 @@ public SemanticModel Model(SyntaxNode node)
5050
/// <returns><code>true</code> iff the label already existed.</returns>
5151
public bool GetOrAddCachedLabel(ICachedEntity entity)
5252
{
53-
var id = GetId(entity);
53+
// Look up the label in the entityLabelCache
54+
if (entityLabelCache.TryGetValue(entity, out Label label))
55+
{
56+
entity.Label = label;
57+
return true;
58+
}
59+
60+
var id = entity.Id;
61+
5462
if (id == null)
5563
throw new InternalError("Attempt to create a null entity for {0}", entity.GetType());
5664

57-
Label existingLabel;
58-
if (labelCache.TryGetValue(id, out existingLabel))
65+
// Look up the Id in the idLabelCache
66+
if (idLabelCache.TryGetValue(id, out label))
5967
{
60-
entity.Label = existingLabel;
68+
entity.Label = label;
69+
entityLabelCache[entity] = label;
6170
return true;
6271
}
6372

64-
entity.Label = new Label(NewId());
65-
DefineLabel(entity.Label, id);
66-
labelCache[id] = entity.Label;
73+
entity.Label = label = new Label(NewId());
74+
DefineLabel(label, id);
75+
entityLabelCache[entity] = label;
76+
idLabelCache[id] = label;
6777
return false;
6878
}
6979

@@ -90,25 +100,6 @@ public bool ExtractGenerics(ICachedEntity entity)
90100
}
91101
}
92102

93-
/// <summary>
94-
/// Gets the ID belonging to cached entity <paramref name="entity"/>.
95-
///
96-
/// The ID itself is also cached, but unlike the label cache (which is used
97-
/// to prevent reextraction/infinite loops), this is a pure performance
98-
/// optimization. Moreover, the label cache is injective, which the ID cache
99-
/// need not be.
100-
/// </summary>
101-
IId GetId(ICachedEntity entity)
102-
{
103-
IId id;
104-
if (!idCache.TryGetValue(entity, out id))
105-
{
106-
id = entity.Id;
107-
idCache[entity] = id;
108-
}
109-
return id;
110-
}
111-
112103
/// <summary>
113104
/// Creates a fresh label with ID "*", and set it on the
114105
/// supplied <paramref name="entity"/> object.
@@ -120,7 +111,8 @@ public void AddFreshLabel(IEntity entity)
120111
entity.Label = label;
121112
}
122113

123-
readonly Dictionary<IId, Label> labelCache = new Dictionary<IId, Label>();
114+
readonly Dictionary<IId, Label> idLabelCache = new Dictionary<IId, Label>();
115+
readonly Dictionary<ICachedEntity, Label> entityLabelCache = new Dictionary<ICachedEntity, Label>();
124116
readonly HashSet<Label> extractedGenerics = new HashSet<Label>();
125117

126118
public void DefineLabel(IEntity entity)
@@ -134,8 +126,6 @@ void DefineLabel(Label label, IId id)
134126
TrapWriter.Emit(new DefineLabelEmitter(label, id));
135127
}
136128

137-
readonly Dictionary<object, IId> idCache = new Dictionary<object, IId>();
138-
139129
/// <summary>
140130
/// Queue of items to populate later.
141131
/// The only reason for this is so that the call stack does not

0 commit comments

Comments
 (0)