diff options
| author | Michael Peter Christen <mc@yacy.net> | 2026-07-09 22:17:32 +0200 |
|---|---|---|
| committer | Michael Peter Christen <mc@yacy.net> | 2026-07-09 22:17:32 +0200 |
| commit | 30f66631bcb91989f4291070dc68db8226365f17 (patch) | |
| tree | fa18f991e20cd21054e637fae60607d1f605f779 /source | |
| parent | 55956c502b00274edc99888c42a21e2985928fff (diff) | |
enhanced Network Graph Caching
Diffstat (limited to 'source')
| -rw-r--r-- | source/net/yacy/htroot/NetworkPicture.java | 94 | ||||
| -rw-r--r-- | source/net/yacy/peers/graphics/NetworkGraph.java | 86 | ||||
| -rw-r--r-- | source/net/yacy/search/Switchboard.java | 3 |
3 files changed, 103 insertions, 80 deletions
diff --git a/source/net/yacy/htroot/NetworkPicture.java b/source/net/yacy/htroot/NetworkPicture.java index 0ebfb7f91..ea89744f7 100644 --- a/source/net/yacy/htroot/NetworkPicture.java +++ b/source/net/yacy/htroot/NetworkPicture.java @@ -37,13 +37,17 @@ import net.yacy.search.SwitchboardConstants; import net.yacy.server.serverObjects;
import net.yacy.server.serverSwitch;
+
/** draw a picture of the yacy network */
public class NetworkPicture {
- private static final ConcurrentLog log = new ConcurrentLog("NetworkPicture");
- private static final Semaphore sync = new Semaphore(1, true);
- private static long lastAccessSeconds = 0;
+ private static final ConcurrentLog log = new ConcurrentLog("NetworkPicture"); + private static final Semaphore sync = new Semaphore(1, true); + private static final int NETWORK_PICTURE_CACHE_MAX_SIZE = 20;
+ private static final long NETWORK_PICTURE_CACHE_MAX_AGE_MILLIS = 10000;
+ public static final NetworkGraph.Cache cache = new NetworkGraph.Cache(NETWORK_PICTURE_CACHE_MAX_AGE_MILLIS, NETWORK_PICTURE_CACHE_MAX_SIZE);
+
public static EncodedImage respond( final RequestHeader header, final serverObjects post, @@ -51,35 +55,8 @@ public class NetworkPicture { final Switchboard sb = (Switchboard) env; final boolean authorized = sb.adminAuthenticated(header) >= 2; - final long timeSeconds = System.currentTimeMillis() / 1000; - if (NetworkGraph.buffer != null && timeSeconds - lastAccessSeconds < 2) { - if (log.isFine()) log.fine("cache hit (1); authorized = " - + authorized - + ", timeSeconds - lastAccessSeconds = " - + (timeSeconds - lastAccessSeconds)); - return NetworkGraph.buffer; - } - - boolean lockAcquired = sync.tryAcquire(); - if (!lockAcquired) { - if (NetworkGraph.buffer != null) { - return NetworkGraph.buffer; - } - sync.acquireUninterruptibly(); - lockAcquired = true; - } - try { - final long refreshCheckSeconds = System.currentTimeMillis() / 1000; - if (NetworkGraph.buffer != null && refreshCheckSeconds - lastAccessSeconds < 2) { - if (log.isFine()) log.fine("cache hit (2); authorized = " - + authorized - + ", timeSeconds - lastAccessSeconds = " - + (refreshCheckSeconds - lastAccessSeconds)); - return NetworkGraph.buffer; - } - - int width = 1280; // 640x480 = VGA, 768x576 = SD/4:3, 1024x576 =SD/16:9 1280x720 = HD/16:9, 1920x1080 = FULL HD/16:9 - int height = 720;
+ int width = 1280; // 640x480 = VGA, 768x576 = SD/4:3, 1024x576 =SD/16:9 1280x720 = HD/16:9, 1920x1080 = FULL HD/16:9 + int height = 720; int passiveLimit = 1440; // minutes; 1440 = 1 day; 720 = 12 hours; 1440 = 24 hours, 10080 = 1 week;
int potentialLimit = 1440;
int maxCount = 9000;
@@ -111,11 +88,34 @@ public class NetworkPicture { if ( potentialLimit > 1000000 ) {
potentialLimit = 1000000;
}
- if ( maxCount > 10000 ) {
- maxCount = 10000;
- }
-
- NetworkGraph.buffer = + if ( maxCount > 10000 ) { + maxCount = 10000; + } + + EncodedImage cachedPicture = cache.getFresh(width, height, coronaangle); + if (cachedPicture != null) { + if (log.isFine()) log.fine("cache hit (1); authorized = " + authorized + ", width = " + width + ", height = " + height); + return cachedPicture; + } + + boolean lockAcquired = sync.tryAcquire(); + if (!lockAcquired) { + /* A stale picture is preferable to waiting, but only for a matching variant. */ + cachedPicture = cache.getCached(width, height, coronaangle); + if (cachedPicture != null) { + return cachedPicture; + } + sync.acquireUninterruptibly(); + lockAcquired = true; + } + try { + cachedPicture = cache.getFresh(width, height, coronaangle); + if (cachedPicture != null) { + if (log.isFine()) log.fine("cache hit (2); authorized = " + authorized + ", width = " + width + ", height = " + height); + return cachedPicture; + } + + final EncodedImage networkPicture = new EncodedImage(NetworkGraph.getNetworkPicture( sb.peers, width, @@ -130,24 +130,8 @@ public class NetworkPicture { Long.parseLong(bgcolor, 16), cyc), "png", false); - /*
- NetworkGraph.buffer =
- new EncodedImage(NetworkSkylineGraph.getNetworkSkylinePicture(
- sb.peers,
- width,
- height,
- passiveLimit,
- potentialLimit,
- maxCount,
- coronaangle,
- communicationTimeout,
- env.getConfig(SwitchboardConstants.NETWORK_NAME, "unspecified"),
- env.getConfig("network.unit.description", "unspecified"),
- Long.parseLong(bgcolor, 16),
- cyc), "png", false);
- */
- lastAccessSeconds = System.currentTimeMillis() / 1000; - return NetworkGraph.buffer; + cache.put(width, height, coronaangle, networkPicture); + return networkPicture; } finally { if (lockAcquired) { sync.release(); diff --git a/source/net/yacy/peers/graphics/NetworkGraph.java b/source/net/yacy/peers/graphics/NetworkGraph.java index cd501dccd..1b14b0379 100644 --- a/source/net/yacy/peers/graphics/NetworkGraph.java +++ b/source/net/yacy/peers/graphics/NetworkGraph.java @@ -30,9 +30,12 @@ import java.awt.Color; import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
-import java.util.Date;
-import java.util.Iterator;
+import java.util.AbstractMap;
+import java.util.Date; +import java.util.Iterator; import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
import net.yacy.cora.document.encoding.ASCII;
import net.yacy.cora.document.encoding.UTF8;
@@ -50,12 +53,11 @@ import net.yacy.search.query.SearchEventCache; import net.yacy.visualization.PrintTool;
import net.yacy.visualization.RasterPlotter;
-public class NetworkGraph {
+public class NetworkGraph { - private final static double DOUBLE_LONG_MAX_VALUE = Long.MAX_VALUE;
- public static EncodedImage buffer = null;
-
+ private static final double DOUBLE_LONG_MAX_VALUE = Long.MAX_VALUE;
+
private static int shortestName = 10;
private static int longestName = 30;
@@ -81,13 +83,62 @@ public class NetworkGraph { private static final long COL_NORMAL_TEXT = 0x000000;
private static final long COL_LOAD_BG = 0xF7F7F7;
- /** Private constructor to avoid instantiation of utility class. */
- private NetworkGraph() { }
- public static void clearcache() {
- buffer = null;
+ public static class Cache {
+
+ private final Map<String, Map.Entry<Long, EncodedImage>> cache;
+ private final long maxAge;
+ private final int maxSize;
+
+ public Cache(long maxAge, int maxSize) {
+ this.maxAge = maxAge;
+ this.maxSize = maxSize;
+ this.cache = new ConcurrentHashMap<>();
+ }
+
+ private String cacheKey(final int width, final int height, final int coronaangle) {
+ return "key-" + width + "-" + height + "-" + coronaangle;
+ }
+
+ public EncodedImage getCached(final int width, final int height, final int coronaangle) {
+ final Map.Entry<Long, EncodedImage> cached = cache.get(cacheKey(width, height, coronaangle));
+ return cached == null ? null : cached.getValue();
+ }
+
+ public EncodedImage getFresh(final int width, final int height, final int coronaangle) {
+ final String key = cacheKey(width, height, coronaangle);
+ final Map.Entry<Long, EncodedImage> cached = this.cache.get(key);
+ if (cached == null) return null;
+ if (System.currentTimeMillis() - cached.getKey() >= this.maxAge) return null;
+ return cached.getValue();
+ }
+
+ public synchronized void put(final int width, final int height, final int coronaangle, final EncodedImage image) {
+ final String key = cacheKey(width, height, coronaangle);
+ if (!this.cache.containsKey(key) && this.cache.size() >= this.maxSize) {
+ String oldestKey = null;
+ long oldestCreationTime = Long.MAX_VALUE;
+ for (final Map.Entry<String, Map.Entry<Long, EncodedImage>> entry: this.cache.entrySet()) {
+ if (entry.getValue().getKey() < oldestCreationTime) {
+ oldestKey = entry.getKey();
+ oldestCreationTime = entry.getValue().getKey();
+ }
+ }
+ if (oldestKey != null) {
+ this.cache.remove(oldestKey);
+ }
+ }
+ this.cache.put(key, new AbstractMap.SimpleEntry<Long, EncodedImage>(System.currentTimeMillis(), image));
+ }
+
+ public void clear() {
+ this.cache.clear();
+ }
}
+ /** Private constructor to avoid instantiation of utility class. */
+ private NetworkGraph() { } +
public static class CircleThreadPiece {
private final String pieceName;
private final Color color;
@@ -148,19 +199,6 @@ public class NetworkGraph { eventPicture.arcLine(cx, cy, cr - 20, cr, angle, true, null, null, -1, -1, -1, false);
}
- // draw in the secondary search peers
- /*
- if (secondarySearches != null) {
- for (final Thread secondarySearche : secondarySearches) {
- if (secondarySearche == null) continue;
- eventPicture.setColor((secondarySearche.isAlive()) ? RasterPlotter.RED : RasterPlotter.GREEN);
- angle = cyc + (360.0d * ((FlatWordPartitionScheme.std.dhtPosition(UTF8.getBytes(secondarySearche.target().hash), null)) / DOUBLE_LONG_MAX_VALUE));
- eventPicture.arcLine(cx, cy, cr - 10, cr, angle - 1.0, true, null, null, -1, -1, -1, false);
- eventPicture.arcLine(cx, cy, cr - 10, cr, angle + 1.0, true, null, null, -1, -1, -1, false);
- }
- }
- */
-
// draw in the search target
final Iterator<byte[]> i = event.query.getQueryGoal().getIncludeHashes().iterator();
eventPicture.setColor(RasterPlotter.GREY);
@@ -447,4 +485,4 @@ public class NetworkGraph { g.drawChars(caption.toCharArray(), 0, caption.length(), x+LEGEND_BOX_SIZE+5,y);
}
-}
\ No newline at end of file +} diff --git a/source/net/yacy/search/Switchboard.java b/source/net/yacy/search/Switchboard.java index 1d0b8d42a..fb19d2a99 100644 --- a/source/net/yacy/search/Switchboard.java +++ b/source/net/yacy/search/Switchboard.java @@ -182,6 +182,7 @@ import net.yacy.document.parser.pdfParser; import net.yacy.document.parser.html.Evaluation; import net.yacy.gui.Audio; import net.yacy.gui.Tray; +import net.yacy.htroot.NetworkPicture; import net.yacy.http.YaCyHttpServer; import net.yacy.kelondro.blob.ArrayStack; import net.yacy.kelondro.blob.BEncodedHeap; @@ -2445,7 +2446,7 @@ public final class Switchboard extends serverSwitch { // clear graphics caches CircleTool.clearcache(); - NetworkGraph.clearcache(); + NetworkPicture.cache.clear();; } public int schedulerJobSize() { |
