Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge pull request #792 from apcj/pwp-no-wait

PersistenceWindowPool.refreshBricks() blocking
  • Loading branch information...
commit 21e95403a8f2668dd2f969249b4954ec81f6d4c3 2 parents 0beff1c + d1075b0
@tinwelint tinwelint authored
View
112 kernel/src/main/java/org/neo4j/kernel/impl/nioneo/store/PersistenceWindowPool.java
@@ -28,6 +28,9 @@
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -70,6 +73,11 @@
private final boolean readOnly;
+ private final AtomicBoolean refreshing = new AtomicBoolean();
+ private final AtomicInteger avertedRefreshes = new AtomicInteger();
+ private final AtomicLong refreshTime = new AtomicLong();
+ private final AtomicInteger refreshes = new AtomicInteger();
+
/**
* Create new pool for a store.
*
@@ -97,6 +105,7 @@ public PersistenceWindowPool( String storeName, int blockSize,
this.mapMode = readOnly ? MapMode.READ_ONLY : MapMode.READ_WRITE;
setupBricks();
dumpStatus();
+ System.out.println( getStats().toString() );
}
/**
@@ -465,50 +474,72 @@ private void refreshBricks()
if ( brickMiss < REFRESH_BRICK_COUNT || brickSize <= 0 )
return;
- synchronized ( this )
+ if ( refreshing.compareAndSet( false, true ) )
{
- brickMiss = 0;
- Pair<List<BrickElement>, List<BrickElement>> currentMappings = gatherMappedVersusUnmappedWindows();
- List<BrickElement> mappedBricks = currentMappings.first();
- List<BrickElement> unmappedBricks = currentMappings.other();
-
- // Fill up unused memory, i.e. map unmapped bricks as much as available memory allows
- // and request patterns signals. Start the loop from the end of the array where the
- // bricks with highest hit ratio are.
- int unmappedIndex = unmappedBricks.size() - 1;
- while ( memUsed + brickSize <= availableMem && unmappedIndex >= 0 )
+ // No one is doing refresh right now, go ahead and do it
+ try
{
- BrickElement unmappedBrick = unmappedBricks.get( unmappedIndex-- );
- if ( unmappedBrick.getHit() == 0 )
- // We have more memory available, but no more windows have actually
- // been requested so don't map unused random windows.
- return;
-
- allocateNewWindow( unmappedBrick );
+ long t = System.currentTimeMillis();
+ doRefreshBricks();
+ refreshes.incrementAndGet();
+ refreshTime.addAndGet( System.currentTimeMillis()-t );
}
+ finally
+ {
+ refreshing.set( false );
+ }
+ }
+ else
+ {
+ // Another thread is doing refresh right now, trust it to refresh the bricks
+ // and just go about my business.
+ avertedRefreshes.incrementAndGet();
+ }
+ }
+
+ private synchronized void doRefreshBricks()
+ {
+ brickMiss = 0;
+ Pair<List<BrickElement>, List<BrickElement>> currentMappings = gatherMappedVersusUnmappedWindows();
+ List<BrickElement> mappedBricks = currentMappings.first();
+ List<BrickElement> unmappedBricks = currentMappings.other();
+
+ // Fill up unused memory, i.e. map unmapped bricks as much as available memory allows
+ // and request patterns signals. Start the loop from the end of the array where the
+ // bricks with highest hit ratio are.
+ int unmappedIndex = unmappedBricks.size() - 1;
+ while ( memUsed + brickSize <= availableMem && unmappedIndex >= 0 )
+ {
+ BrickElement unmappedBrick = unmappedBricks.get( unmappedIndex-- );
+ if ( unmappedBrick.getHit() == 0 )
+ // We have more memory available, but no more windows have actually
+ // been requested so don't map unused random windows.
+ return;
- // Switch bad/unused mappings. Start iterating over mapped bricks
- // from the beginning (those with lowest hit ratio) and unmapped from the end
- // (or rather where the fill-up-unused-memory loop above left off) where we've
- // got the unmapped bricks with highest hit ratio.
- int mappedIndex = 0;
- while ( unmappedIndex >= 0 && mappedIndex < mappedBricks.size() )
+ allocateNewWindow( unmappedBrick );
+ }
+
+ // Switch bad/unused mappings. Start iterating over mapped bricks
+ // from the beginning (those with lowest hit ratio) and unmapped from the end
+ // (or rather where the fill-up-unused-memory loop above left off) where we've
+ // got the unmapped bricks with highest hit ratio.
+ int mappedIndex = 0;
+ while ( unmappedIndex >= 0 && mappedIndex < mappedBricks.size() )
+ {
+ BrickElement mappedBrick = mappedBricks.get( mappedIndex++ );
+ BrickElement unmappedBrick = unmappedBricks.get( unmappedIndex-- );
+ if ( mappedBrick.getHit() >= unmappedBrick.getHit() )
+ // We've passed a point where we don't have any unmapped brick
+ // with a higher hit ratio then the lowest mapped brick. We're done.
+ break;
+
+ LockableWindow window = mappedBrick.getWindow();
+ if (window.writeOutAndCloseIfFree( readOnly ) )
{
- BrickElement mappedBrick = mappedBricks.get( mappedIndex++ );
- BrickElement unmappedBrick = unmappedBricks.get( unmappedIndex-- );
- if ( mappedBrick.getHit() >= unmappedBrick.getHit() )
- // We've passed a point where we don't have any unmapped brick
- // with a higher hit ratio then the lowest mapped brick. We're done.
- break;
-
- LockableWindow window = mappedBrick.getWindow();
- if (window.writeOutAndCloseIfFree( readOnly ) )
- {
- mappedBrick.setWindow( null );
- memUsed -= brickSize;
- if ( allocateNewWindow( unmappedBrick ) )
- switches++;
- }
+ mappedBrick.setWindow( null );
+ memUsed -= brickSize;
+ if ( allocateNewWindow( unmappedBrick ) )
+ switches++;
}
}
}
@@ -644,8 +675,9 @@ private void logWarn( String logMessage, Throwable cause )
WindowPoolStats getStats()
{
+ int avgRefreshTime = refreshes.get() == 0 ? 0 : (int)(refreshTime.get()/refreshes.get());
return new WindowPoolStats( storeName, availableMem, memUsed, brickCount,
- brickSize, hit, miss, ooe );
+ brickSize, hit, miss, ooe, switches, avgRefreshTime, refreshes.get(), avertedRefreshes.get() );
}
private static class BrickElement
View
62 kernel/src/main/java/org/neo4j/kernel/impl/nioneo/store/WindowPoolStats.java
@@ -19,6 +19,8 @@
*/
package org.neo4j.kernel.impl.nioneo.store;
+import java.io.File;
+
public class WindowPoolStats
{
private final String name;
@@ -32,11 +34,17 @@
private final int hitCount;
private final int missCount;
private final int oomCount;
+
+ private final int switchCount;
+ private final int avgRefreshTime;
+ private final int refreshCount;
+ private final int avertedRefreshCount;
public WindowPoolStats( String name, long memAvail, long memUsed, int windowCount,
- int windowSize, int hitCount, int missCount, int oomCount )
+ int windowSize, int hitCount, int missCount, int oomCount, int switchCount, int avgRefreshTime,
+ int refreshCount, int avertedRefreshCount )
{
- this.name = name;
+ this.name = extractName( name );
this.memAvail = memAvail;
this.memUsed = memUsed;
this.windowCount = windowCount;
@@ -44,8 +52,17 @@ public WindowPoolStats( String name, long memAvail, long memUsed, int windowCoun
this.hitCount = hitCount;
this.missCount = missCount;
this.oomCount = oomCount;
+ this.switchCount = switchCount;
+ this.avgRefreshTime = avgRefreshTime;
+ this.refreshCount = refreshCount;
+ this.avertedRefreshCount = avertedRefreshCount;
}
+ private String extractName( String name )
+ {
+ return new File( name ).getName();
+ }
+
public String getName()
{
return name;
@@ -86,16 +103,41 @@ public int getOomCount()
return oomCount;
}
+ public int getSwitchCount()
+ {
+ return switchCount;
+ }
+
+ public int getAvgRefreshTime()
+ {
+ return avgRefreshTime;
+ }
+
+ public int getRefreshCount()
+ {
+ return refreshCount;
+ }
+
+ public int getAvertedRefreshCount()
+ {
+ return avertedRefreshCount;
+ }
+
@Override
public String toString()
{
- return "WindowPoolStats[" +
- "mem available:" + memAvail + " " +
- "mem used:" + memUsed + " " +
- "windows:" + windowCount + " " +
- "win size:" + windowSize + " " +
- "hits:" + hitCount + " " +
- "misses:" + missCount + " " +
- "ooms:" + oomCount + "]";
+ return "WindowPoolStats['" + name + "', " +
+ "memAvail:" + memAvail + ", " +
+ "memUsed:" + memUsed + ", " +
+ "windowCount:" + windowCount + ", " +
+ "windowSize:" + windowSize + ", " +
+ "hitCount:" + hitCount + ", " +
+ "missCount:" + missCount + ", " +
+ "oomCount:" + oomCount + ", " +
+ "switchCount:" + switchCount + ", " +
+ "avgRefreshTime:" + avgRefreshTime + ", " +
+ "refreshCount:" + refreshCount + ", " +
+ "avertedRefreshCount:" + avertedRefreshCount +
+ "]";
}
}
Please sign in to comment.
Something went wrong with that request. Please try again.