Skip to content

Commit 97688ef

Browse files
committed
improve plugin loading performance
1 parent f1a27f8 commit 97688ef

File tree

4 files changed

+59
-47
lines changed

4 files changed

+59
-47
lines changed

Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using System.Linq;
99
using System.Windows.Forms;
1010
using Flow.Launcher.Core.Resource;
11+
using System.Threading.Tasks;
1112

1213
namespace Flow.Launcher.Core.ExternalPlugins.Environments
1314
{
@@ -37,10 +38,10 @@ internal AbstractPluginEnvironment(List<PluginMetadata> pluginMetadataList, Plug
3738
PluginSettings = pluginSettings;
3839
}
3940

40-
internal IEnumerable<PluginPair> Setup()
41+
internal IEnumerable<Task> Setup()
4142
{
4243
if (!PluginMetadataList.Any(o => o.Language.Equals(Language, StringComparison.OrdinalIgnoreCase)))
43-
return new List<PluginPair>();
44+
return new List<Task>();
4445

4546
if (!string.IsNullOrEmpty(PluginsSettingsFilePath) && FilesFolders.FileExists(PluginsSettingsFilePath))
4647
{
@@ -87,7 +88,7 @@ internal IEnumerable<PluginPair> Setup()
8788
$"Not able to successfully set {EnvName} path, setting's plugin executable path variable is still an empty string.",
8889
$"{Language}Environment");
8990

90-
return new List<PluginPair>();
91+
return new List<Task>();
9192
}
9293
}
9394

@@ -106,17 +107,17 @@ private void EnsureLatestInstalled(string expectedPath, string currentPath, stri
106107

107108
internal abstract PluginPair CreatePluginPair(string filePath, PluginMetadata metadata);
108109

109-
private IEnumerable<PluginPair> SetPathForPluginPairs(string filePath, string languageToSet)
110+
private IEnumerable<Task> SetPathForPluginPairs(string filePath, string languageToSet)
110111
{
111-
var pluginPairs = new List<PluginPair>();
112+
var tasks = new List<Task>();
112113

113114
foreach (var metadata in PluginMetadataList)
114115
{
115116
if (metadata.Language.Equals(languageToSet, StringComparison.OrdinalIgnoreCase))
116-
pluginPairs.Add(CreatePluginPair(filePath, metadata));
117+
tasks.Add(Task.Run(() => CreatePluginPair(filePath, metadata)));
117118
}
118119

119-
return pluginPairs;
120+
return tasks;
120121
}
121122

122123
private string GetFileFromDialog(string title, string filter = "")

Flow.Launcher.Core/Plugin/PluginManager.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,12 +146,12 @@ static PluginManager()
146146
/// todo happlebao The API should be removed
147147
/// </summary>
148148
/// <param name="settings"></param>
149-
public static void LoadPlugins(PluginsSettings settings)
149+
public static async Task LoadPluginsAsync(PluginsSettings settings)
150150
{
151151
_metadatas = PluginConfig.Parse(Directories);
152152
Settings = settings;
153153
Settings.UpdatePluginSettings(_metadatas);
154-
AllPlugins = PluginsLoader.Plugins(_metadatas, Settings);
154+
AllPlugins = await PluginsLoader.PluginsAsync(_metadatas, Settings);
155155
}
156156

157157
/// <summary>

Flow.Launcher.Core/Plugin/PluginsLoader.cs

Lines changed: 48 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Concurrent;
23
using System.Collections.Generic;
34
using System.Linq;
45
using System.Reflection;
@@ -16,7 +17,11 @@ namespace Flow.Launcher.Core.Plugin
1617
{
1718
public static class PluginsLoader
1819
{
19-
public static List<PluginPair> Plugins(List<PluginMetadata> metadatas, PluginsSettings settings)
20+
private static readonly ConcurrentQueue<PluginPair> Plugins = new();
21+
22+
private static readonly ConcurrentQueue<string> ErroredPlugins = new();
23+
24+
public static async Task<List<PluginPair>> PluginsAsync(List<PluginMetadata> metadatas, PluginsSettings settings)
2025
{
2126
var dotnetPlugins = DotNetPlugins(metadatas);
2227

@@ -46,17 +51,34 @@ public static List<PluginPair> Plugins(List<PluginMetadata> metadatas, PluginsSe
4651
.Concat(executablePlugins)
4752
.Concat(executableV2Plugins)
4853
.ToList();
49-
return plugins;
54+
55+
await Task.WhenAll(plugins);
56+
57+
if (!ErroredPlugins.IsEmpty)
58+
{
59+
var errorPluginString = String.Join(Environment.NewLine, ErroredPlugins);
60+
61+
var errorMessage = "The following "
62+
+ (ErroredPlugins.Count > 1 ? "plugins have " : "plugin has ")
63+
+ "errored and cannot be loaded:";
64+
65+
_ = Task.Run(() =>
66+
{
67+
MessageBox.Show($"{errorMessage}{Environment.NewLine}{Environment.NewLine}" +
68+
$"{errorPluginString}{Environment.NewLine}{Environment.NewLine}" +
69+
$"Please refer to the logs for more information", "",
70+
MessageBoxButtons.OK, MessageBoxIcon.Warning);
71+
});
72+
}
73+
74+
return Plugins.ToList();
5075
}
5176

52-
public static IEnumerable<PluginPair> DotNetPlugins(List<PluginMetadata> source)
77+
public static IEnumerable<Task> DotNetPlugins(List<PluginMetadata> source)
5378
{
54-
var erroredPlugins = new List<string>();
55-
56-
var plugins = new List<PluginPair>();
5779
var metadatas = source.Where(o => AllowedLanguage.IsDotNet(o.Language));
5880

59-
foreach (var metadata in metadatas)
81+
return metadatas.Select(metadata => Task.Run(() =>
6082
{
6183
var milliseconds = Stopwatch.Debug(
6284
$"|PluginsLoader.DotNetPlugins|Constructor init cost for {metadata.Name}", () =>
@@ -100,53 +122,42 @@ public static IEnumerable<PluginPair> DotNetPlugins(List<PluginMetadata> source)
100122

101123
if (plugin == null)
102124
{
103-
erroredPlugins.Add(metadata.Name);
125+
ErroredPlugins.Enqueue(metadata.Name);
104126
return;
105127
}
106128

107-
plugins.Add(new PluginPair { Plugin = plugin, Metadata = metadata });
129+
Plugins.Enqueue(new PluginPair { Plugin = plugin, Metadata = metadata });
108130
});
109131
metadata.InitTime += milliseconds;
110-
}
111-
112-
if (erroredPlugins.Count > 0)
113-
{
114-
var errorPluginString = String.Join(Environment.NewLine, erroredPlugins);
115-
116-
var errorMessage = "The following "
117-
+ (erroredPlugins.Count > 1 ? "plugins have " : "plugin has ")
118-
+ "errored and cannot be loaded:";
119-
120-
_ = Task.Run(() =>
121-
{
122-
MessageBox.Show($"{errorMessage}{Environment.NewLine}{Environment.NewLine}" +
123-
$"{errorPluginString}{Environment.NewLine}{Environment.NewLine}" +
124-
$"Please refer to the logs for more information", "",
125-
MessageBoxButtons.OK, MessageBoxIcon.Warning);
126-
});
127-
}
128-
129-
return plugins;
132+
}));
130133
}
131134

132-
public static IEnumerable<PluginPair> ExecutablePlugins(IEnumerable<PluginMetadata> source)
135+
public static IEnumerable<Task> ExecutablePlugins(IEnumerable<PluginMetadata> source)
133136
{
134137
return source
135138
.Where(o => o.Language.Equals(AllowedLanguage.Executable, StringComparison.OrdinalIgnoreCase))
136-
.Select(metadata => new PluginPair
139+
.Select(metadata => Task.Run(() =>
137140
{
138-
Plugin = new ExecutablePlugin(metadata.ExecuteFilePath), Metadata = metadata
139-
});
141+
return new PluginPair
142+
{
143+
Plugin = new ExecutablePlugin(metadata.ExecuteFilePath),
144+
Metadata = metadata
145+
};
146+
}));
140147
}
141148

142-
public static IEnumerable<PluginPair> ExecutableV2Plugins(IEnumerable<PluginMetadata> source)
149+
public static IEnumerable<Task> ExecutableV2Plugins(IEnumerable<PluginMetadata> source)
143150
{
144151
return source
145152
.Where(o => o.Language.Equals(AllowedLanguage.ExecutableV2, StringComparison.OrdinalIgnoreCase))
146-
.Select(metadata => new PluginPair
153+
.Select(metadata => Task.Run(() =>
147154
{
148-
Plugin = new ExecutablePluginV2(metadata.ExecuteFilePath), Metadata = metadata
149-
});
155+
return new PluginPair
156+
{
157+
Plugin = new ExecutablePluginV2(metadata.ExecuteFilePath),
158+
Metadata = metadata
159+
};
160+
}));
150161
}
151162
}
152163
}

Flow.Launcher/App.xaml.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ await Stopwatch.NormalAsync("|App.OnStartup|Startup cost", async () =>
7474
InternationalizationManager.Instance.Settings = _settings;
7575
InternationalizationManager.Instance.ChangeLanguage(_settings.Language);
7676

77-
PluginManager.LoadPlugins(_settings.PluginSettings);
77+
await PluginManager.LoadPluginsAsync(_settings.PluginSettings);
7878
_mainVM = new MainViewModel(_settings);
7979

8080
API = new PublicAPIInstance(_settingsVM, _mainVM, _alphabet);

0 commit comments

Comments
 (0)