From b1d1a24b302ab6bdcbecfb5fbc625e7397e41125 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Foidl?= Date: Sun, 17 Dec 2017 16:55:47 +0100 Subject: [PATCH 1/4] SpanHelpers IndexOfAny-methods use sentinel-value Instead of having _valueLength_-times an if-check in the loop, a sentinel value is used and hence only one final checks needs to done. Perf-win depends on the size of _valueLength_, the greater the more win. --- src/System.Memory/src/System/SpanHelpers.T.cs | 9 +++------ .../src/System/SpanHelpers.byte.cs | 18 ++++++------------ 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/src/System.Memory/src/System/SpanHelpers.T.cs b/src/System.Memory/src/System/SpanHelpers.T.cs index 1c0717e3677b..ba2bddc8df1a 100644 --- a/src/System.Memory/src/System/SpanHelpers.T.cs +++ b/src/System.Memory/src/System/SpanHelpers.T.cs @@ -59,16 +59,13 @@ public static int LastIndexOfAny(ref T searchSpace, int searchSpaceLength, re if (valueLength == 0) return 0; // A zero-length sequence is always treated as "found" at the start of the search space. - int index = -1; + int index = int.MinValue; for (int i = 0; i < valueLength; i++) { var tempIndex = LastIndexOf(ref searchSpace, Unsafe.Add(ref value, i), searchSpaceLength); - if (tempIndex != -1) - { - index = (index == -1 || index < tempIndex) ? tempIndex : index; - } + index = (tempIndex == -1 || index > tempIndex) ? index : tempIndex; } - return index; + return index == int.MinValue ? -1 : index; } public static unsafe int IndexOf(ref T searchSpace, T value, int length) diff --git a/src/System.Memory/src/System/SpanHelpers.byte.cs b/src/System.Memory/src/System/SpanHelpers.byte.cs index 89d6139aeaa3..2953cea26061 100644 --- a/src/System.Memory/src/System/SpanHelpers.byte.cs +++ b/src/System.Memory/src/System/SpanHelpers.byte.cs @@ -60,16 +60,13 @@ public static int IndexOfAny(ref byte searchSpace, int searchSpaceLength, ref by if (valueLength == 0) return 0; // A zero-length sequence is always treated as "found" at the start of the search space. - int index = -1; + int index = int.MaxValue; for (int i = 0; i < valueLength; i++) { var tempIndex = IndexOf(ref searchSpace, Unsafe.Add(ref value, i), searchSpaceLength); - if (tempIndex != -1) - { - index = (index == -1 || index > tempIndex) ? tempIndex : index; - } + index = (tempIndex == -1 || tempIndex > index) ? index : tempIndex; } - return index; + return index == int.MaxValue ? -1 : index; } public static int LastIndexOfAny(ref byte searchSpace, int searchSpaceLength, ref byte value, int valueLength) @@ -80,16 +77,13 @@ public static int LastIndexOfAny(ref byte searchSpace, int searchSpaceLength, re if (valueLength == 0) return 0; // A zero-length sequence is always treated as "found" at the start of the search space. - int index = -1; + int index = int.MinValue; for (int i = 0; i < valueLength; i++) { var tempIndex = LastIndexOf(ref searchSpace, Unsafe.Add(ref value, i), searchSpaceLength); - if (tempIndex != -1) - { - index = (index == -1 || index < tempIndex) ? tempIndex : index; - } + index = (tempIndex == -1 || index > tempIndex) ? index : tempIndex; } - return index; + return index == int.MinValue ? -1 : index; } public static unsafe int IndexOf(ref byte searchSpace, byte value, int length) From 4775ee6ab7399b600e4d5f80872b98e95e55e9ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Foidl?= Date: Sun, 17 Dec 2017 18:10:03 +0100 Subject: [PATCH 2/4] LastIndexOf initializes index with -1 instead of int.MinValue As of PR-feedback. --- src/System.Memory/src/System/SpanHelpers.T.cs | 6 +++--- src/System.Memory/src/System/SpanHelpers.byte.cs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/System.Memory/src/System/SpanHelpers.T.cs b/src/System.Memory/src/System/SpanHelpers.T.cs index ba2bddc8df1a..7fb90bc4032b 100644 --- a/src/System.Memory/src/System/SpanHelpers.T.cs +++ b/src/System.Memory/src/System/SpanHelpers.T.cs @@ -59,13 +59,13 @@ public static int LastIndexOfAny(ref T searchSpace, int searchSpaceLength, re if (valueLength == 0) return 0; // A zero-length sequence is always treated as "found" at the start of the search space. - int index = int.MinValue; + int index = -1; for (int i = 0; i < valueLength; i++) { var tempIndex = LastIndexOf(ref searchSpace, Unsafe.Add(ref value, i), searchSpaceLength); - index = (tempIndex == -1 || index > tempIndex) ? index : tempIndex; + index = (index > tempIndex) ? index : tempIndex; } - return index == int.MinValue ? -1 : index; + return index; } public static unsafe int IndexOf(ref T searchSpace, T value, int length) diff --git a/src/System.Memory/src/System/SpanHelpers.byte.cs b/src/System.Memory/src/System/SpanHelpers.byte.cs index 2953cea26061..9d831ed2c619 100644 --- a/src/System.Memory/src/System/SpanHelpers.byte.cs +++ b/src/System.Memory/src/System/SpanHelpers.byte.cs @@ -77,13 +77,13 @@ public static int LastIndexOfAny(ref byte searchSpace, int searchSpaceLength, re if (valueLength == 0) return 0; // A zero-length sequence is always treated as "found" at the start of the search space. - int index = int.MinValue; + int index = -1; for (int i = 0; i < valueLength; i++) { var tempIndex = LastIndexOf(ref searchSpace, Unsafe.Add(ref value, i), searchSpaceLength); - index = (tempIndex == -1 || index > tempIndex) ? index : tempIndex; + index = (index > tempIndex) ? index : tempIndex; } - return index == int.MinValue ? -1 : index; + return index; } public static unsafe int IndexOf(ref byte searchSpace, byte value, int length) From 5b646dd66cbb8e09fc4b1aae831ad21a412d973c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Foidl?= Date: Sun, 17 Dec 2017 19:11:57 +0100 Subject: [PATCH 3/4] Better checks based on if instead of ternary operator As of PR-feedback. --- src/System.Memory/src/System/SpanHelpers.T.cs | 2 +- src/System.Memory/src/System/SpanHelpers.byte.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/System.Memory/src/System/SpanHelpers.T.cs b/src/System.Memory/src/System/SpanHelpers.T.cs index 7fb90bc4032b..00572573429e 100644 --- a/src/System.Memory/src/System/SpanHelpers.T.cs +++ b/src/System.Memory/src/System/SpanHelpers.T.cs @@ -63,7 +63,7 @@ public static int LastIndexOfAny(ref T searchSpace, int searchSpaceLength, re for (int i = 0; i < valueLength; i++) { var tempIndex = LastIndexOf(ref searchSpace, Unsafe.Add(ref value, i), searchSpaceLength); - index = (index > tempIndex) ? index : tempIndex; + if (tempIndex > index) index = tempIndex; } return index; } diff --git a/src/System.Memory/src/System/SpanHelpers.byte.cs b/src/System.Memory/src/System/SpanHelpers.byte.cs index 9d831ed2c619..69b642cf155b 100644 --- a/src/System.Memory/src/System/SpanHelpers.byte.cs +++ b/src/System.Memory/src/System/SpanHelpers.byte.cs @@ -64,7 +64,7 @@ public static int IndexOfAny(ref byte searchSpace, int searchSpaceLength, ref by for (int i = 0; i < valueLength; i++) { var tempIndex = IndexOf(ref searchSpace, Unsafe.Add(ref value, i), searchSpaceLength); - index = (tempIndex == -1 || tempIndex > index) ? index : tempIndex; + if ((uint)tempIndex < (uint)index) index = tempIndex; } return index == int.MaxValue ? -1 : index; } @@ -81,7 +81,7 @@ public static int LastIndexOfAny(ref byte searchSpace, int searchSpaceLength, re for (int i = 0; i < valueLength; i++) { var tempIndex = LastIndexOf(ref searchSpace, Unsafe.Add(ref value, i), searchSpaceLength); - index = (index > tempIndex) ? index : tempIndex; + if (tempIndex > index) index = tempIndex; } return index; } From c9548f34585d1a4f706346a5f1da89dc55b7ae9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Foidl?= Date: Sun, 17 Dec 2017 21:06:04 +0100 Subject: [PATCH 4/4] SpanHelpers.byte.cs IndexOfAny can avoid int.MaxValue due to unit-trick As of PR-Feedback --- src/System.Memory/src/System/SpanHelpers.byte.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/System.Memory/src/System/SpanHelpers.byte.cs b/src/System.Memory/src/System/SpanHelpers.byte.cs index 69b642cf155b..c0f07296e7f9 100644 --- a/src/System.Memory/src/System/SpanHelpers.byte.cs +++ b/src/System.Memory/src/System/SpanHelpers.byte.cs @@ -60,13 +60,13 @@ public static int IndexOfAny(ref byte searchSpace, int searchSpaceLength, ref by if (valueLength == 0) return 0; // A zero-length sequence is always treated as "found" at the start of the search space. - int index = int.MaxValue; + int index = -1; for (int i = 0; i < valueLength; i++) { var tempIndex = IndexOf(ref searchSpace, Unsafe.Add(ref value, i), searchSpaceLength); if ((uint)tempIndex < (uint)index) index = tempIndex; } - return index == int.MaxValue ? -1 : index; + return index; } public static int LastIndexOfAny(ref byte searchSpace, int searchSpaceLength, ref byte value, int valueLength)