Use cache type directly instead of a new class, decouple binarystorage and storage

This commit is contained in:
bao-qian
2017-01-13 15:40:32 +00:00
parent a5aa305773
commit 4c6c310e0a
7 changed files with 70 additions and 86 deletions

View File

@@ -16,13 +16,13 @@ namespace Wox.Plugin.Program
public class Main : ISettingProvider, IPlugin, IPluginI18n, IContextMenu, ISavable public class Main : ISettingProvider, IPlugin, IPluginI18n, IContextMenu, ISavable
{ {
private static readonly object IndexLock = new object(); private static readonly object IndexLock = new object();
private static Win32[] _win32s = { }; private static Win32[] _win32s;
private static UWP.Application[] _uwps = { }; private static UWP.Application[] _uwps;
private static PluginInitContext _context; private static PluginInitContext _context;
private static ProgramIndexCache _cache; private static BinaryStorage<Win32[]> _win32Storage;
private static BinaryStorage<ProgramIndexCache> _cacheStorage; private static BinaryStorage<UWP.Application[]> _uwpStorage;
private static Settings _settings; private static Settings _settings;
private readonly PluginJsonStorage<Settings> _settingsStorage; private readonly PluginJsonStorage<Settings> _settingsStorage;
@@ -33,13 +33,10 @@ namespace Wox.Plugin.Program
Stopwatch.Normal("Preload programs", () => Stopwatch.Normal("Preload programs", () =>
{ {
_cacheStorage = new BinaryStorage<ProgramIndexCache>(); _win32Storage = new BinaryStorage<Win32[]>("Win32Cache");
_cache = _cacheStorage.Load(); _win32s = _win32Storage.TryLoad(new Win32[] { });
_uwpStorage = new BinaryStorage<UWP.Application[]>("UWPCache");
var w = _cache.Win32s; _uwps = _uwpStorage.TryLoad(new UWP.Application[] { });
_win32s = w ?? new Win32[] {};
var u = _cache.UWPs;
_uwps = u ?? new UWP.Application[] { };
}); });
Log.Info($"Preload {_win32s.Length} win32 programs from cache"); Log.Info($"Preload {_win32s.Length} win32 programs from cache");
@@ -53,9 +50,8 @@ namespace Wox.Plugin.Program
public void Save() public void Save()
{ {
_settingsStorage.Save(); _settingsStorage.Save();
_cache.Win32s = _win32s; _win32Storage.Save(_win32s);
_cache.UWPs = _uwps; _uwpStorage.Save(_uwps);
_cacheStorage.Save();
} }
public List<Result> Query(Query query) public List<Result> Query(Query query)
@@ -76,8 +72,8 @@ namespace Wox.Plugin.Program
public static void IndexPrograms() public static void IndexPrograms()
{ {
Win32[] w = {} ; Win32[] w = { };
UWP.Application[] u = {}; UWP.Application[] u = { };
var t1 = Task.Run(() => var t1 = Task.Run(() =>
{ {
w = Win32.All(_settings); w = Win32.All(_settings);

View File

@@ -1,13 +0,0 @@
using System;
using System.Collections.Generic;
using Wox.Plugin.Program.Programs;
namespace Wox.Plugin.Program
{
[Serializable]
public class ProgramIndexCache
{
public Win32[] Win32s = { };
public UWP.Application[] UWPs = { };
}
}

View File

@@ -76,7 +76,6 @@
<Compile Include="Programs\UWP.cs" /> <Compile Include="Programs\UWP.cs" />
<Compile Include="Programs\Win32.cs" /> <Compile Include="Programs\Win32.cs" />
<Compile Include="SuffixesConverter.cs" /> <Compile Include="SuffixesConverter.cs" />
<Compile Include="ProgramIndexCache.cs" />
<Compile Include="Main.cs" /> <Compile Include="Main.cs" />
<Compile Include="ProgramSetting.xaml.cs"> <Compile Include="ProgramSetting.xaml.cs">
<DependentUpon>ProgramSetting.xaml</DependentUpon> <DependentUpon>ProgramSetting.xaml</DependentUpon>

View File

@@ -1,6 +1,8 @@
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Windows.Media;
namespace Wox.Infrastructure.Image namespace Wox.Infrastructure.Image
{ {
@@ -8,29 +10,35 @@ namespace Wox.Infrastructure.Image
public class ImageCache public class ImageCache
{ {
private const int MaxCached = 200; private const int MaxCached = 200;
public ConcurrentDictionary<string, int> TopUsedImages = new ConcurrentDictionary<string, int>(); public ConcurrentDictionary<string, int> Usage = new ConcurrentDictionary<string, int>();
private readonly ConcurrentDictionary<string, ImageSource> _data = new ConcurrentDictionary<string, ImageSource>();
public void Add(string path)
public ImageSource this[string path]
{ {
if (TopUsedImages.ContainsKey(path)) get
{ {
TopUsedImages[path] = TopUsedImages[path] + 1; Usage.AddOrUpdate(path, 1, (k, v) => v + 1);
} var i = _data[path];
else return i;
{
TopUsedImages[path] = 1;
} }
set { _data[path] = value; }
} }
public void Cleanup() public void Cleanup()
{ {
if (TopUsedImages.Count > MaxCached) var images = Usage
{ .OrderByDescending(o => o.Value)
var images = TopUsedImages.OrderByDescending(o => o.Value) .Take(MaxCached)
.Take(MaxCached) .ToDictionary(i => i.Key, i => i.Value);
.ToDictionary(i => i.Key, i => i.Value); Usage = new ConcurrentDictionary<string, int>(images);
TopUsedImages = new ConcurrentDictionary<string, int>(images); }
}
public bool ContainsKey(string key)
{
var contains = _data.ContainsKey(key);
return contains;
} }
} }
} }

View File

@@ -15,7 +15,8 @@ namespace Wox.Infrastructure.Image
{ {
public static class ImageLoader public static class ImageLoader
{ {
private static readonly ConcurrentDictionary<string, ImageSource> ImageSources = new ConcurrentDictionary<string, ImageSource>(); private static readonly ImageCache ImageCache = new ImageCache();
private static readonly BinaryStorage<ConcurrentDictionary<string, int>> Storage;
private static readonly string[] ImageExtions = private static readonly string[] ImageExtions =
@@ -29,19 +30,17 @@ namespace Wox.Infrastructure.Image
".ico" ".ico"
}; };
private static readonly ImageCache _cache;
private static readonly BinaryStorage<ImageCache> _storage;
static ImageLoader() static ImageLoader()
{ {
_storage = new BinaryStorage<ImageCache>(); Storage = new BinaryStorage<ConcurrentDictionary<string, int>> ("ImageCache");
_cache = _storage.Load(); ImageCache.Usage = Storage.TryLoad(new ConcurrentDictionary<string, int>());
} }
public static void Save() public static void Save()
{ {
_cache.Cleanup(); ImageCache.Cleanup();
_storage.Save(); Storage.Save(ImageCache.Usage);
} }
private static ImageSource ShellIcon(string fileName) private static ImageSource ShellIcon(string fileName)
@@ -78,7 +77,7 @@ namespace Wox.Infrastructure.Image
catch (System.Exception e) catch (System.Exception e)
{ {
Log.Exception(e); Log.Exception(e);
return ImageSources[Constant.ErrorIcon]; return ImageCache[Constant.ErrorIcon];
} }
} }
@@ -88,22 +87,22 @@ namespace Wox.Infrastructure.Image
{ {
ImageSource img = new BitmapImage(new Uri(icon)); ImageSource img = new BitmapImage(new Uri(icon));
img.Freeze(); img.Freeze();
ImageSources[icon] = img; ImageCache[icon] = img;
} }
Task.Run(() => Task.Run(() =>
{ {
Stopwatch.Normal("Preload images from cache", () => Stopwatch.Normal("Preload images from cache", () =>
{ {
_cache.TopUsedImages.AsParallel().Where(i => !ImageSources.ContainsKey(i.Key)).ForAll(i => ImageCache.Usage.AsParallel().Where(i => !ImageCache.ContainsKey(i.Key)).ForAll(i =>
{ {
var img = Load(i.Key); var img = Load(i.Key);
if (img != null) if (img != null)
{ {
ImageSources[i.Key] = img; ImageCache[i.Key] = img;
} }
}); });
}); });
Log.Info($"Preload {_cache.TopUsedImages.Count} images from cache"); Log.Info($"Preload {ImageCache.Usage.Count} images from cache");
}); });
} }
@@ -112,13 +111,11 @@ namespace Wox.Infrastructure.Image
ImageSource image; ImageSource image;
if (string.IsNullOrEmpty(path)) if (string.IsNullOrEmpty(path))
{ {
image = ImageSources[Constant.ErrorIcon]; image = ImageCache[Constant.ErrorIcon];
_cache.Add(Constant.ErrorIcon);
} }
else if (ImageSources.ContainsKey(path)) else if (ImageCache.ContainsKey(path))
{ {
image = ImageSources[path]; image = ImageCache[path];
_cache.Add(path);
} }
else else
{ {
@@ -146,7 +143,7 @@ namespace Wox.Infrastructure.Image
} }
else else
{ {
image = ImageSources[Constant.ErrorIcon]; image = ImageCache[Constant.ErrorIcon];
path = Constant.ErrorIcon; path = Constant.ErrorIcon;
} }
} }
@@ -159,12 +156,11 @@ namespace Wox.Infrastructure.Image
} }
else else
{ {
image = ImageSources[Constant.ErrorIcon]; image = ImageCache[Constant.ErrorIcon];
path = Constant.ErrorIcon; path = Constant.ErrorIcon;
} }
} }
ImageSources[path] = image; ImageCache[path] = image;
_cache.Add(path);
image.Freeze(); image.Freeze();
} }
return image; return image;

View File

@@ -13,19 +13,20 @@ namespace Wox.Infrastructure.Storage
/// Normally, it has better performance, but not readable /// Normally, it has better performance, but not readable
/// You MUST mark implement class as Serializable /// You MUST mark implement class as Serializable
/// </summary> /// </summary>
public class BinaryStorage<T> : Storage<T> where T : new() public class BinaryStorage<T> : Storage<T>
{ {
public BinaryStorage() public BinaryStorage(string filename)
{ {
FileSuffix = ".dat"; FileSuffix = ".cache";
DirectoryName = "Cache"; DirectoryName = "Cache";
DirectoryPath = Path.Combine(DirectoryPath, DirectoryName); DirectoryPath = Path.Combine(DirectoryPath, DirectoryName);
FileName = filename;
FilePath = Path.Combine(DirectoryPath, FileName + FileSuffix); FilePath = Path.Combine(DirectoryPath, FileName + FileSuffix);
ValidateDirectory(); ValidateDirectory();
} }
public override T Load() public T TryLoad(T defaultData)
{ {
if (File.Exists(FilePath)) if (File.Exists(FilePath))
{ {
@@ -33,23 +34,25 @@ namespace Wox.Infrastructure.Storage
{ {
if (stream.Length > 0) if (stream.Length > 0)
{ {
Deserialize(stream); var d = Deserialize(stream, defaultData);
return d;
} }
else else
{ {
stream.Close(); stream.Close();
LoadDefault(); Save(defaultData);
return defaultData;
} }
} }
} }
else else
{ {
LoadDefault(); Save(defaultData);
return defaultData;
} }
return Data;
} }
private void Deserialize(FileStream stream) private T Deserialize(FileStream stream, T defaultData)
{ {
//http://stackoverflow.com/questions/2120055/binaryformatter-deserialize-gives-serializationexception //http://stackoverflow.com/questions/2120055/binaryformatter-deserialize-gives-serializationexception
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
@@ -60,14 +63,15 @@ namespace Wox.Infrastructure.Storage
try try
{ {
Data = (T) binaryFormatter.Deserialize(stream); var t = (T) binaryFormatter.Deserialize(stream);
return t;
} }
catch (System.Exception e) catch (System.Exception e)
{ {
Log.Error($"Broken cache file: {FilePath}"); Log.Error($"Broken cache file: {FilePath}");
Log.Exception(e); Log.Exception(e);
stream.Close(); stream.Close();
LoadDefault(); return defaultData;
} }
finally finally
{ {
@@ -75,12 +79,6 @@ namespace Wox.Infrastructure.Storage
} }
} }
public override void LoadDefault()
{
Data = new T();
Save();
}
private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{ {
Assembly ayResult = null; Assembly ayResult = null;
@@ -97,7 +95,7 @@ namespace Wox.Infrastructure.Storage
return ayResult; return ayResult;
} }
public override void Save() public void Save(T data)
{ {
using (var stream = new FileStream(FilePath, FileMode.Create)) using (var stream = new FileStream(FilePath, FileMode.Create))
{ {
@@ -108,7 +106,7 @@ namespace Wox.Infrastructure.Storage
try try
{ {
binaryFormatter.Serialize(stream, Data); binaryFormatter.Serialize(stream, data);
} }
catch (SerializationException e) catch (SerializationException e)
{ {

View File

@@ -7,7 +7,7 @@ namespace Wox.Infrastructure.Storage
{ {
protected T Data; protected T Data;
protected Type DataType { get; } protected Type DataType { get; }
public string FileName { get; } public string FileName { get; set; }
public string FilePath { get; set; } public string FilePath { get; set; }
public string FileSuffix { get; set; } public string FileSuffix { get; set; }
public string DirectoryPath { get; set; } public string DirectoryPath { get; set; }