Skip to content

Commit

Permalink
[Performance] Speed up string reading by 30% (especially for scn)
Browse files Browse the repository at this point in the history
  • Loading branch information
UlyssesWu committed Jul 31, 2018
1 parent 3d7cb41 commit 0a07a11
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 6 deletions.
1 change: 0 additions & 1 deletion FreeMote.Psb/Psb.cs
Expand Up @@ -2,7 +2,6 @@
//#define DEBUG_OBJECT_WRITE //Enable if you want to check how much bytes each object costs.
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.IO;
using System.Linq;
Expand Down
129 changes: 129 additions & 0 deletions FreeMote.Tests/FreeMoteTest.cs
Expand Up @@ -4,6 +4,7 @@
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using FreeMote.Plugins;
using Microsoft.VisualStudio.TestTools.UnitTesting;

Expand Down Expand Up @@ -226,5 +227,133 @@ public void TestRGBA4444()

RL.ConvertToImageFile(bts, "rgba4444.png", 2048, 2048, PsbImageFormat.Png, PsbPixelFormat.WinRGBA4444);
}

[TestMethod]
public void TestReadWriteZeroTrimString()
{
string ReadPeekAndAppend(BinaryReader br)
{
StringBuilder sb = new StringBuilder();
while (br.PeekChar() != 0)
{
sb.Append(br.ReadChar());
}
br.ReadByte(); //skip \0 - fail if end without \0
return sb.ToString();
}

string ReadDetectAndSwallow(BinaryReader br)
{
var pos = br.BaseStream.Position;
var length = 0;
while (br.ReadByte() > 0)
{
length++;
}
br.BaseStream.Position = pos;
var str = Encoding.UTF8.GetString(br.ReadBytes(length));
br.ReadByte(); //skip \0 - fail if end without \0
return str;
}

//Generate super long string
var theNatureOfHuman = "人类的本质是:";
var bts = Encoding.UTF8.GetBytes(theNatureOfHuman);
using (var ms = new MemoryStream())
using (var bw = new BinaryWriter(ms))
using (var br = new BinaryReader(ms))
{
for (int i = 0; i < 100_0000; i++)
{
bw.Write(bts);
}
bw.Write((byte)0);

Console.WriteLine("Read 1 long string:");
ms.Position = 0;
Stopwatch sw = Stopwatch.StartNew();
var r = ReadPeekAndAppend(br);
sw.Stop();
var time = sw.Elapsed;
Console.WriteLine($"Time of {nameof(ReadPeekAndAppend)}: \t{time}");

ms.Position = 0;
sw.Restart();
r = ReadDetectAndSwallow(br);
sw.Stop();
time = sw.Elapsed;
Console.WriteLine($"Time of {nameof(ReadDetectAndSwallow)}: \t{time}");

ms.SetLength(0); //Clear
for (int i = 0; i < 100_0000; i++)
{
bw.Write(bts);
bw.Write((byte)0);
}

Console.WriteLine("Read 100_0000 short strings:");
ms.Position = 0;
sw.Restart();
while (br.BaseStream.Position < br.BaseStream.Length)
{
r = ReadPeekAndAppend(br);
}
sw.Stop();
time = sw.Elapsed;
Console.WriteLine($"Time of {nameof(ReadPeekAndAppend)}:\t{time}");

ms.Position = 0;
sw.Restart();
while (br.BaseStream.Position < br.BaseStream.Length)
{
r = ReadDetectAndSwallow(br);
}
sw.Stop();
time = sw.Elapsed;
Console.WriteLine($"Time of {nameof(ReadDetectAndSwallow)}:\t{time}");

ms.Position = 0;
Console.WriteLine("PeekChar vs AppendChar:");

sw.Restart();
for (int i = 0; i < 100_0000; i++)
{
br.PeekChar();
}
sw.Stop();
time = sw.Elapsed;
Console.WriteLine($"Time of PeekChar: \t{time}");

StringBuilder sb = new StringBuilder();
sw.Restart();
for (int i = 0; i < 100_0000; i++)
{
sb.Append('咕');
}
//r = sb.ToString();
sw.Stop();
time = sw.Elapsed;
Console.WriteLine($"Time of Append: \t{time}");

Console.WriteLine("Write 1 long string:");
ms.SetLength(0);
r = sb.ToString();

sw.Restart();
bw.Write(r.ToCharArray());
bw.Write((byte) 0);
sw.Stop();
time = sw.Elapsed;
Console.WriteLine($"Time of ToCharArray: \t{time}");

sw.Restart();
bw.Write(Encoding.UTF8.GetBytes(r));
bw.Write((byte)0);
sw.Stop();
time = sw.Elapsed;
Console.WriteLine($"Time of GetBytes: \t{time}");
}

}
}
}
17 changes: 12 additions & 5 deletions FreeMote/PsbConstants.cs
Expand Up @@ -23,6 +23,8 @@ public static class PsbConstants
/// </summary>
public const uint Key3 = 521288629;

public static Encoding PsbEncoding { get; set; } = Encoding.UTF8;

public static string ToStringForPsb(this PsbPixelFormat pixelFormat)
{
switch (pixelFormat)
Expand Down Expand Up @@ -98,17 +100,22 @@ public static void Write(this PsbStreamContext context, ushort value, BinaryWrit

public static string ReadStringZeroTrim(this BinaryReader br)
{
StringBuilder sb = new StringBuilder();
while (br.PeekChar() != 0)
var pos = br.BaseStream.Position;
var length = 0;
while (br.ReadByte() > 0)
{
sb.Append(br.ReadChar());
length++;
}
return sb.ToString();
br.BaseStream.Position = pos;
var str = PsbEncoding.GetString(br.ReadBytes(length));
br.ReadByte(); //skip \0 - fail if end without \0
return str;
}

public static void WriteStringZeroTrim(this BinaryWriter bw, string str)
{
bw.Write(str.ToCharArray());
//bw.Write(str.ToCharArray());
bw.Write(PsbEncoding.GetBytes(str));
bw.Write((byte)0);
}

Expand Down

0 comments on commit 0a07a11

Please sign in to comment.