From 064d04fccc81b1a1ec6223b9f85f57f7755e4df0 Mon Sep 17 00:00:00 2001 From: leo Date: Thu, 6 Jun 2024 20:25:16 +0800 Subject: [PATCH] enhance: improve QueryCommits performance --- src/Commands/QueryCommits.cs | 43 +++++++++++++++++++++++++-------- src/Models/CommitGraph.cs | 18 +++++++++++--- src/ViewModels/Histories.cs | 31 +++--------------------- src/ViewModels/Repository.cs | 3 +++ src/Views/Histories.axaml | 2 +- src/Views/Histories.axaml.cs | 17 +++---------- src/Views/TextDiffView.axaml.cs | 22 +++++++++++------ 7 files changed, 72 insertions(+), 64 deletions(-) diff --git a/src/Commands/QueryCommits.cs b/src/Commands/QueryCommits.cs index 8308f577..295bb950 100644 --- a/src/Commands/QueryCommits.cs +++ b/src/Commands/QueryCommits.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Text; namespace SourceGit.Commands { @@ -31,15 +32,14 @@ namespace SourceGit.Commands { case 0: _current = new Models.Commit() { SHA = line }; + _isSubjectSet = false; _commits.Add(_current); break; case 1: - if (!string.IsNullOrEmpty(line)) - _current.Parents.AddRange(line.Split(' ', StringSplitOptions.RemoveEmptyEntries)); + ParseParent(line); break; case 2: - if (!string.IsNullOrEmpty(line)) - ParseDecorators(line); + ParseDecorators(line); break; case 3: _current.Author = Models.User.FindOrAdd(line); @@ -57,15 +57,17 @@ namespace SourceGit.Commands if (line.Equals(_endOfBodyToken, StringComparison.Ordinal)) { _nextPartIdx = 0; - if (!string.IsNullOrEmpty(_current.Message)) - _current.Message = _current.Message.Trim(); + _current.Message = _messageReader.ToString().Trim(); + _messageReader.Clear(); + } + else if (!_isSubjectSet) + { + _isSubjectSet = true; + _current.Subject = line; } else { - if (string.IsNullOrEmpty(_current.Subject)) - _current.Subject = line; - else - _current.Message += (line + "\n"); + _messageReader.AppendLine(line); } return; } @@ -73,8 +75,27 @@ namespace SourceGit.Commands _nextPartIdx++; } + private void ParseParent(string data) + { + if (data.Length < 8) + return; + + var idx = data.IndexOf(' ', StringComparison.Ordinal); + if (idx == -1) + { + _current.Parents.Add(data); + return; + } + + _current.Parents.Add(data.Substring(0, idx)); + _current.Parents.Add(data.Substring(idx + 1)); + } + private void ParseDecorators(string data) { + if (data.Length < 3) + return; + var subs = data.Split(',', StringSplitOptions.RemoveEmptyEntries); foreach (var sub in subs) { @@ -172,5 +193,7 @@ namespace SourceGit.Commands private bool _isHeadFounded = false; private readonly bool _findFirstMerged = true; private int _nextPartIdx = 0; + private bool _isSubjectSet = false; + private StringBuilder _messageReader = new StringBuilder(); } } diff --git a/src/Models/CommitGraph.cs b/src/Models/CommitGraph.cs index 201a1e69..6b26eba5 100644 --- a/src/Models/CommitGraph.cs +++ b/src/Models/CommitGraph.cs @@ -2,11 +2,23 @@ using System.Collections.Generic; using Avalonia; +using Avalonia.Media; namespace SourceGit.Models { public class CommitGraph { + public static readonly Pen[] Pens = [ + new Pen(Brushes.Orange, 2), + new Pen(Brushes.ForestGreen, 2), + new Pen(Brushes.Gold, 2), + new Pen(Brushes.Magenta, 2), + new Pen(Brushes.Red, 2), + new Pen(Brushes.Gray, 2), + new Pen(Brushes.Turquoise, 2), + new Pen(Brushes.Olive, 2), + ]; + public class Path { public List Points = new List(); @@ -101,12 +113,12 @@ namespace SourceGit.Models public List Links { get; set; } = new List(); public List Dots { get; set; } = new List(); - public static CommitGraph Parse(List commits, double rowHeight, int colorCount) + public static CommitGraph Parse(List commits, int colorCount) { double UNIT_WIDTH = 12; double HALF_WIDTH = 6; - double UNIT_HEIGHT = rowHeight; - double HALF_HEIGHT = rowHeight / 2; + double UNIT_HEIGHT = 28; + double HALF_HEIGHT = 14; var temp = new CommitGraph(); var unsolved = new List(); diff --git a/src/ViewModels/Histories.cs b/src/ViewModels/Histories.cs index bba8f901..73007e02 100644 --- a/src/ViewModels/Histories.cs +++ b/src/ViewModels/Histories.cs @@ -1,11 +1,9 @@ using System; using System.Collections; using System.Collections.Generic; -using System.Threading.Tasks; using Avalonia.Controls; using Avalonia.Platform.Storage; -using Avalonia.Threading; using CommunityToolkit.Mvvm.ComponentModel; @@ -24,38 +22,16 @@ namespace SourceGit.ViewModels set => SetProperty(ref _isLoading, value); } - public double DataGridRowHeight - { - get => _dataGridRowHeight; - } - public List Commits { get => _commits; set { - var oldAutoSelectedCommitSHA = AutoSelectedCommit?.SHA; + var lastSelected = AutoSelectedCommit; if (SetProperty(ref _commits, value)) { - Models.Commit newSelectedCommit = null; - if (value.Count > 0 && oldAutoSelectedCommitSHA != null) - { - newSelectedCommit = value.Find(x => x.SHA == oldAutoSelectedCommitSHA); - } - if (newSelectedCommit != AutoSelectedCommit) - { - AutoSelectedCommit = newSelectedCommit; - } - - Graph = null; - Task.Run(() => - { - var graph = Models.CommitGraph.Parse(value, DataGridRowHeight, 8); - Dispatcher.UIThread.Invoke(() => - { - Graph = graph; - }); - }); + if (value.Count > 0 && lastSelected != null) + AutoSelectedCommit = value.Find(x => x.SHA == lastSelected.SHA); } } } @@ -652,7 +628,6 @@ namespace SourceGit.ViewModels } private Repository _repo = null; - private readonly double _dataGridRowHeight = 28; private bool _isLoading = true; private List _commits = new List(); private Models.CommitGraph _graph = null; diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index 65ee45f2..898d40c5 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -606,12 +606,15 @@ namespace SourceGit.ViewModels } var commits = new Commands.QueryCommits(FullPath, limits).Result(); + var graph = Models.CommitGraph.Parse(commits, 8); + Dispatcher.UIThread.Invoke(() => { if (_histories != null) { _histories.IsLoading = false; _histories.Commits = commits; + _histories.Graph = graph; } }); } diff --git a/src/Views/Histories.axaml b/src/Views/Histories.axaml index 650d52e2..e5d064c2 100644 --- a/src/Views/Histories.axaml +++ b/src/Views/Histories.axaml @@ -23,7 +23,7 @@ IsReadOnly="True" HeadersVisibility="None" Focusable="False" - RowHeight="{Binding DataGridRowHeight}" + RowHeight="28" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto" LayoutUpdated="OnCommitDataGridLayoutUpdated" diff --git a/src/Views/Histories.axaml.cs b/src/Views/Histories.axaml.cs index 508645d4..37ad441d 100644 --- a/src/Views/Histories.axaml.cs +++ b/src/Views/Histories.axaml.cs @@ -69,17 +69,6 @@ namespace SourceGit.Views public class CommitGraph : Control { - public static readonly Pen[] Pens = [ - new Pen(Brushes.Orange, 2), - new Pen(Brushes.ForestGreen, 2), - new Pen(Brushes.Gold, 2), - new Pen(Brushes.Magenta, 2), - new Pen(Brushes.Red, 2), - new Pen(Brushes.Gray, 2), - new Pen(Brushes.Turquoise, 2), - new Pen(Brushes.Olive, 2), - ]; - public static readonly StyledProperty GraphProperty = AvaloniaProperty.Register(nameof(Graph)); @@ -151,7 +140,7 @@ namespace SourceGit.Views if (dot.Center.Y > bottom) break; - context.DrawEllipse(dotFill, Pens[dot.Color], dot.Center, 3, 3); + context.DrawEllipse(dotFill, Models.CommitGraph.Pens[dot.Color], dot.Center, 3, 3); } } @@ -168,7 +157,7 @@ namespace SourceGit.Views continue; var geo = new StreamGeometry(); - var pen = Pens[line.Color]; + var pen = Models.CommitGraph.Pens[line.Color]; using (var ctx = geo.Open()) { var started = false; @@ -238,7 +227,7 @@ namespace SourceGit.Views ctx.QuadraticBezierTo(link.Control, link.End); } - context.DrawGeometry(null, Pens[link.Color], geo); + context.DrawGeometry(null, Models.CommitGraph.Pens[link.Color], geo); } } } diff --git a/src/Views/TextDiffView.axaml.cs b/src/Views/TextDiffView.axaml.cs index 0edfd47f..50576cc4 100644 --- a/src/Views/TextDiffView.axaml.cs +++ b/src/Views/TextDiffView.axaml.cs @@ -1166,25 +1166,31 @@ namespace SourceGit.Views { base.OnPropertyChanged(change); + var data = TextDiff; + if (data == null) + { + Content = null; + SyncScrollOffset = Vector.Zero; + return; + } + if (change.Property == TextDiffProperty) { - if (TextDiff == null) - Content = null; - else if (UseSideBySideDiff) + if (UseSideBySideDiff) Content = new ViewModels.TwoSideTextDiff(TextDiff); else Content = TextDiff; + + SetCurrentValue(SyncScrollOffsetProperty, TextDiff.SyncScrollOffset); } else if (change.Property == UseSideBySideDiffProperty) { - SyncScrollOffset = Vector.Zero; - - if (TextDiff == null) - Content = null; - else if (UseSideBySideDiff) + if (UseSideBySideDiff) Content = new ViewModels.TwoSideTextDiff(TextDiff); else Content = TextDiff; + + SetCurrentValue(SyncScrollOffsetProperty, Vector.Zero); } }