enhance: improve QueryCommits performance

This commit is contained in:
leo 2024-06-06 20:25:16 +08:00
parent 1a18235a76
commit 064d04fccc
No known key found for this signature in database
GPG key ID: B528468E49CD0E58
7 changed files with 72 additions and 64 deletions

View file

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text;
namespace SourceGit.Commands namespace SourceGit.Commands
{ {
@ -31,14 +32,13 @@ namespace SourceGit.Commands
{ {
case 0: case 0:
_current = new Models.Commit() { SHA = line }; _current = new Models.Commit() { SHA = line };
_isSubjectSet = false;
_commits.Add(_current); _commits.Add(_current);
break; break;
case 1: case 1:
if (!string.IsNullOrEmpty(line)) ParseParent(line);
_current.Parents.AddRange(line.Split(' ', StringSplitOptions.RemoveEmptyEntries));
break; break;
case 2: case 2:
if (!string.IsNullOrEmpty(line))
ParseDecorators(line); ParseDecorators(line);
break; break;
case 3: case 3:
@ -57,15 +57,17 @@ namespace SourceGit.Commands
if (line.Equals(_endOfBodyToken, StringComparison.Ordinal)) if (line.Equals(_endOfBodyToken, StringComparison.Ordinal))
{ {
_nextPartIdx = 0; _nextPartIdx = 0;
if (!string.IsNullOrEmpty(_current.Message)) _current.Message = _messageReader.ToString().Trim();
_current.Message = _current.Message.Trim(); _messageReader.Clear();
}
else if (!_isSubjectSet)
{
_isSubjectSet = true;
_current.Subject = line;
} }
else else
{ {
if (string.IsNullOrEmpty(_current.Subject)) _messageReader.AppendLine(line);
_current.Subject = line;
else
_current.Message += (line + "\n");
} }
return; return;
} }
@ -73,8 +75,27 @@ namespace SourceGit.Commands
_nextPartIdx++; _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) private void ParseDecorators(string data)
{ {
if (data.Length < 3)
return;
var subs = data.Split(',', StringSplitOptions.RemoveEmptyEntries); var subs = data.Split(',', StringSplitOptions.RemoveEmptyEntries);
foreach (var sub in subs) foreach (var sub in subs)
{ {
@ -172,5 +193,7 @@ namespace SourceGit.Commands
private bool _isHeadFounded = false; private bool _isHeadFounded = false;
private readonly bool _findFirstMerged = true; private readonly bool _findFirstMerged = true;
private int _nextPartIdx = 0; private int _nextPartIdx = 0;
private bool _isSubjectSet = false;
private StringBuilder _messageReader = new StringBuilder();
} }
} }

View file

@ -2,11 +2,23 @@
using System.Collections.Generic; using System.Collections.Generic;
using Avalonia; using Avalonia;
using Avalonia.Media;
namespace SourceGit.Models namespace SourceGit.Models
{ {
public class CommitGraph 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 class Path
{ {
public List<Point> Points = new List<Point>(); public List<Point> Points = new List<Point>();
@ -101,12 +113,12 @@ namespace SourceGit.Models
public List<Link> Links { get; set; } = new List<Link>(); public List<Link> Links { get; set; } = new List<Link>();
public List<Dot> Dots { get; set; } = new List<Dot>(); public List<Dot> Dots { get; set; } = new List<Dot>();
public static CommitGraph Parse(List<Commit> commits, double rowHeight, int colorCount) public static CommitGraph Parse(List<Commit> commits, int colorCount)
{ {
double UNIT_WIDTH = 12; double UNIT_WIDTH = 12;
double HALF_WIDTH = 6; double HALF_WIDTH = 6;
double UNIT_HEIGHT = rowHeight; double UNIT_HEIGHT = 28;
double HALF_HEIGHT = rowHeight / 2; double HALF_HEIGHT = 14;
var temp = new CommitGraph(); var temp = new CommitGraph();
var unsolved = new List<PathHelper>(); var unsolved = new List<PathHelper>();

View file

@ -1,11 +1,9 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Platform.Storage; using Avalonia.Platform.Storage;
using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
@ -24,38 +22,16 @@ namespace SourceGit.ViewModels
set => SetProperty(ref _isLoading, value); set => SetProperty(ref _isLoading, value);
} }
public double DataGridRowHeight
{
get => _dataGridRowHeight;
}
public List<Models.Commit> Commits public List<Models.Commit> Commits
{ {
get => _commits; get => _commits;
set set
{ {
var oldAutoSelectedCommitSHA = AutoSelectedCommit?.SHA; var lastSelected = AutoSelectedCommit;
if (SetProperty(ref _commits, value)) if (SetProperty(ref _commits, value))
{ {
Models.Commit newSelectedCommit = null; if (value.Count > 0 && lastSelected != null)
if (value.Count > 0 && oldAutoSelectedCommitSHA != null) AutoSelectedCommit = value.Find(x => x.SHA == lastSelected.SHA);
{
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;
});
});
} }
} }
} }
@ -652,7 +628,6 @@ namespace SourceGit.ViewModels
} }
private Repository _repo = null; private Repository _repo = null;
private readonly double _dataGridRowHeight = 28;
private bool _isLoading = true; private bool _isLoading = true;
private List<Models.Commit> _commits = new List<Models.Commit>(); private List<Models.Commit> _commits = new List<Models.Commit>();
private Models.CommitGraph _graph = null; private Models.CommitGraph _graph = null;

View file

@ -606,12 +606,15 @@ namespace SourceGit.ViewModels
} }
var commits = new Commands.QueryCommits(FullPath, limits).Result(); var commits = new Commands.QueryCommits(FullPath, limits).Result();
var graph = Models.CommitGraph.Parse(commits, 8);
Dispatcher.UIThread.Invoke(() => Dispatcher.UIThread.Invoke(() =>
{ {
if (_histories != null) if (_histories != null)
{ {
_histories.IsLoading = false; _histories.IsLoading = false;
_histories.Commits = commits; _histories.Commits = commits;
_histories.Graph = graph;
} }
}); });
} }

View file

@ -23,7 +23,7 @@
IsReadOnly="True" IsReadOnly="True"
HeadersVisibility="None" HeadersVisibility="None"
Focusable="False" Focusable="False"
RowHeight="{Binding DataGridRowHeight}" RowHeight="28"
HorizontalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"
LayoutUpdated="OnCommitDataGridLayoutUpdated" LayoutUpdated="OnCommitDataGridLayoutUpdated"

View file

@ -69,17 +69,6 @@ namespace SourceGit.Views
public class CommitGraph : Control 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<Models.CommitGraph> GraphProperty = public static readonly StyledProperty<Models.CommitGraph> GraphProperty =
AvaloniaProperty.Register<CommitGraph, Models.CommitGraph>(nameof(Graph)); AvaloniaProperty.Register<CommitGraph, Models.CommitGraph>(nameof(Graph));
@ -151,7 +140,7 @@ namespace SourceGit.Views
if (dot.Center.Y > bottom) if (dot.Center.Y > bottom)
break; 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; continue;
var geo = new StreamGeometry(); var geo = new StreamGeometry();
var pen = Pens[line.Color]; var pen = Models.CommitGraph.Pens[line.Color];
using (var ctx = geo.Open()) using (var ctx = geo.Open())
{ {
var started = false; var started = false;
@ -238,7 +227,7 @@ namespace SourceGit.Views
ctx.QuadraticBezierTo(link.Control, link.End); ctx.QuadraticBezierTo(link.Control, link.End);
} }
context.DrawGeometry(null, Pens[link.Color], geo); context.DrawGeometry(null, Models.CommitGraph.Pens[link.Color], geo);
} }
} }
} }

View file

@ -1166,25 +1166,31 @@ namespace SourceGit.Views
{ {
base.OnPropertyChanged(change); base.OnPropertyChanged(change);
var data = TextDiff;
if (data == null)
{
Content = null;
SyncScrollOffset = Vector.Zero;
return;
}
if (change.Property == TextDiffProperty) if (change.Property == TextDiffProperty)
{ {
if (TextDiff == null) if (UseSideBySideDiff)
Content = null;
else if (UseSideBySideDiff)
Content = new ViewModels.TwoSideTextDiff(TextDiff); Content = new ViewModels.TwoSideTextDiff(TextDiff);
else else
Content = TextDiff; Content = TextDiff;
SetCurrentValue(SyncScrollOffsetProperty, TextDiff.SyncScrollOffset);
} }
else if (change.Property == UseSideBySideDiffProperty) else if (change.Property == UseSideBySideDiffProperty)
{ {
SyncScrollOffset = Vector.Zero; if (UseSideBySideDiff)
if (TextDiff == null)
Content = null;
else if (UseSideBySideDiff)
Content = new ViewModels.TwoSideTextDiff(TextDiff); Content = new ViewModels.TwoSideTextDiff(TextDiff);
else else
Content = TextDiff; Content = TextDiff;
SetCurrentValue(SyncScrollOffsetProperty, Vector.Zero);
} }
} }