Skip to content

Commit

Permalink
Separate data and index memory #755
Browse files Browse the repository at this point in the history
  • Loading branch information
diego.salvi committed Aug 27, 2021
1 parent 4619b01 commit 2ac8a7c
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 18 deletions.
44 changes: 38 additions & 6 deletions herddb-core/src/main/java/herddb/core/DBManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,10 @@ public class DBManager implements AutoCloseable, MetadataChangeListener {
private long maxMemoryReference = ServerConfiguration.PROPERTY_MEMORY_LIMIT_REFERENCE_DEFAULT;
private long maxLogicalPageSize = ServerConfiguration.PROPERTY_MAX_LOGICAL_PAGE_SIZE_DEFAULT;
private long maxDataUsedMemory = ServerConfiguration.PROPERTY_MAX_DATA_MEMORY_DEFAULT;
private long maxIndexUsedMemory = ServerConfiguration.PROPERTY_MAX_INDEX_MEMORY_DEFAULT;
private long maxPKUsedMemory = ServerConfiguration.PROPERTY_MAX_PK_MEMORY_DEFAULT;
private double maxDataUsedMemoryPercentage = ServerConfiguration.PROPERTY_MAX_DATA_MEMORY_PERCENTAGE_DEFAULT;
private double maxIndexUsedMemoryPercentage = ServerConfiguration.PROPERTY_MAX_INDEX_MEMORY_PERCENTAGE_DEFAULT;
private double maxPKUsedMemoryPercentage = ServerConfiguration.PROPERTY_MAX_PK_MEMORY_PERCENTAGE_DEFAULT;

private boolean clearAtBoot = false;
Expand Down Expand Up @@ -259,6 +261,10 @@ public Thread newThread(final Runnable r) {
ServerConfiguration.PROPERTY_MAX_DATA_MEMORY,
ServerConfiguration.PROPERTY_MAX_DATA_MEMORY_DEFAULT);

this.maxIndexUsedMemory = configuration.getLong(
ServerConfiguration.PROPERTY_MAX_INDEX_MEMORY,
ServerConfiguration.PROPERTY_MAX_INDEX_MEMORY_DEFAULT);

this.maxPKUsedMemory = configuration.getLong(
ServerConfiguration.PROPERTY_MAX_PK_MEMORY,
ServerConfiguration.PROPERTY_MAX_PK_MEMORY_DEFAULT);
Expand All @@ -267,15 +273,23 @@ public Thread newThread(final Runnable r) {
ServerConfiguration.PROPERTY_MAX_DATA_MEMORY_PERCENTAGE,
ServerConfiguration.PROPERTY_MAX_DATA_MEMORY_PERCENTAGE_DEFAULT);

if (maxDataUsedMemoryPercentage <= 0) {
if (maxDataUsedMemoryPercentage <= 0.0D) {
maxDataUsedMemoryPercentage = ServerConfiguration.PROPERTY_MAX_DATA_MEMORY_PERCENTAGE_DEFAULT;
}

this.maxIndexUsedMemoryPercentage = configuration.getDouble(
ServerConfiguration.PROPERTY_MAX_INDEX_MEMORY_PERCENTAGE,
ServerConfiguration.PROPERTY_MAX_INDEX_MEMORY_PERCENTAGE_DEFAULT);

if (maxIndexUsedMemoryPercentage <= 0.0D) {
maxIndexUsedMemoryPercentage = ServerConfiguration.PROPERTY_MAX_DATA_MEMORY_PERCENTAGE_DEFAULT;
}

this.maxPKUsedMemoryPercentage = configuration.getDouble(
ServerConfiguration.PROPERTY_MAX_PK_MEMORY_PERCENTAGE,
ServerConfiguration.PROPERTY_MAX_PK_MEMORY_PERCENTAGE_DEFAULT);

if (maxPKUsedMemoryPercentage <= 0) {
if (maxPKUsedMemoryPercentage <= 0.0D) {
maxPKUsedMemoryPercentage = ServerConfiguration.PROPERTY_MAX_PK_MEMORY_PERCENTAGE_DEFAULT;
}

Expand Down Expand Up @@ -373,6 +387,14 @@ public void setMaxDataUsedMemory(long maxDataUsedMemory) {
this.maxDataUsedMemory = maxDataUsedMemory;
}

public long getMaxIndexUsedMemory() {
return maxIndexUsedMemory;
}

public void setMaxIndexUsedMemory(long maxIndexUsedMemory) {
this.maxIndexUsedMemory = maxIndexUsedMemory;
}

public long getMaxPKUsedMemory() {
return maxPKUsedMemory;
}
Expand Down Expand Up @@ -426,24 +448,34 @@ public void start() throws DataStorageManagerException, LogNotAvailableException
maxDataUsedMemory = (long) (maxDataUsedMemoryPercentage * maxMemoryReference);
}

/* If max index memory for pages isn't configured or is too high default it to a maxMemoryReference percentage */
if (maxIndexUsedMemory == 0 || maxIndexUsedMemory > maxMemoryReference) {
maxIndexUsedMemory = (long) (maxIndexUsedMemoryPercentage * maxMemoryReference);
}

/* If max index memory for pages isn't configured or is too high default it to a maxMemoryReference percentage */
if (maxPKUsedMemory == 0 || maxPKUsedMemory > maxMemoryReference) {
maxPKUsedMemory = (long) (maxPKUsedMemoryPercentage * maxMemoryReference);
}

/* If max used memory is too high lower index and data accordingly */
if (maxDataUsedMemory + maxPKUsedMemory > maxMemoryReference) {
if (maxDataUsedMemory + maxIndexUsedMemory + maxPKUsedMemory > maxMemoryReference) {

long data = (int) ((double) maxDataUsedMemory
/ ((double) (maxDataUsedMemory + maxPKUsedMemory)) * maxMemoryReference);
/ ((double) (maxDataUsedMemory + maxIndexUsedMemory + maxPKUsedMemory)) * maxMemoryReference);

long index = (int) ((double) maxIndexUsedMemory
/ ((double) (maxDataUsedMemory + maxIndexUsedMemory + maxPKUsedMemory)) * maxMemoryReference);

long pk = (int) ((double) maxPKUsedMemory
/ ((double) (maxDataUsedMemory + maxPKUsedMemory)) * maxMemoryReference);
/ ((double) (maxDataUsedMemory + maxIndexUsedMemory + maxPKUsedMemory)) * maxMemoryReference);

maxDataUsedMemory = data;
maxIndexUsedMemory = data;
maxPKUsedMemory = pk;
}

memoryManager = new MemoryManager(maxDataUsedMemory, maxPKUsedMemory, maxLogicalPageSize);
memoryManager = new MemoryManager(maxDataUsedMemory, maxIndexUsedMemory, maxPKUsedMemory, maxLogicalPageSize);

metadataStorageManager.start();

Expand Down
39 changes: 34 additions & 5 deletions herddb-core/src/main/java/herddb/core/MemoryManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,18 @@ public class MemoryManager {
MemoryManager.class.getName() + ".pageReplacementPolicy", "cp").toLowerCase(Locale.US);

private final long maxDataUsedMemory;
private final long maxIndexUsedMemory;
private final long maxPKUsedMemory;
private final long maxLogicalPageSize;

private final PageReplacementPolicy dataPageReplacementPolicy;
private final PageReplacementPolicy indexPageReplacementPolicy;
private final PageReplacementPolicy pkPageReplacementPolicy;

public MemoryManager(long maxDataUsedMemory, long maxPKUsedMemory, long maxLogicalPageSize) {
public MemoryManager(long maxDataUsedMemory, long maxIndexUsedMemory, long maxPKUsedMemory, long maxLogicalPageSize) {

this.maxDataUsedMemory = maxDataUsedMemory;
this.maxIndexUsedMemory = maxIndexUsedMemory;
this.maxPKUsedMemory = maxPKUsedMemory;
this.maxLogicalPageSize = maxLogicalPageSize;

Expand All @@ -55,33 +58,51 @@ public MemoryManager(long maxDataUsedMemory, long maxPKUsedMemory, long maxLogic
+ ") must be greater or equal than page size (" + maxLogicalPageSize + ")");
}

// Max index memory 0 is acceptable, will use data memory instead
if (maxIndexUsedMemory > 0 && maxIndexUsedMemory < maxLogicalPageSize) {
throw new IllegalArgumentException("Max memory for index pages (" + maxIndexUsedMemory
+ ") must be greater or equal than page size (" + maxLogicalPageSize + ")");
}

if (maxPKUsedMemory < maxLogicalPageSize) {
throw new IllegalArgumentException("Max memory for primary key index pages (" + maxPKUsedMemory
+ ") must be greater or equal than page size (" + maxLogicalPageSize + ")");
}

final int dataPages = (int) (maxDataUsedMemory / maxLogicalPageSize);
final int indexPages = (int) (maxIndexUsedMemory / maxLogicalPageSize);
final int pkPages = (int) (maxPKUsedMemory / maxLogicalPageSize);

LOGGER.log(Level.INFO, "Maximum amount of memory for data and indexes {0}", (maxDataUsedMemory / (1024 * 1024)) + " MB");
LOGGER.log(Level.INFO, "Maximum amount of memory for primary key indexes {0}", (maxPKUsedMemory / (1024 * 1024)) + " MB");
LOGGER.log(Level.INFO, "Maximum amount of memory for primary key indexes {0} ({1} pages)",
new Object[]{(maxPKUsedMemory / (1024 * 1024)) + " MB", pkPages});

if (indexPages > 0) {
LOGGER.log(Level.INFO, "Maximum amount of memory for data {0} ({1} pages)",
new Object[]{(maxDataUsedMemory / (1024 * 1024)) + " MB", dataPages});
LOGGER.log(Level.INFO, "Maximum amount of memory for indexes {0} ({1} pages)",
new Object[]{(maxIndexUsedMemory / (1024 * 1024)) + " MB", indexPages});
} else {
LOGGER.log(Level.INFO, "Maximum amount of memory for data and indexes {0} ({1} pages)",
new Object[]{(maxDataUsedMemory / (1024 * 1024)) + " MB", dataPages});
}

LOGGER.log(Level.INFO, "Maximum number of loaded pages for data {0}"
+ ", maximum number of loadedd pages for primary key indexes {1}", new Object[]{dataPages, pkPages});
switch (PAGE_REPLACEMENT_POLICY) {
case "random":
dataPageReplacementPolicy = new RandomPageReplacementPolicy(dataPages);
indexPageReplacementPolicy = indexPages > 0 ? new RandomPageReplacementPolicy(dataPages) : dataPageReplacementPolicy;
pkPageReplacementPolicy = new RandomPageReplacementPolicy(pkPages);
break;

case "cp":
dataPageReplacementPolicy = new ClockProPolicy(dataPages);
indexPageReplacementPolicy = indexPages > 0 ? new ClockProPolicy(dataPages) : dataPageReplacementPolicy;
pkPageReplacementPolicy = new ClockProPolicy(pkPages);
break;

case "car":
default:
dataPageReplacementPolicy = new ClockAdaptiveReplacement(dataPages);
indexPageReplacementPolicy = indexPages > 0 ? new ClockAdaptiveReplacement(dataPages) : dataPageReplacementPolicy;
pkPageReplacementPolicy = new ClockAdaptiveReplacement(pkPages);
}

Expand All @@ -92,6 +113,10 @@ public long getMaxDataUsedMemory() {
}

public long getMaxIndexUsedMemory() {
return maxIndexUsedMemory;
}

public long getMaxPKUsedMemory() {
return maxPKUsedMemory;
}

Expand All @@ -103,6 +128,10 @@ public PageReplacementPolicy getDataPageReplacementPolicy() {
return dataPageReplacementPolicy;
}

public PageReplacementPolicy getIndexPageReplacementPolicy() {
return indexPageReplacementPolicy;
}

public PageReplacementPolicy getPKPageReplacementPolicy() {
return pkPageReplacementPolicy;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ public BRINIndexManager(Index index, MemoryManager memoryManager, AbstractTableM
writeLockTimeout, readLockTimeout);
this.data = new BlockRangeIndex<>(
memoryManager.getMaxLogicalPageSize(),
memoryManager.getDataPageReplacementPolicy(),
memoryManager.getIndexPageReplacementPolicy(),
storageLayer);
}

Expand Down
17 changes: 15 additions & 2 deletions herddb-core/src/main/java/herddb/server/ServerConfiguration.java
Original file line number Diff line number Diff line change
Expand Up @@ -280,20 +280,33 @@ public final class ServerConfiguration {
public static final String PROPERTY_MAX_DATA_MEMORY = "server.memory.data.limit";
public static final long PROPERTY_MAX_DATA_MEMORY_DEFAULT = 0L;

/**
* Maximum amount of memory used for data pages
*/
public static final String PROPERTY_MAX_INDEX_MEMORY = "server.memory.index.limit";
public static final long PROPERTY_MAX_INDEX_MEMORY_DEFAULT = 0L;

/**
* Maximum amount of memory used for primary index pages
*/
public static final String PROPERTY_MAX_PK_MEMORY = "server.memory.pk.limit";
public static final long PROPERTY_MAX_PK_MEMORY_DEFAULT = 0L;

/**
* Percentage of maximum memory used for data pages, will be used if {@link PROPERTY_MAX_PK_MEMORY} is not given
* Percentage of maximum memory used for data pages, will be used if {@link PROPERTY_MAX_DATA_MEMORY} is not given
*/
public static final String PROPERTY_MAX_DATA_MEMORY_PERCENTAGE = "server.memory.data.percentage";
public static final double PROPERTY_MAX_DATA_MEMORY_PERCENTAGE_DEFAULT = 0.50D;

/**
* Percentage of maximum memory used for primary index pages, will be used if {@link PROPERTY_MAX_DATA_MEMORY} is
* Percentage of maximum memory used for index pages, will be used if {@link PROPERTY_MAX_INDEX_MEMORY} is not given.
* A value of zero means "no dedicated index memory": data memory will be used instead.
*/
public static final String PROPERTY_MAX_INDEX_MEMORY_PERCENTAGE = "server.memory.index.percentage";
public static final double PROPERTY_MAX_INDEX_MEMORY_PERCENTAGE_DEFAULT = 0.00D;

/**
* Percentage of maximum memory used for primary index pages, will be used if {@link PROPERTY_MAX_PK_MEMORY} is
* not given
*/
public static final String PROPERTY_MAX_PK_MEMORY_PERCENTAGE = "server.memory.pk.percentage";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,13 @@ public void testChangeRoleAndReleaseMemory() throws Exception {
new HashSet<>(Arrays.asList("server1", "server2")), "server1", 1, 0), StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), TransactionContext.NO_TRANSACTION);

assertEquals(0, server2MemoryManager.getDataPageReplacementPolicy().size());
assertEquals(0, server2MemoryManager.getIndexPageReplacementPolicy().size());
assertEquals(0, server2MemoryManager.getPKPageReplacementPolicy().size());

server_2.waitForTableSpaceBoot(TableSpace.DEFAULT, false);

assertEquals(2, server2MemoryManager.getDataPageReplacementPolicy().size());
assertEquals(1, server2MemoryManager.getDataPageReplacementPolicy().size());
assertEquals(1, server2MemoryManager.getIndexPageReplacementPolicy().size());
assertEquals(1, server2MemoryManager.getPKPageReplacementPolicy().size());

// stop tablespace on server2
Expand All @@ -125,6 +127,7 @@ public void testChangeRoleAndReleaseMemory() throws Exception {

// memory must have been totally released
assertEquals(0, server2MemoryManager.getDataPageReplacementPolicy().size());
assertEquals(0, server2MemoryManager.getIndexPageReplacementPolicy().size());
assertEquals(0, server2MemoryManager.getPKPageReplacementPolicy().size());

// start tablespace on server2, as let it become leader
Expand All @@ -135,6 +138,7 @@ public void testChangeRoleAndReleaseMemory() throws Exception {

assertTrue("unexpected value " + server2MemoryManager.getDataPageReplacementPolicy().size(),
server2MemoryManager.getDataPageReplacementPolicy().size() >= 1);
assertEquals(1, server2MemoryManager.getIndexPageReplacementPolicy().size());
assertEquals(1, server2MemoryManager.getPKPageReplacementPolicy().size());

server_1.getManager().executeStatement(new AlterTableSpaceStatement(TableSpace.DEFAULT,
Expand All @@ -149,6 +153,7 @@ public void testChangeRoleAndReleaseMemory() throws Exception {

// memory must have been totally released again
assertEquals(0, server2MemoryManager.getDataPageReplacementPolicy().size());
assertEquals(0, server2MemoryManager.getIndexPageReplacementPolicy().size());
assertEquals(0, server2MemoryManager.getPKPageReplacementPolicy().size());

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public class BLinkKeyToPageIndexTest extends KeyToPageIndexTest {
@Override
KeyToPageIndex createIndex() {

MemoryManager mem = new MemoryManager(5 * (1L << 20), 10 * (128L << 10), (128L << 10));
MemoryManager mem = new MemoryManager(5 * (1L << 20), 10 * (128L << 10), 0, (128L << 10));
MemoryDataStorageManager ds = new MemoryDataStorageManager();
BLinkKeyToPageIndex idx = new BLinkKeyToPageIndex("tblspc", "tbl", mem, ds);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ public static void main(String[] args) {
PrintStream eps = new PrintStream(eos);
System.setErr(eps);

MemoryManager mem = new MemoryManager(5 * (1L << 20), 10 * (128L << 10), (128L << 10));
MemoryManager mem = new MemoryManager(5 * (1L << 20), 10 * (128L << 10), 0, (128L << 10));

try (MemoryDataStorageManager ds = new MemoryDataStorageManager();
BLinkKeyToPageIndex idx = new BLinkKeyToPageIndex("tblspc", "tbl", mem, ds)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ public static void main(String[] args) {
PrintStream eps = new PrintStream(eos);
System.setErr(eps);

MemoryManager mem = new MemoryManager(5 * (1L << 20), 10 * (128L << 10), (128L << 10));
MemoryManager mem = new MemoryManager(5 * (1L << 20), 10 * (128L << 10), 0, (128L << 10));
// MemoryManager mem = new MemoryManager(5 * (1L << 20), (128L << 10), (128L << 10));

try (MemoryDataStorageManager ds = new MemoryDataStorageManager();
Expand Down

0 comments on commit 2ac8a7c

Please sign in to comment.