Core, RichText, Draw: Global Value Cache with dynamically adjusted size based on system statistics, MakeImage now using global value cache, RichText now stores decompressed images in the cache

git-svn-id: svn://ultimatepp.org/upp/trunk@14576 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2020-06-10 14:10:50 +00:00
parent 1718ed50be
commit 7470ee085b
8 changed files with 176 additions and 36 deletions

View file

@ -1,11 +1,15 @@
#include "Core.h"
#define LLOG(x) // LOG(x)
namespace Upp {
bool sFinished;
StaticMutex ValueCacheMutex;
std::atomic<bool> sValueCacheFinished;
struct ValueMakeCacheClass : LRUCache<Value> {
~ValueMakeCacheClass() { sFinished = true; }
~ValueMakeCacheClass() { sValueCacheFinished = true; }
};
LRUCache<Value>& TheValueCache()
@ -14,23 +18,54 @@ LRUCache<Value>& TheValueCache()
return m;
}
int sMaxSize = 1000000;
bool IsValueCacheActive()
{
return !sValueCacheFinished;
}
int ValueCacheMaxSize = 4000000;
int ValueCacheMaxSizeLimitLow = 1000000;
int ValueCacheMaxSizeLimitHigh = 0;
double ValueCacheRatio = 0.125;
void AdjustValueCache()
{
Mutex::Lock __(ValueCacheMutex);
uint64 total, available;
GetSystemMemoryStatus(total, available);
if(ValueCacheMaxSizeLimitHigh == 0)
ValueCacheMaxSizeLimitHigh = (int)clamp(total / 4, (uint64)16000000, (uint64)2000000000);
ValueCacheMaxSize = clamp((int)min((int64)(ValueCacheRatio * available), (int64)2000*1024*1024),
ValueCacheMaxSizeLimitLow, ValueCacheMaxSizeLimitHigh);
LLOG("New MakeValue max size " << ValueCacheMaxSize << " high limit " << ValueCacheMaxSizeLimitHigh);
ShrinkValueCache();
}
void ShrinkValueCache()
{
TheValueCache().Shrink(sMaxSize, 2000);
Mutex::Lock __(ValueCacheMutex);
TheValueCache().Shrink(ValueCacheMaxSize, 2000);
LLOG("MakeValue cache size after shrink: " << TheValueCache().GetSize());
}
void ShrinkValueCache(int maxsize)
void SetupValueCache(int limit_low, int limit_high, double ratio)
{
sMaxSize = maxsize;
ShrinkValueCache();
Mutex::Lock __(ValueCacheMutex);
ValueCacheMaxSizeLimitLow = 1000000;
ValueCacheMaxSizeLimitHigh = 256000000;
ValueCacheRatio = 0.125;
}
Value MakeValue(ValueMaker& m)
{
Mutex::Lock __(ValueCacheMutex);
LLOG("MakeValue cache size before make: " << TheValueCache().GetSize());
Value v = TheValueCache().Get(m);
LLOG("MakeValue cache size after make: " << TheValueCache().GetSize());
ShrinkValueCache();
LLOG("-------------");
return v;
}

View file

@ -1,20 +1,35 @@
typedef LRUCache<Value>::Maker ValueMaker;
extern StaticMutex ValueCacheMutex;
LRUCache<Value>& TheValueCache();
bool IsValueCacheActive();
Value MakeValue(ValueMaker& m);
void AdjustValueCache();
void ShrinkValueCache();
void ShrinkValueCache(int maxsize);
void SetupValueCache(int limit_low, int limit_high, double ratio);
template <class P>
int ValueCacheRemove(P what)
{
Mutex::Lock __(ValueCacheMutex);
return TheValueCache().Remove(what);
}
template <class P>
int ValueCacheRemoveOne(P what)
{
Mutex::Lock __(ValueCacheMutex);
return TheValueCache().Remove(what);
}
template <class P>
void ValueCacheAdjustSize(P getsize)
{
Mutex::Lock __(ValueCacheMutex);
TheValueCache().AdjustSize(getsize);
}

View file

@ -4,6 +4,89 @@ namespace Upp {
#define LLOG(x) // DLOG(x)
#if 1
struct scImageMaker : ValueMaker {
const ImageMaker *m;
bool paintonly;
virtual String Key() const {
StringBuffer s;
s.Cat(typeid(*m).name());
RawCat(s, paintonly);
s.Cat(m->Key());
return s;
}
virtual int Make(Value& object) const {
Image img = m->Make();
LLOG("ImageMaker " << object.GetSerialId() << ", size " << object.GetSize() << ", paintonly: " << paintonly);
if(paintonly && !IsNull(img) && img.GetRefCount() == 1)
SetPaintOnly__(img);
object = img;
return img.GetLength() + 64;
}
};
void SysImageRealized(const Image& img)
{ // Pixel data copied to host platform, no need to keep pixels data in cache if it is Fpaintonly kind
if(!IsValueCacheActive())
return;
LLOG("SysImageRealized " << img.GetSize());
if(img.data && img.data->paintonly) {
LLOG("Dropping PAINTONLY pixels of image #" << img.GetSerialId() << ", cache size: " << sImageCache().GetSize() << ", img " << img.GetLength());
DropPixels___(img.data->buffer);
ValueCacheAdjustSize([](const Value& v) -> int {
if(v.Is<Image>()) {
const Image& img = v.To<Image>();
return 64 + (~img ? img.GetLength() : 0);
}
return -1;
});
LLOG("After drop, cache size: " << TheValueCache().GetSize());
}
}
void SysImageReleased(const Image& img)
{ // CtrlCore removed handle for img, have to remove paintonly
if(!IsValueCacheActive())
return;
if(!~img) { // No data -> this is paintonly image
int64 serial_id = img.GetSerialId();
LLOG("SysImageReleased " << img.GetSerialId() << ", cache size: " << sImageCache().GetSize() << ", count " << sImageCache().GetCount());
int n = ValueCacheRemoveOne([&](const Value& v) -> bool {
return v.Is<Image>() && v.To<Image>().GetSerialId() == serial_id;
});
IGNORE_RESULT(n); // suppress warning about unused 'n' without LLOGs
LLOG("SysImageReleased count: " << n);
LLOG("SysImageReleased done cache size: " << sImageCache().GetSize() << ", count " << sImageCache().GetCount());
}
}
void SetMakeImageCacheMax(int m)
{
SetupValueCache(m, 0, 0.125);
}
void SetMakeImageCacheSize(int m)
{
SetMakeImageCacheMax(m);
}
void SweepMkImageCache()
{
AdjustValueCache();
}
Image MakeImage__(const ImageMaker& m, bool paintonly)
{
scImageMaker cm;
cm.m = &m;
cm.paintonly = paintonly;
return MakeValue(cm);
}
#else
static StaticCriticalSection sMakeImage;
// SystemDraw image cache can get destructed later than maker cache invoking SysImageReleased
@ -132,6 +215,7 @@ Image MakeImage__(const ImageMaker& m, bool paintonly)
sMaxSize = q;
return result;
}
#endif
Image MakeImage(const ImageMaker& m)
{

View file

@ -71,10 +71,6 @@ on the cache. Size of cache is increased according to cache size
counter data collected since the last SweepMkImageCache.&]
[s3; &]
[s4; &]
[s5;:ClearMakeImageCache`(`): [@(0.0.255) void]_[* ClearMakeImageCache]()&]
[s2;%% Removes all images from the cache.&]
[s3; &]
[s4; &]
[s5;:SetMakeImageCacheSize`(int`): [@(0.0.255) void]_[* SetMakeImageCacheSize]([@(0.0.255) i
nt]_[*@3 m])&]
[s2;%% Sets the amount of images that can be kept in cache. This

View file

@ -107,12 +107,12 @@ void RichObjectType::Paint(const Value& data, Draw& w, Size sz, void *context) c
void RichObjectType::Paint(const Value& data, Draw& w, Size sz) const {}
Image RichObjectType::ToImage(const Value& data, Size sz) const
Image RichObjectType::ToImage(int64 serial_id, const Value& data, Size sz) const
{
return ToImage(data, sz, NULL);
return ToImage(serial_id, data, sz, NULL);
}
Image RichObjectType::ToImage(const Value& data, Size sz, void *context) const
Image RichObjectType::ToImage(int64, const Value& data, Size sz, void *context) const
{
ImageAnyDraw iw(sz);
iw.DrawRect(sz, SColorPaper());
@ -178,7 +178,7 @@ void RichObject::Paint(Draw& w, Size sz, void *context) const
Image RichObject::ToImage(Size sz, void *context) const
{
if(type)
return type->ToImage(data, sz, context);
return type->ToImage(serial, data, sz, context);
else {
ImageAnyDraw w(sz);
Paint(w, sz, context);
@ -272,7 +272,7 @@ String RichObject::GetTypeName() const
void RichObject::Clear()
{
NewSerial();
serial = 0;
keepratio = true;
type = NULL;
data = Value();

View file

@ -138,11 +138,9 @@ struct RichObjectImageMaker : ImageMaker {
String RichObjectImageMaker::Key() const
{
StringBuffer b;
int64 id = object.GetSerialId();
b.Cat((const char *)&id, sizeof(id));
b.Cat((const char *)&sz.cx, sizeof(sz.cx));
b.Cat((const char *)&sz.cy, sizeof(sz.cy));
b.Cat((const char *)&context, sizeof(context));
RawCat(b, object.GetSerialId());
RawCat(b, sz);
RawCat(b, context);
return b;
}

View file

@ -10,7 +10,7 @@ struct RichImage : public RichObjectType {
virtual Size GetPhysicalSize(const Value& data) const;
virtual Size GetPixelSize(const Value& data) const;
virtual void Paint(const Value& data, Draw& w, Size sz, void *) const;
virtual Image ToImage(const Value& data, Size sz, void *) const;
virtual Image ToImage(int64, const Value& data, Size sz, void *) const;
virtual bool Accept(PasteClip& clip);
virtual Value Read(PasteClip& clip);
@ -88,7 +88,7 @@ void RichImage::Paint(const Value& data, Draw& w, Size sz, void *) const
w.DrawImage(0, 0, sz.cx, sz.cy, x);
}
Image RichImage::ToImage(const Value& data, Size sz, void *) const
Image RichImage::ToImage(int64, const Value& data, Size sz, void *) const
{
return Rescale(LoadImageFromString(data), sz);
}
@ -112,7 +112,7 @@ struct RichPNG : public RichObjectType {
virtual Size GetPhysicalSize(const Value& data) const;
virtual Size GetPixelSize(const Value& data) const;
virtual void Paint(const Value& data, Draw& w, Size sz) const;
virtual Image ToImage(const Value& data, Size sz, void *) const;
virtual Image ToImage(int64, const Value& data, Size sz, void *) const;
};
String RichPNG::GetTypeName(const Value& v) const
@ -162,7 +162,7 @@ void RichPNG::Paint(const Value& data, Draw& w, Size sz) const
w.DrawImage(0, 0, outsz.cx, outsz.cy, x);
}
Image RichPNG::ToImage(const Value& data, Size sz, void *) const
Image RichPNG::ToImage(int64, const Value& data, Size sz, void *) const
{
if(IsString(data)) {
ImageAnyDraw iw(sz);
@ -185,7 +185,7 @@ struct RichRawImage : public RichObjectType {
virtual Size GetPhysicalSize(const Value& data) const;
virtual Size GetPixelSize(const Value& data) const;
virtual void Paint(const Value& data, Draw& w, Size sz, void *) const;
virtual Image ToImage(const Value& data, Size sz, void *) const;
virtual Image ToImage(int64, const Value& data, Size sz, void *) const;
};
String RichRawImage::GetTypeName(const Value& v) const
@ -254,14 +254,26 @@ void RichRawImage::Paint(const Value& data, Draw& w, Size sz, void *) const
w.DrawImage(0, 0, RenderSVGImage(sz, ~data));
}
Image RichRawImage::ToImage(const Value& data, Size sz, void *) const
Image RichRawImage::ToImage(int64 serial_id, const Value& data, Size sz, void *) const
{
String s = data;
StringStream ss(s);
One<StreamRaster> r = StreamRaster::OpenAny(ss);
if(r) {
Image x = r->GetImage();
return Rescale(x, sz);
struct ImgFormatLoader : ImageMaker {
int64 serial_id;
String s;
virtual String Key() const { String x; RawCat(x, serial_id); return x; }
virtual Image Make() const {
StringStream ss(s);
One<StreamRaster> r = StreamRaster::OpenAny(ss);
return r ? r->GetImage() : Image();
}
} loader;
loader.serial_id = serial_id;
loader.s = s;
return Rescale(MakeImage(loader), sz);
}
else
if(IsString(data) && IsSVG(~data))
@ -285,7 +297,7 @@ struct RichImlImage : public RichObjectType {
virtual Size GetPhysicalSize(const Value& data) const;
virtual Size GetPixelSize(const Value& data) const;
virtual void Paint(const Value& data, Draw& w, Size sz) const;
virtual Image ToImage(const Value& data, Size sz, void *) const;
virtual Image ToImage(int64, const Value& data, Size sz, void *) const;
virtual bool IsText() const;
Image Get(const Value& v) const;
@ -321,7 +333,7 @@ void RichImlImage::Paint(const Value& data, Draw& w, Size sz) const
w.DrawImage(0, 0, sz.cx, sz.cy, Get(data));
}
Image RichImlImage::ToImage(const Value& data, Size sz, void *) const
Image RichImlImage::ToImage(int64, const Value& data, Size sz, void *) const
{
return Rescale(Get(data), sz);
}

View file

@ -149,7 +149,7 @@ struct RichObjectType {
virtual Size GetPhysicalSize(const Value& data, void *context) const;
virtual Size GetPixelSize(const Value& data, void *context) const;
virtual void Paint(const Value& data, Draw& w, Size sz, void *context) const;
virtual Image ToImage(const Value& data, Size sz, void *context) const;
virtual Image ToImage(int64 serial_id, const Value& data, Size sz, void *context) const;
virtual void Menu(Bar& bar, RichObject& ex, void *context) const;
virtual void DefaultAction(RichObject& ex, void *context) const;
virtual String GetLink(const Value& data, Point pt, Size sz, void *context) const;
@ -164,7 +164,7 @@ protected:
virtual Size GetPhysicalSize(const Value& data) const;
virtual Size GetPixelSize(const Value& data) const;
virtual void Paint(const Value& data, Draw& w, Size sz) const;
virtual Image ToImage(const Value& data, Size sz) const;
virtual Image ToImage(int64 serial_id, const Value& data, Size sz) const;
virtual void Menu(Bar& bar, RichObject& ex) const;
virtual void DefaultAction(RichObject& ex) const;
virtual String GetLink(const Value& data, Point pt, Size sz) const;
@ -193,8 +193,8 @@ public:
static RichObjectType& GetType(int i) { return *Map()[i]; }
static String GetTypeName(int i) { return Map().GetKey(i); }
void SetSize(int cx, int cy) { size = Size(cx, cy); NewSerial(); }
void SetSize(Size sz) { size = sz; NewSerial(); }
void SetSize(int cx, int cy) { size = Size(cx, cy); }
void SetSize(Size sz) { SetSize(sz.cx, sz.cy); }
Size GetSize() const { return size; }
void Paint(Draw& w, Size sz, void *context = NULL) const;
Image ToImage(Size sz, void *context = NULL) const;