Skip to content
This repository was archived by the owner on Jun 21, 2023. It is now read-only.

Commit 943836e

Browse files
committed
Lazy load the services needed by UsageTracker.
To improve the startup time of the extension.
1 parent 1c561dd commit 943836e

File tree

4 files changed

+76
-28
lines changed

4 files changed

+76
-28
lines changed

src/GitHub.VisualStudio/GitHub.VisualStudio.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,7 @@
298298
<Compile Include="Properties\AssemblyInfo.cs" />
299299
<Compile Include="Helpers\Browser.cs" />
300300
<Compile Include="Services\UsageTracker.cs" />
301+
<Compile Include="Services\UsageTrackerDispatcher.cs" />
301302
<Compile Include="Settings\Constants.cs" />
302303
<Compile Include="Services\ConnectionManager.cs" />
303304
<Compile Include="Services\Program.cs" />

src/GitHub.VisualStudio/GitHubPackage.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,9 @@ protected override async Task InitializeAsync(CancellationToken cancellationToke
5252
await base.InitializeAsync(cancellationToken, progress);
5353
await EnsurePackageLoaded(new Guid(ServiceProviderPackage.ServiceProviderPackageId));
5454

55-
//var usageTracker = await GetServiceAsync(typeof(IUsageTracker)) as IUsageTracker;
56-
//usageTracker.IncrementLaunchCount();
55+
// Activate the usage tracker by forcing an instance to be created.
56+
await GetServiceAsync(typeof(IUsageTracker));
57+
5758
InitializeMenus().Forget();
5859
}
5960

@@ -178,6 +179,11 @@ async Task<object> CreateService(IAsyncServiceContainer container, CancellationT
178179
var sp = await GetServiceAsync(typeof(IUIProvider)) as IUIProvider;
179180
return new MenuProvider(sp);
180181
}
182+
else if (serviceType == typeof(IUsageTracker))
183+
{
184+
var uiProvider = await GetServiceAsync(typeof(IUIProvider)) as IUIProvider;
185+
return new UsageTracker(uiProvider);
186+
}
181187
// go the mef route
182188
else
183189
{

src/GitHub.VisualStudio/Services/UsageTracker.cs

Lines changed: 38 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -14,34 +14,30 @@
1414

1515
namespace GitHub.Services
1616
{
17-
[Export(typeof(IUsageTracker))]
18-
[PartCreationPolicy(CreationPolicy.Shared)]
1917
public class UsageTracker : IUsageTracker
2018
{
2119
const string StoreFileName = "ghfvs.usage";
2220
static readonly Calendar cal = CultureInfo.InvariantCulture.Calendar;
2321

22+
readonly IUIProvider uiProvider;
23+
readonly DispatcherTimer timer;
24+
2425
IMetricsService client;
25-
readonly IConnectionManager connectionManager;
26+
IConnectionManager connectionManager;
2627
IPackageSettings userSettings;
27-
readonly IVSServices vsservices;
28-
readonly DispatcherTimer timer;
29-
readonly string storePath;
30-
readonly IServiceProvider serviceProvider;
28+
IVSServices vsservices;
29+
string storePath;
30+
bool firstRun = true;
3131

3232
Func<string, bool> fileExists;
3333
Func<string, Encoding, string> readAllText;
3434
Action<string, string, Encoding> writeAllText;
3535
Action<string> dirCreate;
3636

3737
[ImportingConstructor]
38-
public UsageTracker(
39-
IProgram program,
40-
IConnectionManager connectionManager,
41-
IVSServices vsservices,
42-
[Import(typeof(SVsServiceProvider))] IServiceProvider serviceProvider)
38+
public UsageTracker(IUIProvider uiProvider)
4339
{
44-
this.serviceProvider = serviceProvider;
40+
this.uiProvider = uiProvider;
4541

4642
fileExists = (path) => System.IO.File.Exists(path);
4743
readAllText = (path, encoding) =>
@@ -65,17 +61,11 @@ public UsageTracker(
6561
};
6662
dirCreate = (path) => System.IO.Directory.CreateDirectory(path);
6763

68-
this.connectionManager = connectionManager;
69-
this.vsservices = vsservices;
7064
this.timer = new DispatcherTimer(
71-
TimeSpan.FromMinutes(1),
65+
TimeSpan.FromMinutes(3),
7266
DispatcherPriority.Background,
7367
TimerTick,
7468
Dispatcher.CurrentDispatcher);
75-
this.storePath = System.IO.Path.Combine(
76-
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
77-
program.ApplicationName,
78-
StoreFileName);
7969

8070
RunTimer();
8171
}
@@ -145,8 +135,29 @@ public void IncrementLoginCount()
145135
SaveUsage(usage);
146136
}
147137

138+
void Initialize()
139+
{
140+
// The services needed by the usage tracker are loaded when they are first needed to
141+
// improve the startup time of the extension.
142+
if (userSettings == null)
143+
{
144+
client = uiProvider.GetService<IMetricsService>();
145+
connectionManager = uiProvider.GetService<IConnectionManager>();
146+
userSettings = uiProvider.GetService<IPackageSettings>();
147+
vsservices = uiProvider.GetService<IVSServices>();
148+
149+
var program = uiProvider.GetService<IProgram>();
150+
storePath = System.IO.Path.Combine(
151+
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
152+
program.ApplicationName,
153+
StoreFileName);
154+
}
155+
}
156+
148157
UsageStore LoadUsage()
149158
{
159+
Initialize();
160+
150161
var json = fileExists(storePath) ? readAllText(storePath, Encoding.UTF8) : null;
151162
UsageStore result = null;
152163
try
@@ -178,7 +189,6 @@ void RunTimer()
178189
{
179190
// The timer first ticks after 3 minutes to allow things to settle down after startup.
180191
// This will be changed to 8 hours after the first tick by the TimerTick method.
181-
timer.Interval = TimeSpan.FromMinutes(3);
182192
timer.Start();
183193
}
184194

@@ -194,21 +204,23 @@ void TimerTick(object sender, EventArgs e)
194204

195205
async Task TimerTick()
196206
{
197-
Debug.Assert(client != null, "TimerTick should not be triggered when there is no IMetricsService");
207+
Initialize();
198208

199-
// Subsequent timer ticks should occur every 8 hours.
200-
timer.Interval = TimeSpan.FromHours(8);
209+
if (firstRun)
210+
{
211+
IncrementLaunchCount();
212+
timer.Interval = TimeSpan.FromHours(8);
213+
firstRun = false;
214+
}
201215

202216
if (userSettings == null)
203217
{
204218
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
205-
client = serviceProvider.GetExportedValue<IMetricsService>();
206219
if (client == null)
207220
{
208221
timer.Stop();
209222
return;
210223
}
211-
userSettings = serviceProvider.GetExportedValue<IPackageSettings>();
212224
}
213225

214226
if (!userSettings.CollectMetrics)
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using Microsoft.VisualStudio.Shell;
2+
using System;
3+
using System.ComponentModel.Composition;
4+
5+
namespace GitHub.Services
6+
{
7+
[Export(typeof(IUsageTracker))]
8+
[PartCreationPolicy(CreationPolicy.NonShared)]
9+
public class UsageTrackerDispatcher : IUsageTracker
10+
{
11+
readonly IUsageTracker inner;
12+
13+
[ImportingConstructor]
14+
public UsageTrackerDispatcher([Import(typeof(SVsServiceProvider))] IServiceProvider serviceProvider)
15+
{
16+
inner = serviceProvider.GetService(typeof(IUsageTracker)) as IUsageTracker;
17+
}
18+
19+
public void IncrementCloneCount() => inner.IncrementCloneCount();
20+
public void IncrementCreateCount() => inner.IncrementCreateCount();
21+
public void IncrementCreateGistCount() => inner.IncrementCreateGistCount();
22+
public void IncrementLaunchCount() => inner.IncrementLaunchCount();
23+
public void IncrementLinkToGitHubCount() => inner.IncrementLinkToGitHubCount();
24+
public void IncrementLoginCount() => inner.IncrementLoginCount();
25+
public void IncrementOpenInGitHubCount() => inner.IncrementOpenInGitHubCount();
26+
public void IncrementPublishCount() => inner.IncrementPublishCount();
27+
public void IncrementUpstreamPullRequestCount() => inner.IncrementUpstreamPullRequestCount();
28+
}
29+
}

0 commit comments

Comments
 (0)