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
{
private static readonly object IndexLock = new object();
private static Win32[] _win32s = { };
private static UWP.Application[] _uwps = { };
private static Win32[] _win32s;
private static UWP.Application[] _uwps;
private static PluginInitContext _context;
private static ProgramIndexCache _cache;
private static BinaryStorage<ProgramIndexCache> _cacheStorage;
private static BinaryStorage<Win32[]> _win32Storage;
private static BinaryStorage<UWP.Application[]> _uwpStorage;
private static Settings _settings;
private readonly PluginJsonStorage<Settings> _settingsStorage;
@ -33,13 +33,10 @@ namespace Wox.Plugin.Program
Stopwatch.Normal("Preload programs", () =>
{
_cacheStorage = new BinaryStorage<ProgramIndexCache>();
_cache = _cacheStorage.Load();
var w = _cache.Win32s;
_win32s = w ?? new Win32[] {};
var u = _cache.UWPs;
_uwps = u ?? new UWP.Application[] { };
_win32Storage = new BinaryStorage<Win32[]>("Win32Cache");
_win32s = _win32Storage.TryLoad(new Win32[] { });
_uwpStorage = new BinaryStorage<UWP.Application[]>("UWPCache");
_uwps = _uwpStorage.TryLoad(new UWP.Application[] { });
});
Log.Info($"Preload {_win32s.Length} win32 programs from cache");
@ -53,9 +50,8 @@ namespace Wox.Plugin.Program
public void Save()
{
_settingsStorage.Save();
_cache.Win32s = _win32s;
_cache.UWPs = _uwps;
_cacheStorage.Save();
_win32Storage.Save(_win32s);
_uwpStorage.Save(_uwps);
}
public List<Result> Query(Query query)
@ -76,8 +72,8 @@ namespace Wox.Plugin.Program
public static void IndexPrograms()
{
Win32[] w = {} ;
UWP.Application[] u = {};
Win32[] w = { };
UWP.Application[] u = { };
var t1 = Task.Run(() =>
{
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\Win32.cs" />
<Compile Include="SuffixesConverter.cs" />
<Compile Include="ProgramIndexCache.cs" />
<Compile Include="Main.cs" />
<Compile Include="ProgramSetting.xaml.cs">
<DependentUpon>ProgramSetting.xaml</DependentUpon>

View file

@ -1,6 +1,8 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Media;
namespace Wox.Infrastructure.Image
{
@ -8,29 +10,35 @@ namespace Wox.Infrastructure.Image
public class ImageCache
{
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;
}
else
{
TopUsedImages[path] = 1;
Usage.AddOrUpdate(path, 1, (k, v) => v + 1);
var i = _data[path];
return i;
}
set { _data[path] = value; }
}
public void Cleanup()
{
if (TopUsedImages.Count > MaxCached)
{
var images = TopUsedImages.OrderByDescending(o => o.Value)
.Take(MaxCached)
.ToDictionary(i => i.Key, i => i.Value);
TopUsedImages = new ConcurrentDictionary<string, int>(images);
}
var images = Usage
.OrderByDescending(o => o.Value)
.Take(MaxCached)
.ToDictionary(i => i.Key, i => i.Value);
Usage = 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
{
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 =
@ -29,19 +30,17 @@ namespace Wox.Infrastructure.Image
".ico"
};
private static readonly ImageCache _cache;
private static readonly BinaryStorage<ImageCache> _storage;
static ImageLoader()
{
_storage = new BinaryStorage<ImageCache>();
_cache = _storage.Load();
Storage = new BinaryStorage<ConcurrentDictionary<string, int>> ("ImageCache");
ImageCache.Usage = Storage.TryLoad(new ConcurrentDictionary<string, int>());
}
public static void Save()
{
_cache.Cleanup();
_storage.Save();
ImageCache.Cleanup();
Storage.Save(ImageCache.Usage);
}
private static ImageSource ShellIcon(string fileName)
@ -78,7 +77,7 @@ namespace Wox.Infrastructure.Image
catch (System.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));
img.Freeze();
ImageSources[icon] = img;
ImageCache[icon] = img;
}
Task.Run(() =>
{
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);
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;
if (string.IsNullOrEmpty(path))
{
image = ImageSources[Constant.ErrorIcon];
_cache.Add(Constant.ErrorIcon);
image = ImageCache[Constant.ErrorIcon];
}
else if (ImageSources.ContainsKey(path))
else if (ImageCache.ContainsKey(path))
{
image = ImageSources[path];
_cache.Add(path);
image = ImageCache[path];
}
else
{
@ -146,7 +143,7 @@ namespace Wox.Infrastructure.Image
}
else
{
image = ImageSources[Constant.ErrorIcon];
image = ImageCache[Constant.ErrorIcon];
path = Constant.ErrorIcon;
}
}
@ -159,12 +156,11 @@ namespace Wox.Infrastructure.Image
}
else
{
image = ImageSources[Constant.ErrorIcon];
image = ImageCache[Constant.ErrorIcon];
path = Constant.ErrorIcon;
}
}
ImageSources[path] = image;
_cache.Add(path);
ImageCache[path] = image;
image.Freeze();
}
return image;

View file

@ -13,19 +13,20 @@ namespace Wox.Infrastructure.Storage
/// Normally, it has better performance, but not readable
/// You MUST mark implement class as Serializable
/// </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";
DirectoryPath = Path.Combine(DirectoryPath, DirectoryName);
FileName = filename;
FilePath = Path.Combine(DirectoryPath, FileName + FileSuffix);
ValidateDirectory();
}
public override T Load()
public T TryLoad(T defaultData)
{
if (File.Exists(FilePath))
{
@ -33,23 +34,25 @@ namespace Wox.Infrastructure.Storage
{
if (stream.Length > 0)
{
Deserialize(stream);
var d = Deserialize(stream, defaultData);
return d;
}
else
{
stream.Close();
LoadDefault();
Save(defaultData);
return defaultData;
}
}
}
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
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
@ -60,14 +63,15 @@ namespace Wox.Infrastructure.Storage
try
{
Data = (T) binaryFormatter.Deserialize(stream);
var t = (T) binaryFormatter.Deserialize(stream);
return t;
}
catch (System.Exception e)
{
Log.Error($"Broken cache file: {FilePath}");
Log.Exception(e);
stream.Close();
LoadDefault();
return defaultData;
}
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)
{
Assembly ayResult = null;
@ -97,7 +95,7 @@ namespace Wox.Infrastructure.Storage
return ayResult;
}
public override void Save()
public void Save(T data)
{
using (var stream = new FileStream(FilePath, FileMode.Create))
{
@ -108,7 +106,7 @@ namespace Wox.Infrastructure.Storage
try
{
binaryFormatter.Serialize(stream, Data);
binaryFormatter.Serialize(stream, data);
}
catch (SerializationException e)
{

View file

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