Skip to content

Commit 9ddc7f7

Browse files
committed
LZX optimizations
1 parent 9efbf89 commit 9ddc7f7

1 file changed

Lines changed: 64 additions & 11 deletions

File tree

Library/DiscUtils.Core/Compression/LzxDecoder.cs

Lines changed: 64 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -605,23 +605,76 @@ private bool CopyMatchFromWindow(
605605
src += _windowSize;
606606
}
607607

608-
for (int i = 0; i < matchLength; i++)
608+
while (matchLength > 0)
609609
{
610-
byte value = _window[src];
610+
// How much can we read contiguously from current source position
611+
// before wrapping the circular window?
612+
int srcRun = _windowSize - src;
611613

612-
if ((uint)dstPos < (uint)output.Length)
614+
// How much can we write contiguously to current window position
615+
// before wrapping the circular window?
616+
int dstRun = _windowSize - _windowPos;
617+
618+
int chunk = Math.Min(matchLength, Math.Min(srcRun, dstRun));
619+
620+
// If source and destination are safely separated inside the current
621+
// contiguous chunk, we can copy the whole chunk with Span.CopyTo.
622+
// Otherwise fall back to byte-serial copying to preserve overlap behavior.
623+
if (chunk > 0 && (src + chunk <= _windowPos || _windowPos + chunk <= src))
613624
{
614-
output[dstPos] = value;
615-
}
625+
var srcSlice = _window.Slice(src, chunk);
626+
var dstSlice = _window.Slice(_windowPos, chunk);
627+
628+
srcSlice.CopyTo(dstSlice);
629+
630+
int outChunk = Math.Min(chunk, output.Length - dstPos);
631+
if (outChunk > 0)
632+
{
633+
dstSlice.Slice(0, outChunk).CopyTo(output.Slice(dstPos, outChunk));
634+
}
616635

617-
dstPos++;
618-
blockRemaining--;
619-
WriteWindowByte(value);
636+
dstPos += chunk;
637+
blockRemaining -= chunk;
638+
matchLength -= chunk;
620639

621-
src++;
622-
if (src == _windowSize)
640+
_windowPos += chunk;
641+
if (_windowPos == _windowSize)
642+
{
643+
_windowPos = 0;
644+
}
645+
646+
src += chunk;
647+
if (src == _windowSize)
648+
{
649+
src = 0;
650+
}
651+
}
652+
else
623653
{
624-
src = 0;
654+
byte value = _window[src];
655+
656+
if ((uint)dstPos < (uint)output.Length)
657+
{
658+
output[dstPos] = value;
659+
}
660+
661+
_window[_windowPos] = value;
662+
663+
dstPos++;
664+
blockRemaining--;
665+
matchLength--;
666+
667+
src++;
668+
if (src == _windowSize)
669+
{
670+
src = 0;
671+
}
672+
673+
_windowPos++;
674+
if (_windowPos == _windowSize)
675+
{
676+
_windowPos = 0;
677+
}
625678
}
626679
}
627680

0 commit comments

Comments
 (0)