-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Small irc parsing performance improvements (#39)
- Loading branch information
Showing
22 changed files
with
562 additions
and
463 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
using System.Text; | ||
using BenchmarkDotNet.Attributes; | ||
using MiniTwitch.Irc.Internal.Models; | ||
|
||
namespace MiniTwitch.Irc.Benchmarks; | ||
|
||
[MemoryDiagnoser(false)] | ||
public class Benchmarks | ||
{ | ||
private byte[][] utf8Lines = null!; | ||
private readonly IrcClient _client = new(op => op.Anonymous = true); | ||
|
||
[Params(1, 100, 1000)] | ||
public int LineCount { get; set; } | ||
|
||
[GlobalSetup] | ||
public void AddData() | ||
{ | ||
utf8Lines = File.ReadAllText("data.txt").Split('\0').Take(LineCount).Select(Encoding.UTF8.GetBytes).ToArray(); | ||
Console.WriteLine(utf8Lines.Length); | ||
} | ||
|
||
[Benchmark] | ||
public void Create() | ||
{ | ||
foreach (var line in utf8Lines.AsSpan()) | ||
{ | ||
_ = new IrcMessage(line); | ||
} | ||
} | ||
|
||
[Benchmark] | ||
public void Create_Parse() | ||
{ | ||
foreach (var line in utf8Lines.AsSpan()) | ||
{ | ||
var msg = new IrcMessage(line); | ||
_ = msg.ParseTags(); | ||
_ = msg.GetChannel(); | ||
_ = msg.GetContent(); | ||
_ = msg.GetUsername(); | ||
} | ||
} | ||
|
||
[Benchmark] | ||
public void Create_Parse_Map_Send() | ||
{ | ||
foreach (var line in utf8Lines.AsSpan()) | ||
{ | ||
_client.Parse(line); | ||
} | ||
} | ||
} |
22 changes: 22 additions & 0 deletions
22
MiniTwitch.Irc.Benchmarks/MiniTwitch.Irc.Benchmarks.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<OutputType>Exe</OutputType> | ||
<TargetFramework>net7.0</TargetFramework> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<Nullable>enable</Nullable> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="BenchmarkDotNet" Version="0.13.9" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\MiniTwitch.Irc\MiniTwitch.Irc.csproj" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<Content Include="data.txt" CopyToOutputDirectory="Always" /> | ||
</ItemGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
using BenchmarkDotNet.Running; | ||
using MiniTwitch.Irc.Benchmarks; | ||
|
||
BenchmarkRunner.Run<Benchmarks>(); |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
using System.Text; | ||
using MiniTwitch.Irc.Internal.Enums; | ||
using MiniTwitch.Irc.Internal.Models; | ||
using MiniTwitch.Irc.Internal.Parsing; | ||
using Xunit; | ||
|
||
|
@@ -10,78 +11,67 @@ public class CommandParsingTests | |
public void Parse_PRIVMSG() | ||
{ | ||
string raw = "@badge-info=subscriber/42;badges=subscriber/42,glhf-pledge/1;color=#F97304;display-name=zneix;emotes=;first-msg=0;flags=;id=ffc033d5-862c-413c-8422-72a59aa1b0f1;mod=0;returning-chatter=0;room-id=11148817;subscriber=1;tmi-sent-ts=1678752306574;turbo=0;user-id=99631238;user-type= :[email protected] PRIVMSG #pajlada :btw DFantasy, have you gotten an unused Dragon Hunter Crossbow just laying around by any chance? kkOna"; | ||
ReadOnlySpan<byte> span = Encoding.UTF8.GetBytes(raw).AsSpan(); | ||
Assert.Equal(IrcCommand.PRIVMSG, IrcParsing.ParseCommand(span).cmd); | ||
Assert.Equal(IrcCommand.PRIVMSG, new IrcMessage(Encoding.UTF8.GetBytes(raw)).Command); | ||
} | ||
[Fact] | ||
public void Parse_USERNOTICE() | ||
{ | ||
string raw = "@badge-info=subscriber/15;badges=subscriber/12;color=#BAFF2F;display-name=VOJTERIS;emotes=;flags=;id=267bffe6-534c-4ddc-a11c-d32b242d8734;login=vojteris;mod=0;msg-id=resub;msg-param-cumulative-months=15;msg-param-months=0;msg-param-multimonth-duration=0;msg-param-multimonth-tenure=0;msg-param-should-share-streak=0;msg-param-sub-plan-name=look\\sat\\sthose\\sshitty\\semotes,\\srip\\s$5\\sLUL;msg-param-sub-plan=1000;msg-param-was-gifted=false;room-id=11148817;subscriber=1;system-msg=VOJTERIS\\ssubscribed\\sat\\sTier\\s1.\\sThey've\\ssubscribed\\sfor\\s15\\smonths!;tmi-sent-ts=1678743959736;user-id=75436142;user-type= :tmi.twitch.tv USERNOTICE #pajlada :egFors TeaTime"; | ||
ReadOnlySpan<byte> span = Encoding.UTF8.GetBytes(raw).AsSpan(); | ||
Assert.Equal(IrcCommand.USERNOTICE, IrcParsing.ParseCommand(span).cmd); | ||
Assert.Equal(IrcCommand.USERNOTICE, new IrcMessage(Encoding.UTF8.GetBytes(raw)).Command); | ||
} | ||
[Fact] | ||
public void Parse_CLEARCHAT() | ||
{ | ||
string raw = "@ban-duration=30;room-id=11148817;target-user-id=783267696;tmi-sent-ts=1678712873805 :tmi.twitch.tv CLEARCHAT #pajlada :occluder"; | ||
ReadOnlySpan<byte> span = Encoding.UTF8.GetBytes(raw).AsSpan(); | ||
Assert.Equal(IrcCommand.CLEARCHAT, IrcParsing.ParseCommand(span).cmd); | ||
Assert.Equal(IrcCommand.CLEARCHAT, new IrcMessage(Encoding.UTF8.GetBytes(raw)).Command); | ||
} | ||
[Fact] | ||
public void Parse_WHISPER() | ||
{ | ||
string raw = "@badges=;color=#2E8B57;display-name=pajbot;emotes=25:7-11;message-id=7;thread-id=82008718_783267696;turbo=0;user-id=82008718;user-type= :[email protected] WHISPER occluder :Riftey Kappa"; | ||
ReadOnlySpan<byte> span = Encoding.UTF8.GetBytes(raw).AsSpan(); | ||
Assert.Equal(IrcCommand.WHISPER, IrcParsing.ParseCommand(span).cmd); | ||
Assert.Equal(IrcCommand.WHISPER, new IrcMessage(Encoding.UTF8.GetBytes(raw)).Command); | ||
} | ||
[Fact] | ||
public void Parse_ROOMSTATE() | ||
{ | ||
string raw = "@emote-only=0;followers-only=-1;r9k=0;room-id=783267696;slow=0;subs-only=0 :tmi.twitch.tv ROOMSTATE #occluder"; | ||
ReadOnlySpan<byte> span = Encoding.UTF8.GetBytes(raw).AsSpan(); | ||
Assert.Equal(IrcCommand.ROOMSTATE, IrcParsing.ParseCommand(span).cmd); | ||
Assert.Equal(IrcCommand.ROOMSTATE, new IrcMessage(Encoding.UTF8.GetBytes(raw)).Command); | ||
} | ||
[Fact] | ||
public void Parse_NOTICE() | ||
{ | ||
string raw = "@msg-id=msg_channel_suspended :tmi.twitch.tv NOTICE #foretack :This channel does not exist or has been suspended."; | ||
ReadOnlySpan<byte> span = Encoding.UTF8.GetBytes(raw).AsSpan(); | ||
Assert.Equal(IrcCommand.NOTICE, IrcParsing.ParseCommand(span).cmd); | ||
Assert.Equal(IrcCommand.NOTICE, new IrcMessage(Encoding.UTF8.GetBytes(raw)).Command); | ||
} | ||
[Fact] | ||
public void Parse_CLEARMSG() | ||
{ | ||
string raw = "@login=occluder;room-id=;target-msg-id=55dc74c9-a6b2-4443-9b68-3446a5ddb7ed;tmi-sent-ts=1678798254260 :tmi.twitch.tv CLEARMSG #occluder :@emote-only=0;followers-only=-1;r9k=0;room-id=783267696;slow=0;subs-only=0 :tmi.twitch.tv ROOMSTATE #occluder "; | ||
ReadOnlySpan<byte> span = Encoding.UTF8.GetBytes(raw).AsSpan(); | ||
Assert.Equal(IrcCommand.CLEARMSG, IrcParsing.ParseCommand(span).cmd); | ||
Assert.Equal(IrcCommand.CLEARMSG, new IrcMessage(Encoding.UTF8.GetBytes(raw)).Command); | ||
} | ||
[Fact] | ||
public void Parse_USERSTATE() | ||
{ | ||
string raw = "@badge-info=;badges=broadcaster/1;color=#F2647B;display-name=occluder;emote-sets=0,4236,15961,19194,376284588,385292559,477339272,5fc5e142-d394-481f-a561-5406c2ba3ef0,e21484e8-cf11-48b1-8b67-c180fa39f926;mod=0;subscriber=0;user-type= :tmi.twitch.tv USERSTATE #occluder"; | ||
ReadOnlySpan<byte> span = Encoding.UTF8.GetBytes(raw).AsSpan(); | ||
Assert.Equal(IrcCommand.USERSTATE, IrcParsing.ParseCommand(span).cmd); | ||
Assert.Equal(IrcCommand.USERSTATE, new IrcMessage(Encoding.UTF8.GetBytes(raw)).Command); | ||
} | ||
[Fact] | ||
public void Parse_RECONNECT() | ||
{ | ||
string raw = ":tmi.twitch.tv RECONNECT"; | ||
ReadOnlySpan<byte> span = Encoding.UTF8.GetBytes(raw).AsSpan(); | ||
Assert.Equal(IrcCommand.RECONNECT, IrcParsing.ParseCommand(span).cmd); | ||
Assert.Equal(IrcCommand.RECONNECT, new IrcMessage(Encoding.UTF8.GetBytes(raw)).Command); | ||
} | ||
[Fact] | ||
public void Parse_PING() | ||
{ | ||
string raw = "PING :tmi.twitch.tv"; | ||
ReadOnlySpan<byte> span = Encoding.UTF8.GetBytes(raw).AsSpan(); | ||
Assert.Equal(IrcCommand.PING, IrcParsing.ParseCommand(span).cmd); | ||
Assert.Equal(IrcCommand.PING, new IrcMessage(Encoding.UTF8.GetBytes(raw)).Command); | ||
} | ||
[Fact] | ||
public void Parse_PONG() | ||
{ | ||
string raw = "PONG :tmi.twitch.tv"; | ||
ReadOnlySpan<byte> span = Encoding.UTF8.GetBytes(raw).AsSpan(); | ||
Assert.Equal(IrcCommand.PONG, IrcParsing.ParseCommand(span).cmd); | ||
Assert.Equal(IrcCommand.PONG, new IrcMessage(Encoding.UTF8.GetBytes(raw)).Command); | ||
} | ||
[Fact] | ||
public void Parse_Multiple() | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
using System.Text; | ||
using MiniTwitch.Irc.Internal.Models; | ||
using MiniTwitch.Irc.Internal.Parsing; | ||
using Xunit; | ||
|
||
|
@@ -9,18 +10,7 @@ public class IrcParsingTests | |
public void Find_Channel() | ||
{ | ||
string raw = ":[email protected] JOIN #bar"; | ||
ReadOnlySpan<byte> span = Encoding.UTF8.GetBytes(raw).AsSpan(); | ||
string channel = IrcParsing.FindChannel(span); | ||
|
||
Assert.Equal("bar", channel); | ||
} | ||
|
||
[Fact] | ||
public void Find_Channel_AnySeparator() | ||
{ | ||
string raw = ":[email protected] JOIN #bar\r\n"; | ||
ReadOnlySpan<byte> span = Encoding.UTF8.GetBytes(raw).AsSpan(); | ||
string channel = IrcParsing.FindChannel(span, true); | ||
string channel = new IrcMessage(Encoding.UTF8.GetBytes(raw)).GetChannel(); | ||
|
||
Assert.Equal("bar", channel); | ||
} | ||
|
@@ -29,8 +19,7 @@ public void Find_Channel_AnySeparator() | |
public void Find_Content() | ||
{ | ||
string raw = "@badge-info=subscriber/11;badges=subscriber/6;color=#F2647B;display-name=occluder;emotes=;first-msg=0;flags=;id=e674e393-1230-4a89-bebc-fae1f925e52c;mod=0;returning-chatter=0;room-id=11148817;subscriber=1;tmi-sent-ts=1680255594264;turbo=0;user-id=783267696;user-type= :[email protected] PRIVMSG #pajlada :Are you on some dank browser jammehcow"; | ||
ReadOnlySpan<byte> span = Encoding.UTF8.GetBytes(raw).AsSpan(); | ||
string content = IrcParsing.FindContent(span).Content; | ||
string content = new IrcMessage(Encoding.UTF8.GetBytes(raw)).GetContent().Content; | ||
|
||
Assert.Equal("Are you on some dank browser jammehcow", content); | ||
} | ||
|
@@ -39,8 +28,7 @@ public void Find_Content() | |
public void Find_Content_Empty() | ||
{ | ||
string raw = "@badge-info=subscriber/5;badges=subscriber/3;color=#5F9EA0;display-name=Syn993;emotes=;flags=;id=401d17b8-363a-4f63-85c8-cd5996fbd4e0;login=syn993;mod=0;msg-id=resub;msg-param-cumulative-months=5;msg-param-months=0;msg-param-multimonth-duration=0;msg-param-multimonth-tenure=0;msg-param-should-share-streak=1;msg-param-streak-months=4;msg-param-sub-plan-name=Channel\\sSubscription\\s(mandeow);msg-param-sub-plan=1000;msg-param-was-gifted=false;room-id=128856353;subscriber=1;system-msg=Syn993\\ssubscribed\\sat\\sTier\\s1.\\sThey've\\ssubscribed\\sfor\\s5\\smonths,\\scurrently\\son\\sa\\s4\\smonth\\sstreak!;tmi-sent-ts=1678873100296;user-id=79085174;user-type= :tmi.twitch.tv USERNOTICE #mande"; | ||
ReadOnlySpan<byte> span = Encoding.UTF8.GetBytes(raw).AsSpan(); | ||
string content = IrcParsing.FindContent(span, maybeEmpty: true).Content; | ||
string content = new IrcMessage(Encoding.UTF8.GetBytes(raw)).GetContent().Content; | ||
|
||
Assert.Equal(string.Empty, content); | ||
} | ||
|
@@ -49,19 +37,16 @@ public void Find_Content_Empty() | |
public void Find_Content_Action() | ||
{ | ||
string raw = "@badge-info=subscriber/1;badges=subscriber/0;color=#9ACD32;display-name=FeelsCzechMan;emotes=425671:13-20;first-msg=0;flags=;id=0012619e-8e14-4d51-93c9-e9d6fd5a178b;mod=0;returning-chatter=0;room-id=11148817;subscriber=1;tmi-sent-ts=1679730451594;turbo=0;user-id=875745889;user-type= :[email protected] PRIVMSG #pajlada :\u0001ACTION FeelsDankMan PowerUpR DANK WAVE▂▃▄▅▆▇██▇▆▅▄▃▂▂▃▄▅▆▇██▇▆▅▄▃▂▂▃▄▅▆▇██▇▆▅▄▃▂▂▃▄▅▆▇██▇▆▅▄▃▂▂▃▄▅▆▇██▇▆▅▄▃▂\u0001"; | ||
ReadOnlySpan<byte> span = Encoding.UTF8.GetBytes(raw).AsSpan(); | ||
(string content, bool action) = IrcParsing.FindContent(span, maybeAction: true); | ||
|
||
Assert.True(action); | ||
(string content, bool action) = new IrcMessage(Encoding.UTF8.GetBytes(raw)).GetContent(maybeAction: true); | ||
Assert.Equal("FeelsDankMan PowerUpR DANK WAVE▂▃▄▅▆▇██▇▆▅▄▃▂▂▃▄▅▆▇██▇▆▅▄▃▂▂▃▄▅▆▇██▇▆▅▄▃▂▂▃▄▅▆▇██▇▆▅▄▃▂▂▃▄▅▆▇██▇▆▅▄▃▂", content); | ||
Assert.True(action); | ||
} | ||
|
||
[Fact] | ||
public void Find_Content_InvalidAction() | ||
{ | ||
string raw = "@badge-info=subscriber/1;badges=subscriber/0;color=#9ACD32;display-name=FeelsCzechMan;emotes=425671:13-20;first-msg=0;flags=;id=0012619e-8e14-4d51-93c9-e9d6fd5a178b;mod=0;returning-chatter=0;room-id=11148817;subscriber=1;tmi-sent-ts=1679730451594;turbo=0;user-id=875745889;user-type= :[email protected] PRIVMSG #pajlada :\u0001ACTION \u0001"; | ||
ReadOnlySpan<byte> span = Encoding.UTF8.GetBytes(raw).AsSpan(); | ||
(string content, bool action) = IrcParsing.FindContent(span, maybeAction: true); | ||
(string content, bool action) = new IrcMessage(Encoding.UTF8.GetBytes(raw)).GetContent(); | ||
|
||
Assert.False(action); | ||
Assert.Equal("\u0001ACTION \u0001", content); | ||
|
@@ -71,8 +56,7 @@ public void Find_Content_InvalidAction() | |
public void Find_Username() | ||
{ | ||
string raw = "@badge-info=subscriber/1;badges=subscriber/0;color=#9ACD32;display-name=FeelsCzechMan;emotes=425671:13-20;first-msg=0;flags=;id=0012619e-8e14-4d51-93c9-e9d6fd5a178b;mod=0;returning-chatter=0;room-id=11148817;subscriber=1;tmi-sent-ts=1679730451594;turbo=0;user-id=875745889;user-type= :[email protected] PRIVMSG #pajlada :\u0001ACTION FeelsDankMan PowerUpR DANK WAVE▂▃▄▅▆▇██▇▆▅▄▃▂▂▃▄▅▆▇██▇▆▅▄▃▂▂▃▄▅▆▇██▇▆▅▄▃▂▂▃▄▅▆▇██▇▆▅▄▃▂▂▃▄▅▆▇██▇▆▅▄▃▂\u0001"; | ||
ReadOnlySpan<byte> span = Encoding.UTF8.GetBytes(raw).AsSpan(); | ||
string username = IrcParsing.FindUsername(span); | ||
string username = new IrcMessage(Encoding.UTF8.GetBytes(raw)).GetUsername(); | ||
|
||
Assert.Equal("feelsczechman", username); | ||
} | ||
|
@@ -81,8 +65,7 @@ public void Find_Username() | |
public void Find_Username_NoTags() | ||
{ | ||
string raw = ":[email protected] JOIN #bar"; | ||
ReadOnlySpan<byte> span = Encoding.UTF8.GetBytes(raw).AsSpan(); | ||
string username = IrcParsing.FindUsername(span, true); | ||
string username = new IrcMessage(Encoding.UTF8.GetBytes(raw)).GetUsername(); | ||
|
||
Assert.Equal("pajapajapaja", username); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
using System.Runtime.CompilerServices; | ||
|
||
[assembly: InternalsVisibleTo("MiniTwitch.Irc.Test")] | ||
[assembly: InternalsVisibleTo("MiniTwitch.Irc.Benchmarks")] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
namespace MiniTwitch.Irc.Internal.Enums; | ||
|
||
internal enum Tags | ||
{ | ||
Id = 205, | ||
R9K = 278, | ||
Mod = 320, | ||
Vip = 335, | ||
Bits = 434, | ||
Slow = 453, | ||
Flags = 525, | ||
Login = 537, | ||
Color = 543, | ||
Turbo = 556, | ||
MsgId = 577, | ||
Badges = 614, | ||
Emotes = 653, | ||
RoomId = 695, | ||
UserId = 697, | ||
ThreadId = 882, | ||
FirstMsg = 924, | ||
SubsOnly = 940, | ||
UserType = 942, | ||
BadgeInfo = 972, | ||
MessageId = 991, | ||
EmoteSets = 1030, | ||
EmoteOnly = 1033, | ||
SystemMsg = 1049, | ||
Subscriber = 1076, | ||
TmiSentTs = 1093, | ||
ClientNonce = 1215, | ||
BanDuration = 1220, | ||
DisplayName = 1220, | ||
TargetMsgId = 1269, | ||
TargetUserId = 1389, | ||
FollowersOnly = 1484, | ||
MsgParamColor = 1489, | ||
MsgParamMonths = 1611, | ||
MsgParamSubPlan = 1748, | ||
ReturningChatter = 1782, | ||
ReplyParentMsgId = 1873, | ||
ReplyParentUserId = 1993, | ||
MsgParamSenderName = 2049, | ||
MsgParamGiftMonths = 2082, | ||
ReplyParentMsgBody = 2098, | ||
MsgParamViewerCount = 2125, | ||
PinnedChatPaidLevel = 2139, | ||
MsgParamRecipientId = 2159, | ||
MsgParamSenderLogin = 2169, | ||
MsgParamSenderCount = 2185, | ||
MsgParamSubPlanName = 2210, | ||
PinnedChatPaidAmount = 2263, | ||
MsgParamStreakMonths = 2306, | ||
ReplyParentUserLogin = 2325, | ||
MsgParamMassGiftCount = 2451, | ||
PinnedChatPaidCurrency = 2478, | ||
PinnedChatPaidExponent = 2484, | ||
ReplyParentDisplayName = 2516, | ||
ReplyThreadParentMsgId = 2550, | ||
MsgParamCumulativeMonths = 2743, | ||
MsgParamRecipientUserName = 2863, | ||
MsgParamShouldShareStreak = 2872, | ||
ReplyThreadParentUserLogin = 3002, | ||
MsgparamRecipientDisplayName = 3174, | ||
PinnedChatPaidIsSystemMessage = 3331, | ||
} |
Oops, something went wrong.