Add unit test for data source merging speed
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
package testItems.wrappers;
|
||||
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper;
|
||||
|
||||
public class TestBiomeWrapper implements IBiomeWrapper
|
||||
{
|
||||
private final String name;
|
||||
|
||||
|
||||
public TestBiomeWrapper(String name)
|
||||
{ this.name = name; }
|
||||
|
||||
|
||||
@Override
|
||||
public String getName()
|
||||
{ return this.name; }
|
||||
@Override
|
||||
public String getSerialString()
|
||||
{ return this.name; }
|
||||
|
||||
@Override
|
||||
public Object getWrappedMcObject()
|
||||
{ return this; }
|
||||
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{ return this.name.hashCode(); }
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (!(obj instanceof TestBiomeWrapper))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.name.equals(((TestBiomeWrapper)obj).name);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package testItems.wrappers;
|
||||
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
public class TestBlockStateWrapper implements IBlockStateWrapper
|
||||
{
|
||||
private final String name;
|
||||
|
||||
|
||||
public TestBlockStateWrapper(String name)
|
||||
{ this.name = name; }
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isAir()
|
||||
{ return false; }
|
||||
@Override
|
||||
public boolean isSolid()
|
||||
{ return true; }
|
||||
@Override
|
||||
public boolean isLiquid()
|
||||
{ return false; }
|
||||
@Override
|
||||
public String getSerialString()
|
||||
{ return this.name; }
|
||||
@Override
|
||||
public int getOpacity()
|
||||
{ return 15; }
|
||||
@Override
|
||||
public int getLightEmission()
|
||||
{ return 0; }
|
||||
@Override
|
||||
public byte getMaterialId()
|
||||
{ return 0; }
|
||||
@Override
|
||||
public boolean isBeaconBlock()
|
||||
{ return false; }
|
||||
@Override
|
||||
public boolean isBeaconTintBlock()
|
||||
{ return false; }
|
||||
@Override
|
||||
public boolean allowsBeaconBeamPassage()
|
||||
{ return false; }
|
||||
@Override
|
||||
public boolean isBeaconBaseBlock()
|
||||
{ return false; }
|
||||
@Override
|
||||
public Color getMapColor()
|
||||
{ return Color.MAGENTA; }
|
||||
@Override
|
||||
public Color getBeaconTintColor()
|
||||
{ return Color.MAGENTA; }
|
||||
|
||||
@Override
|
||||
public Object getWrappedMcObject()
|
||||
{ return this; }
|
||||
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{ return this.name.hashCode(); }
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (!(obj instanceof TestBlockStateWrapper))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.name.equals(((TestBlockStateWrapper)obj).name);
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -30,7 +30,6 @@ import com.seibel.distanthorizons.core.sql.repo.FullDataSourceV2Repo;
|
||||
import com.seibel.distanthorizons.core.util.FullDataPointUtil;
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
import com.seibel.distanthorizons.core.util.ThreadUtil;
|
||||
import com.seibel.distanthorizons.core.util.objects.DataCorruptedException;
|
||||
import it.unimi.dsi.fastutil.bytes.ByteArrayList;
|
||||
import it.unimi.dsi.fastutil.longs.LongArrayList;
|
||||
import org.junit.Assert;
|
||||
@@ -50,7 +49,7 @@ import java.util.concurrent.atomic.LongAdder;
|
||||
* Can also be used to test if there are memory leaks in SQLite
|
||||
* and if the {@link FullDataSourceV2DTO}/{@link FullDataSourceV2}'s are using pooled objects correctly
|
||||
*/
|
||||
public class DhFullDataSourceRepoTests
|
||||
public class DataSourceRepoTests
|
||||
{
|
||||
public static String DATABASE_TYPE = "jdbc:sqlite";
|
||||
public static String DB_FILE_NAME = "test.sqlite";
|
||||
@@ -395,4 +394,5 @@ public class DhFullDataSourceRepoTests
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package tests;
|
||||
|
||||
import com.seibel.distanthorizons.api.enums.config.EDhApiWorldCompressionMode;
|
||||
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiWorldGenerationStep;
|
||||
import com.seibel.distanthorizons.core.dataObjects.fullData.FullDataPointIdMap;
|
||||
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
|
||||
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||
import com.seibel.distanthorizons.core.util.FullDataPointUtil;
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
import com.seibel.distanthorizons.core.util.objects.DataCorruptedException;
|
||||
import it.unimi.dsi.fastutil.bytes.ByteArrayList;
|
||||
import it.unimi.dsi.fastutil.longs.LongArrayList;
|
||||
import org.junit.Assert;
|
||||
import testItems.wrappers.TestBiomeWrapper;
|
||||
import testItems.wrappers.TestBlockStateWrapper;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class DataSourceUpdateSpeedTest
|
||||
{
|
||||
//@Test
|
||||
public void test() throws DataCorruptedException
|
||||
{
|
||||
Random seededRandom = new Random(3);
|
||||
|
||||
|
||||
//===================//
|
||||
// parent datasource //
|
||||
//===================//
|
||||
|
||||
long parentPos = DhSectionPos.encode((byte)7, 0, 0);
|
||||
|
||||
FullDataSourceV2 parentDataSource;
|
||||
{
|
||||
FullDataPointIdMap dataMapping = new FullDataPointIdMap(parentPos);
|
||||
LongArrayList[] fullDataArray = new LongArrayList[FullDataSourceV2.WIDTH * FullDataSourceV2.WIDTH];
|
||||
|
||||
for (int arrayIndex = 0; arrayIndex < FullDataSourceV2.WIDTH * FullDataSourceV2.WIDTH; arrayIndex++)
|
||||
{
|
||||
fullDataArray[arrayIndex] = new LongArrayList(1);
|
||||
|
||||
// random column heights so we can differentiate
|
||||
// columns from each other
|
||||
int columnCount = Math.abs(seededRandom.nextInt() % 31) + 1;
|
||||
int lastMaxY = 4000;
|
||||
for (int colIndex = columnCount; colIndex >= 0; colIndex--)
|
||||
{
|
||||
int height = (Math.abs(seededRandom.nextInt()) % 20) + 1;
|
||||
lastMaxY -= height;
|
||||
|
||||
long datapoint = FullDataPointUtil.encode(
|
||||
colIndex, // id
|
||||
height, // height
|
||||
lastMaxY, // relative min Y
|
||||
LodUtil.MIN_MC_LIGHT, // block light
|
||||
LodUtil.MIN_MC_LIGHT // sky light
|
||||
);
|
||||
fullDataArray[arrayIndex].add(datapoint);
|
||||
|
||||
dataMapping.addIfNotPresentAndGetId(
|
||||
new TestBiomeWrapper(colIndex+""),
|
||||
new TestBlockStateWrapper(colIndex+""));
|
||||
}
|
||||
|
||||
FullDataSourceV2.throwIfDataColumnInWrongOrder(parentPos, fullDataArray[arrayIndex]);
|
||||
}
|
||||
|
||||
byte[] columnGenStep = new byte[FullDataSourceV2.WIDTH * FullDataSourceV2.WIDTH];
|
||||
Arrays.fill(columnGenStep, EDhApiWorldGenerationStep.FEATURES.value);
|
||||
|
||||
byte[] columnWorldCompressionMode = new byte[FullDataSourceV2.WIDTH * FullDataSourceV2.WIDTH];
|
||||
Arrays.fill(columnWorldCompressionMode, EDhApiWorldCompressionMode.VISUALLY_EQUAL.value);
|
||||
|
||||
parentDataSource = FullDataSourceV2.createWithData(parentPos, dataMapping, fullDataArray, columnGenStep, columnWorldCompressionMode);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//==================//
|
||||
// child datasource //
|
||||
//==================//
|
||||
|
||||
long childPos = DhSectionPos.encode((byte)6, 0, 0);
|
||||
|
||||
FullDataSourceV2 childDataSource;
|
||||
{
|
||||
FullDataPointIdMap dataMapping = new FullDataPointIdMap(childPos);
|
||||
LongArrayList[] fullDataArray = new LongArrayList[FullDataSourceV2.WIDTH * FullDataSourceV2.WIDTH];
|
||||
|
||||
for (int arrayIndex = 0; arrayIndex < FullDataSourceV2.WIDTH * FullDataSourceV2.WIDTH; arrayIndex++)
|
||||
{
|
||||
fullDataArray[arrayIndex] = new LongArrayList(1);
|
||||
|
||||
// random column heights so we can differentiate
|
||||
// columns from each other
|
||||
int columnCount = Math.abs(seededRandom.nextInt() % 31) + 1;
|
||||
int lastMaxY = 4000;
|
||||
for (int colIndex = columnCount; colIndex >= 0; colIndex--)
|
||||
{
|
||||
int height = (Math.abs(seededRandom.nextInt()) % 20) + 1;
|
||||
lastMaxY -= height;
|
||||
|
||||
long datapoint = FullDataPointUtil.encode(
|
||||
colIndex, // id
|
||||
height, // height
|
||||
lastMaxY, // relative min Y
|
||||
LodUtil.MAX_MC_LIGHT, // block light
|
||||
LodUtil.MAX_MC_LIGHT // sky light
|
||||
);
|
||||
fullDataArray[arrayIndex].add(datapoint);
|
||||
|
||||
dataMapping.addIfNotPresentAndGetId(
|
||||
new TestBiomeWrapper(colIndex+""),
|
||||
new TestBlockStateWrapper(colIndex+""));
|
||||
}
|
||||
|
||||
FullDataSourceV2.throwIfDataColumnInWrongOrder(childPos, fullDataArray[arrayIndex]);
|
||||
}
|
||||
|
||||
byte[] columnGenStep = new byte[FullDataSourceV2.WIDTH * FullDataSourceV2.WIDTH];
|
||||
Arrays.fill(columnGenStep, EDhApiWorldGenerationStep.FEATURES.value);
|
||||
|
||||
byte[] columnWorldCompressionMode = new byte[FullDataSourceV2.WIDTH * FullDataSourceV2.WIDTH];
|
||||
Arrays.fill(columnWorldCompressionMode, EDhApiWorldCompressionMode.VISUALLY_EQUAL.value);
|
||||
|
||||
|
||||
|
||||
childDataSource = FullDataSourceV2.createWithData(childPos, dataMapping, fullDataArray, columnGenStep, columnWorldCompressionMode);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=========================//
|
||||
// (optional) loop forever //
|
||||
//=========================//
|
||||
|
||||
// this can be set to "true"
|
||||
// so we can profile the DTO creation process and
|
||||
// see if there are any object leaks and how the GC
|
||||
// handles it
|
||||
if (true)
|
||||
{
|
||||
System.out.println("Starting long update test for time testing...");
|
||||
|
||||
long lastLogMsTime = 0;
|
||||
|
||||
long totalNano = 0;
|
||||
|
||||
NumberFormat numberFormat = NumberFormat.getNumberInstance();
|
||||
|
||||
// run for a long time
|
||||
for (int i = 1; i < 100_000_000; i++)
|
||||
{
|
||||
long startNano = System.nanoTime();
|
||||
|
||||
boolean updated = parentDataSource.updateFromDataSource(childDataSource);
|
||||
//Assert.assertTrue(updated);
|
||||
|
||||
long updateTimeNano = System.nanoTime() - startNano;
|
||||
totalNano += updateTimeNano;
|
||||
|
||||
long nowMs = System.currentTimeMillis();
|
||||
if (nowMs - lastLogMsTime > 5_000)
|
||||
{
|
||||
lastLogMsTime = nowMs;
|
||||
|
||||
double avgMs = ((totalNano / 1_000_000.0)/i);
|
||||
double totalMs = totalNano / 1_000_000.0;
|
||||
System.out.println("count: "+numberFormat.format(i)+"\tavg ms: "+numberFormat.format(avgMs)+"\ttotal ms: "+numberFormat.format(totalMs));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//================//
|
||||
// helper methods //
|
||||
//================//
|
||||
|
||||
private static void assertArraysAreEqual(ByteArrayList expectedArray, ByteArrayList actualArray)
|
||||
{
|
||||
Assert.assertEquals("size mismatch", expectedArray.size(), actualArray.size());
|
||||
|
||||
for (int i = 0; i < expectedArray.size(); i++)
|
||||
{
|
||||
byte expectedNumb = expectedArray.getByte(i);
|
||||
byte actualNumb = actualArray.getByte(i);
|
||||
|
||||
Assert.assertEquals("value mismatch at index ["+i+"]", expectedNumb, actualNumb);
|
||||
}
|
||||
}
|
||||
|
||||
private static void assertArraysAreEqual(LongArrayList expectedArray, LongArrayList actualArray)
|
||||
{ assertArraysAreEqual(null, expectedArray, actualArray); }
|
||||
private static void assertArraysAreEqual(String message, LongArrayList expectedArray, LongArrayList actualArray)
|
||||
{
|
||||
Assert.assertEquals(message + "size mismatch", expectedArray.size(), actualArray.size());
|
||||
|
||||
for (int i = 0; i < expectedArray.size(); i++)
|
||||
{
|
||||
long expectedNumb = expectedArray.getLong(i);
|
||||
long actualNumb = actualArray.getLong(i);
|
||||
|
||||
Assert.assertEquals(message + "value mismatch at index ["+i+"]", expectedNumb, actualNumb);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user