mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-07-11 22:03:01 -06:00
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:
parent
1718ed50be
commit
7470ee085b
8 changed files with 176 additions and 36 deletions
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue