-
Notifications
You must be signed in to change notification settings - Fork 0
Conversation
var idxA = currentIndex | ||
var idxB = subsequence.startIndex | ||
|
||
// iterating through both indices is MUCH faster than constructing and comparing | ||
// a substring slice, especially since we get early exist on the first mismatched | ||
// character. | ||
repeat { | ||
if rest[idxA] != subsequence[idxB] { | ||
return false | ||
} | ||
|
||
idxA = rest.index(after: idxA) | ||
idxB = subsequence.index(after: idxB) | ||
} while idxB < subsequence.endIndex | ||
|
||
self.currentIndex = endIndex | ||
return true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I found this one speedup to be equally effective vs. storing an array of indices (a la https://maximeremenko.com/string-random-access)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting!
There may still be an advantage to storing indices in an array once at Tape creation IFF it has the same performance characteristics.
this.indices = Array(base.indices)
The reason is that consumeMatch
is just one place where we want to do this kind of operation. I think we use it for most of the parser, but there are other cases where we might want to use peek
or other helpers.
We also use Substring
and Substring.Index
in a bookkeeping role, for example, to keep track of the rest
position and startIndex
. I'm wondering if we could get a performance improvement by storing indices in an array, and thus avoiding the manipulation of Substring
indexes altogether.
rest()
could become aRange<Int>
that indexes intoindices
advance()
coud increment anInt
counter by one- Etc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's leave that for a future exploration.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did test exactly this and found it didn't significantly affect indexing time, but I agree it may be worth further investigation. Specifically: if we could speed up the attributed string renderer our UI would feel significantly more responsive in list views.
e4486e8
to
0991a48
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just one small request to update comment. Otherwise LGTM!
Great work.
var idxA = currentIndex | ||
var idxB = subsequence.startIndex | ||
|
||
// iterating through both indices is MUCH faster than constructing and comparing | ||
// a substring slice, especially since we get early exist on the first mismatched | ||
// character. | ||
repeat { | ||
if rest[idxA] != subsequence[idxB] { | ||
return false | ||
} | ||
|
||
idxA = rest.index(after: idxA) | ||
idxB = subsequence.index(after: idxB) | ||
} while idxB < subsequence.endIndex | ||
|
||
self.currentIndex = endIndex | ||
return true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting!
There may still be an advantage to storing indices in an array once at Tape creation IFF it has the same performance characteristics.
this.indices = Array(base.indices)
The reason is that consumeMatch
is just one place where we want to do this kind of operation. I think we use it for most of the parser, but there are other cases where we might want to use peek
or other helpers.
We also use Substring
and Substring.Index
in a bookkeeping role, for example, to keep track of the rest
position and startIndex
. I'm wondering if we could get a performance improvement by storing indices in an array, and thus avoiding the manipulation of Substring
indexes altogether.
rest()
could become aRange<Int>
that indexes intoindices
advance()
coud increment anInt
counter by one- Etc
var idxA = currentIndex | ||
var idxB = subsequence.startIndex | ||
|
||
// iterating through both indices is MUCH faster than constructing and comparing | ||
// a substring slice, especially since we get early exist on the first mismatched | ||
// character. | ||
repeat { | ||
if rest[idxA] != subsequence[idxB] { | ||
return false | ||
} | ||
|
||
idxA = rest.index(after: idxA) | ||
idxB = subsequence.index(after: idxB) | ||
} while idxB < subsequence.endIndex | ||
|
||
self.currentIndex = endIndex | ||
return true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's leave that for a future exploration.
Speeds up indexing between 4x and 6x.
Before
After