replaced ReadByte with 64kb buffer in parser

This commit is contained in:
2026-09-14 23:09:16 +02:00
parent f726597401
commit f1aca261ae
+65 -59
View File
@@ -1,4 +1,4 @@
global using System; global using System;
global using System.Collections.Generic; global using System.Collections.Generic;
global using System.IO; global using System.IO;
global using System.Text; global using System.Text;
@@ -80,69 +80,75 @@ public class SaveParserEU4
return true; return true;
} }
while (_saveFile.CanRead) // Reading the save one byte at a time through Stream.ReadByte() costs a virtual call
// per byte, which dominated the parsing time. Bytes are pulled into this buffer
// instead, so the stream is touched once per 64 KB and the inner loop reads an array.
byte[] buffer = new byte[64 * 1024];
int bufferLength;
while ((bufferLength = _saveFile.Read(buffer, 0, buffer.Length)) > 0)
{ {
int c = _saveFile.ReadByte(); for (int i = 0; i < bufferLength; i++)
column++;
switch (c)
{ {
case -1: int c = buffer[i];
if (TryCompleteStringToken()) column++;
yield return strToken; switch (c)
_stringBuilderPool.Return(strb); {
yield break; case '\"':
case '\"': isQuoteOpen = !isQuoteOpen;
isQuoteOpen = !isQuoteOpen; isStrInQuotes = true;
isStrInQuotes = true; break;
break; case ' ':
case ' ': case '\t':
case '\t': case '\r':
case '\r': if (TryCompleteStringToken())
if (TryCompleteStringToken()) yield return strToken;
yield return strToken; break;
break; case '\n':
case '\n': if (TryCompleteStringToken())
if (TryCompleteStringToken()) yield return strToken;
yield return strToken; line++;
line++; column = 0;
column = 0; break;
break; case '=':
case '=': if (TryCompleteStringToken())
if (TryCompleteStringToken()) yield return strToken;
yield return strToken; yield return new Token
yield return new Token {
{ type = TokenType.Equals,
type = TokenType.Equals, line = line, column = (short)column
line = line, column = (short)column };
}; break;
break; case '{':
case '{': if (TryCompleteStringToken())
if (TryCompleteStringToken()) yield return strToken;
yield return strToken; yield return new Token
yield return new Token {
{ type = TokenType.BracketOpen,
type = TokenType.BracketOpen, line = line, column = (short)column
line = line, column = (short)column };
}; break;
break; case '}':
case '}': if (TryCompleteStringToken())
if (TryCompleteStringToken()) yield return strToken;
yield return strToken; yield return new Token
yield return new Token {
{ type = TokenType.BracketClose,
type = TokenType.BracketClose, line = line, column = (short)column
line = line, column = (short)column };
}; break;
break; default:
default: // Skip control characters, which are invisible and causing frontend bugs.
// Skip control characters, which are invisible and causing frontend bugs. // I dont know why there are so many of them in strings.
// I dont know why there are so many of them in strings. if (c >= 0x20)
if (c >= 0x20) strb.Append((char)c);
strb.Append((char)c); break;
break; }
} }
} }
// end of file: the last token may still be unterminated
if (TryCompleteStringToken())
yield return strToken;
_stringBuilderPool.Return(strb); _stringBuilderPool.Return(strb);
} }