Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 135 additions & 1 deletion src/HotChocolate/Core/src/Types/Execution/Processing/SelectionSet.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Collections.Frozen;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using System.Text;
using HotChocolate.Types;

Expand Down Expand Up @@ -107,8 +108,141 @@ public bool TryGetSelection(string responseName, [NotNullWhen(true)] out Selecti
/// <returns>
/// Returns true if the selection was successfully resolved.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool TryGetSelection(ReadOnlySpan<byte> utf8ResponseName, [NotNullWhen(true)] out Selection? selection)
=> _utf8ResponseNameLookup.TryGetSelection(utf8ResponseName, out selection);
{
// Many execution selection sets are tiny (1-4 fields), so direct
// span comparisons avoid hash computation/probing in the hot path.
var selections = _selections;

switch (selections.Length)
{
case 1:
var candidate = selections[0];

if (utf8ResponseName.SequenceEqual(candidate.Utf8ResponseName))
{
selection = candidate;
return true;
}

selection = default;
return false;

case 2:
var candidate0 = selections[0];

if (utf8ResponseName.SequenceEqual(candidate0.Utf8ResponseName))
{
selection = candidate0;
return true;
}

var candidate1 = selections[1];

if (utf8ResponseName.SequenceEqual(candidate1.Utf8ResponseName))
{
selection = candidate1;
return true;
}

selection = default;
return false;

case 3:
var firstCandidate = selections[0];

if (utf8ResponseName.SequenceEqual(firstCandidate.Utf8ResponseName))
{
selection = firstCandidate;
return true;
}

var secondCandidate = selections[1];

if (utf8ResponseName.SequenceEqual(secondCandidate.Utf8ResponseName))
{
selection = secondCandidate;
return true;
}

var thirdCandidate = selections[2];

if (utf8ResponseName.SequenceEqual(thirdCandidate.Utf8ResponseName))
{
selection = thirdCandidate;
return true;
}

selection = default;
return false;

case 4:
var firstCandidate4 = selections[0];

if (utf8ResponseName.SequenceEqual(firstCandidate4.Utf8ResponseName))
{
selection = firstCandidate4;
return true;
}

var secondCandidate4 = selections[1];

if (utf8ResponseName.SequenceEqual(secondCandidate4.Utf8ResponseName))
{
selection = secondCandidate4;
return true;
}

var thirdCandidate4 = selections[2];

if (utf8ResponseName.SequenceEqual(thirdCandidate4.Utf8ResponseName))
{
selection = thirdCandidate4;
return true;
}

var fourthCandidate4 = selections[3];

if (utf8ResponseName.SequenceEqual(fourthCandidate4.Utf8ResponseName))
{
selection = fourthCandidate4;
return true;
}

selection = default;
return false;

}

if (selections.Length <= 7)
{
return TryGetSelectionLinear(utf8ResponseName, selections, out selection);
}

return _utf8ResponseNameLookup.TryGetSelection(utf8ResponseName, out selection);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static bool TryGetSelectionLinear(
ReadOnlySpan<byte> utf8ResponseName,
Selection[] selections,
[NotNullWhen(true)] out Selection? selection)
{
for (var i = 0; i < selections.Length; i++)
{
var candidate = selections[i];

if (utf8ResponseName.SequenceEqual(candidate.Utf8ResponseName))
{
selection = candidate;
return true;
}
}

selection = default;
return false;
}

internal void Complete(Operation declaringOperation)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Collections.Frozen;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using HotChocolate.Execution;
using HotChocolate.Types;

Expand Down Expand Up @@ -92,8 +93,141 @@ public bool TryGetSelection(string responseName, [NotNullWhen(true)] out Selecti
/// <returns>
/// Returns true if the selection was successfully resolved.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool TryGetSelection(ReadOnlySpan<byte> utf8ResponseName, [NotNullWhen(true)] out Selection? selection)
=> _utf8ResponseNameLookup.TryGetSelection(utf8ResponseName, out selection);
{
// Many execution selection sets are tiny (1-4 fields), so direct
// span comparisons avoid hash computation/probing in the hot path.
var selections = _selections;

switch (selections.Length)
{
case 1:
var candidate = selections[0];

if (utf8ResponseName.SequenceEqual(candidate.Utf8ResponseName))
{
selection = candidate;
return true;
}

selection = default;
return false;

case 2:
var candidate0 = selections[0];

if (utf8ResponseName.SequenceEqual(candidate0.Utf8ResponseName))
{
selection = candidate0;
return true;
}

var candidate1 = selections[1];

if (utf8ResponseName.SequenceEqual(candidate1.Utf8ResponseName))
{
selection = candidate1;
return true;
}

selection = default;
return false;

case 3:
var firstCandidate = selections[0];

if (utf8ResponseName.SequenceEqual(firstCandidate.Utf8ResponseName))
{
selection = firstCandidate;
return true;
}

var secondCandidate = selections[1];

if (utf8ResponseName.SequenceEqual(secondCandidate.Utf8ResponseName))
{
selection = secondCandidate;
return true;
}

var thirdCandidate = selections[2];

if (utf8ResponseName.SequenceEqual(thirdCandidate.Utf8ResponseName))
{
selection = thirdCandidate;
return true;
}

selection = default;
return false;

case 4:
var firstCandidate4 = selections[0];

if (utf8ResponseName.SequenceEqual(firstCandidate4.Utf8ResponseName))
{
selection = firstCandidate4;
return true;
}

var secondCandidate4 = selections[1];

if (utf8ResponseName.SequenceEqual(secondCandidate4.Utf8ResponseName))
{
selection = secondCandidate4;
return true;
}

var thirdCandidate4 = selections[2];

if (utf8ResponseName.SequenceEqual(thirdCandidate4.Utf8ResponseName))
{
selection = thirdCandidate4;
return true;
}

var fourthCandidate4 = selections[3];

if (utf8ResponseName.SequenceEqual(fourthCandidate4.Utf8ResponseName))
{
selection = fourthCandidate4;
return true;
}

selection = default;
return false;

}

if (selections.Length <= 7)
{
return TryGetSelectionLinear(utf8ResponseName, selections, out selection);
}

return _utf8ResponseNameLookup.TryGetSelection(utf8ResponseName, out selection);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static bool TryGetSelectionLinear(
ReadOnlySpan<byte> utf8ResponseName,
Selection[] selections,
[NotNullWhen(true)] out Selection? selection)
{
for (var i = 0; i < selections.Length; i++)
{
var candidate = selections[i];

if (utf8ResponseName.SequenceEqual(candidate.Utf8ResponseName))
{
selection = candidate;
return true;
}
}

selection = default;
return false;
}

internal void Seal(Operation operation)
{
Expand Down
Loading