Preload top used images.

This commit is contained in:
qianlifeng
2014-12-18 19:22:47 +08:00
parent d370f7e721
commit 57bc1f2032
8 changed files with 115 additions and 14 deletions

View File

@@ -10,6 +10,7 @@ namespace Wox.Infrastructure.Storage
/// <summary> /// <summary>
/// Stroage object using binary data /// Stroage object using binary data
/// Normally, it has better performance, but not readable /// Normally, it has better performance, but not readable
/// You MUST mark implement class as Serializable
/// </summary> /// </summary>
[Serializable] [Serializable]
public abstract class BinaryStorage<T> : BaseStorage<T> where T : class, IStorage, new() public abstract class BinaryStorage<T> : BaseStorage<T> where T : class, IStorage, new()

View File

@@ -29,5 +29,6 @@ namespace Wox.Plugin.SystemPlugins.CMD
} }
Save(); Save();
} }
} }
} }

View File

@@ -18,7 +18,7 @@ namespace Wox.Converters
return null; return null;
} }
return ImageLoader.Load(value.ToString()); return ImageLoader.ImageLoader.Load(value.ToString());
} }
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)

View File

@@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Wox.Infrastructure.Storage;
namespace Wox.ImageLoader
{
[Serializable]
public class ImageCacheStroage : BinaryStorage<ImageCacheStroage>
{
public int counter = 0;
public const int maxCached = 200;
public Dictionary<string, int> TopUsedImages = new Dictionary<string, int>();
protected override string ConfigName
{
get { return "ImageCache"; }
}
public void Add(string path)
{
if (TopUsedImages.ContainsKey(path))
{
TopUsedImages[path] = TopUsedImages[path] + 1 ;
}
else
{
TopUsedImages.Add(path, 1);
}
if (TopUsedImages.Count > maxCached)
{
TopUsedImages = TopUsedImages.OrderByDescending(o => o.Value)
.Take(maxCached)
.ToDictionary(i => i.Key, i => i.Value);
}
if (++counter == 30)
{
counter = 0;
Save();
}
}
public void Remove(string path)
{
if (TopUsedImages.ContainsKey(path))
{
TopUsedImages.Remove(path);
}
}
}
}

View File

@@ -1,17 +1,14 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing; using System.Drawing;
using System.Globalization;
using System.IO; using System.IO;
using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text;
using System.Windows; using System.Windows;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using Wox.Infrastructure;
namespace Wox.Helper namespace Wox.ImageLoader
{ {
public class ImageLoader public class ImageLoader
{ {
@@ -53,9 +50,42 @@ namespace Wox.Helper
return null; return null;
} }
public static ImageSource Load(string path) public static void PreloadImages()
{
//ImageCacheStroage.Instance.TopUsedImages can be changed during foreach, so we need to make a copy
var imageList = new Dictionary<string, int>(ImageCacheStroage.Instance.TopUsedImages);
using (new Timeit(string.Format("Preload {0} images",imageList.Count)))
{
foreach (var image in imageList)
{
ImageSource img = Load(image.Key, false);
if (img != null)
{
img.Freeze(); //to make it copy to UI thread
if (!imageCache.ContainsKey(image.Key))
{
lock (locker)
{
if (!imageCache.ContainsKey(image.Key))
{
KeyValuePair<string, int> copyedImg = image;
App.Window.Dispatcher.Invoke(new Action(() => imageCache.Add(copyedImg.Key, img)));
}
}
}
}
}
}
}
public static ImageSource Load(string path,bool addToCache = true)
{ {
if (string.IsNullOrEmpty(path)) return null; if (string.IsNullOrEmpty(path)) return null;
if (addToCache)
{
ImageCacheStroage.Instance.Add(path);
}
if (imageCache.ContainsKey(path)) if (imageCache.ContainsKey(path))
{ {
return imageCache[path]; return imageCache[path];
@@ -78,7 +108,7 @@ namespace Wox.Helper
} }
if (img != null) if (img != null && addToCache)
{ {
if (!imageCache.ContainsKey(path)) if (!imageCache.ContainsKey(path))
{ {

View File

@@ -16,6 +16,7 @@ using NHotkey;
using NHotkey.Wpf; using NHotkey.Wpf;
using Wox.Commands; using Wox.Commands;
using Wox.Helper; using Wox.Helper;
using Wox.ImageLoader;
using Wox.Infrastructure; using Wox.Infrastructure;
using Wox.Infrastructure.Storage; using Wox.Infrastructure.Storage;
using Wox.Infrastructure.Storage.UserSettings; using Wox.Infrastructure.Storage.UserSettings;
@@ -188,9 +189,22 @@ namespace Wox
Closing += MainWindow_Closing; Closing += MainWindow_Closing;
//since MainWIndow implement IPublicAPI, so we need to finish ctor MainWindow object before //since MainWIndow implement IPublicAPI, so we need to finish ctor MainWindow object before
//PublicAPI invoke in plugin init methods. E.g FolderPlugin //PublicAPI invoke in plugin init methods. E.g FolderPlugin
ThreadPool.QueueUserWorkItem(o => Plugins.Init()); ThreadPool.QueueUserWorkItem(o =>
{
Thread.Sleep(50);
Plugins.Init();
});
ThreadPool.QueueUserWorkItem(o =>
{
Thread.Sleep(50);
PreLoadImages();
});
ThreadPool.QueueUserWorkItem(o => CheckUpdate());
}
ThreadPool.QueueUserWorkItem(o => checkUpdate()); private void PreLoadImages()
{
ImageLoader.ImageLoader.PreloadImages();
} }
void pnlResult_RightMouseClickEvent(Result result) void pnlResult_RightMouseClickEvent(Result result)
@@ -198,7 +212,7 @@ namespace Wox
ShowContextMenu(result); ShowContextMenu(result);
} }
void checkUpdate() void CheckUpdate()
{ {
Release release = new UpdateChecker().CheckUpgrade(); Release release = new UpdateChecker().CheckUpgrade();
if (release != null && !UserSettingStorage.Instance.DontPromptUpdateMsg) if (release != null && !UserSettingStorage.Instance.DontPromptUpdateMsg)

View File

@@ -482,7 +482,7 @@ namespace Wox
pluginAuthor.Text = "By: " + pair.Metadata.Author; pluginAuthor.Text = "By: " + pair.Metadata.Author;
pluginSubTitle.Text = pair.Metadata.Description; pluginSubTitle.Text = pair.Metadata.Description;
pluginId = pair.Metadata.ID; pluginId = pair.Metadata.ID;
pluginIcon.Source = ImageLoader.Load(pair.Metadata.FullIcoPath); pluginIcon.Source = ImageLoader.ImageLoader.Load(pair.Metadata.FullIcoPath);
} }
else else
{ {
@@ -499,7 +499,7 @@ namespace Wox
tbOpenPluginDirecoty.Visibility = Visibility.Collapsed; tbOpenPluginDirecoty.Visibility = Visibility.Collapsed;
pluginActionKeywordTitle.Visibility = Visibility.Collapsed; pluginActionKeywordTitle.Visibility = Visibility.Collapsed;
pluginTitle.Cursor = Cursors.Arrow; pluginTitle.Cursor = Cursors.Arrow;
pluginIcon.Source = ImageLoader.Load(sys.FullIcoPath); pluginIcon.Source = ImageLoader.ImageLoader.Load(sys.FullIcoPath);
} }
} }

View File

@@ -104,6 +104,7 @@
<Reference Include="WPFToolkit, Version=3.5.40128.1, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" /> <Reference Include="WPFToolkit, Version=3.5.40128.1, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="ImageLoader\ImageCacheStroage.cs" />
<Compile Include="Update\NewVersionWindow.xaml.cs"> <Compile Include="Update\NewVersionWindow.xaml.cs">
<DependentUpon>NewVersionWindow.xaml</DependentUpon> <DependentUpon>NewVersionWindow.xaml</DependentUpon>
</Compile> </Compile>
@@ -136,7 +137,7 @@
</Compile> </Compile>
<Compile Include="Helper\FontHelper.cs" /> <Compile Include="Helper\FontHelper.cs" />
<Compile Include="Helper\HttpProxy.cs" /> <Compile Include="Helper\HttpProxy.cs" />
<Compile Include="Helper\ImageLoader.cs" /> <Compile Include="ImageLoader\ImageLoader.cs" />
<Compile Include="Helper\SingleInstance.cs" /> <Compile Include="Helper\SingleInstance.cs" />
<Compile Include="Helper\SyntaxSugars.cs" /> <Compile Include="Helper\SyntaxSugars.cs" />
<Compile Include="Helper\WallpaperPathRetrieval.cs" /> <Compile Include="Helper\WallpaperPathRetrieval.cs" />