Skip to content

Commit

Permalink
Add MBTiles benchmark and refactor TileStore
Browse files Browse the repository at this point in the history
  • Loading branch information
bchapuis committed Jun 13, 2023
1 parent 42e3c83 commit 7cf110e
Show file tree
Hide file tree
Showing 12 changed files with 137 additions and 33 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/

package org.apache.baremaps.benchmarks;

import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import org.apache.baremaps.tilestore.TileCoord;
import org.apache.baremaps.tilestore.TileStoreException;
import org.apache.baremaps.tilestore.mbtiles.MBTiles;
import org.apache.baremaps.workflow.tasks.ExportVectorTiles;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

@State(Scope.Benchmark)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@Fork(value = 1, warmups = 1)
public class MBTilesBenchmark {

public Random random = new Random(0);

@Param({"10", "100", "1000"})
public int iterations;

private MBTiles mbTiles;

@Setup
public void setup() throws IOException, TileStoreException {
var sqliteFile = File.createTempFile("baremaps", ".sqlite");
sqliteFile.deleteOnExit();
var sqliteDataSource = ExportVectorTiles.createDataSource(sqliteFile.toPath());
mbTiles = new MBTiles(sqliteDataSource);
mbTiles.initializeDatabase();
}

@Benchmark
@BenchmarkMode(Mode.SingleShotTime)
public void writeMBTiles(MBTilesBenchmark benchmark) throws TileStoreException {
for (int i = 0; i < benchmark.iterations; i++) {
var bytes = new byte[1 << 16];
random.nextBytes(bytes);
mbTiles.put(new TileCoord(0, 0, i), ByteBuffer.wrap(bytes));
}
}

public static void main(String[] args) throws RunnerException {
Options opt =
new OptionsBuilder().include(MBTilesBenchmark.class.getSimpleName()).forks(1).build();
new Runner(opt).run();
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,10 @@ public TileCache(TileStore tileStore, CaffeineSpec spec) {

/** {@inheritDoc} */
@Override
public ByteBuffer read(TileCoord tileCoord) throws TileStoreException {
public ByteBuffer get(TileCoord tileCoord) throws TileStoreException {
return cache.get(tileCoord, t -> {
try {
var buffer = tileStore.read(t);
var buffer = tileStore.get(t);
if (buffer == null) {
return null;
} else {
Expand All @@ -68,8 +68,8 @@ public ByteBuffer read(TileCoord tileCoord) throws TileStoreException {

/** {@inheritDoc} */
@Override
public void write(TileCoord tileCoord, ByteBuffer bytes) throws TileStoreException {
tileStore.write(tileCoord, bytes);
public void put(TileCoord tileCoord, ByteBuffer bytes) throws TileStoreException {
tileStore.put(tileCoord, bytes);
cache.invalidate(tileCoord);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@ public TileChannel(TileStore source, TileStore target, boolean deleteEmptyTiles)
@Override
public void accept(TileCoord tileCoord) {
try {
ByteBuffer blob = source.read(tileCoord);
ByteBuffer blob = source.get(tileCoord);
if (blob != null) {
target.write(tileCoord, blob);
target.put(tileCoord, blob);
} else if (deleteEmptyTiles) {
target.delete(tileCoord);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,57 @@


import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;

/** Represents a store for tiles. */
public interface TileStore {

/**
* Reads the content of a tile.
* Gets the content of a tile.
*
* @param tileCoord the tile coordinate
* @return the content of the tile
* @throws TileStoreException
*/
ByteBuffer read(TileCoord tileCoord) throws TileStoreException;
ByteBuffer get(TileCoord tileCoord) throws TileStoreException;

/**
* Writes the content of a tile.
* Gets the content of several tiles.
*
* @param tileCoords the tile coordinates
* @return the content of the tiles
* @throws TileStoreException
*/
default List<ByteBuffer> get(List<TileCoord> tileCoords) throws TileStoreException {
var blobs = new ArrayList<ByteBuffer>(tileCoords.size());
for (var tileCoord : tileCoords) {
blobs.add(get(tileCoord));
}
return blobs;
}

/**
* Puts the content of a tile.
*
* @param tileCoord the tile coordinate
* @param blob the content of the tile
* @throws TileStoreException
*/
void write(TileCoord tileCoord, ByteBuffer blob) throws TileStoreException;
void put(TileCoord tileCoord, ByteBuffer blob) throws TileStoreException;

/**
* Puts the content of several tiles.
*
* @param tileCoords the tile coordinates
* @param blobs the content of the tiles
* @throws TileStoreException
*/
default void put(List<TileCoord> tileCoords, List<ByteBuffer> blobs) throws TileStoreException {
for (int i = 0; i < tileCoords.size(); i++) {
put(tileCoords.get(i), blobs.get(i));
}
}

/**
* Deletes the content of a tile.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public FileTileStore(Path path) {

/** {@inheritDoc} */
@Override
public ByteBuffer read(TileCoord tileCoord) throws TileStoreException {
public ByteBuffer get(TileCoord tileCoord) throws TileStoreException {
try {
return ByteBuffer.wrap(Files.readAllBytes(resolve(tileCoord)));
} catch (IOException e) {
Expand All @@ -48,7 +48,7 @@ public ByteBuffer read(TileCoord tileCoord) throws TileStoreException {

/** {@inheritDoc} */
@Override
public void write(TileCoord tileCoord, ByteBuffer blob) throws TileStoreException {
public void put(TileCoord tileCoord, ByteBuffer blob) throws TileStoreException {
try {
var file = resolve(tileCoord);
Files.createDirectories(file.getParent());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public MBTiles(DataSource dataSource) {

/** {@inheritDoc} */
@Override
public ByteBuffer read(TileCoord tileCoord) throws TileStoreException {
public ByteBuffer get(TileCoord tileCoord) throws TileStoreException {
try (Connection connection = dataSource.getConnection();
PreparedStatement statement = connection.prepareStatement(SELECT_TILE)) {
statement.setInt(1, tileCoord.z());
Expand All @@ -92,7 +92,7 @@ public ByteBuffer read(TileCoord tileCoord) throws TileStoreException {

/** {@inheritDoc} */
@Override
public void write(TileCoord tileCoord, ByteBuffer blob) throws TileStoreException {
public void put(TileCoord tileCoord, ByteBuffer blob) throws TileStoreException {
try (Connection connection = dataSource.getConnection();
PreparedStatement statement = connection.prepareStatement(INSERT_TILE)) {
statement.setInt(1, tileCoord.z());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ public PostgresTileStore(DataSource datasource, Tileset tileset) {

/** {@inheritDoc} */
@Override
public ByteBuffer read(TileCoord tileCoord) throws TileStoreException {
public ByteBuffer get(TileCoord tileCoord) throws TileStoreException {
try (Connection connection = datasource.getConnection();
Statement statement = connection.createStatement();
ByteArrayOutputStream data = new ByteArrayOutputStream()) {
Expand Down Expand Up @@ -239,7 +239,7 @@ protected String tileEnvelope(TileCoord tileCoord) {
}

/** This operation is not supported. */
public void write(TileCoord tileCoord, ByteBuffer blob) {
public void put(TileCoord tileCoord, ByteBuffer blob) {
throw new UnsupportedOperationException("The postgis tile store is read only");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,17 +87,7 @@ private TileStore targetTileStore(Tileset source) throws TileStoreException, IOE
if (mbtiles) {
Files.deleteIfExists(repository);

var sqliteConfig = new SQLiteConfig();
sqliteConfig.setCacheSize(1000000);
sqliteConfig.setPageSize(65536);
sqliteConfig.setJournalMode(JournalMode.OFF);
sqliteConfig.setLockingMode(LockingMode.EXCLUSIVE);
sqliteConfig.setSynchronous(SynchronousMode.OFF);
sqliteConfig.setTempStore(TempStore.MEMORY);

var sqliteDataSource = new SQLiteDataSource();
sqliteDataSource.setConfig(sqliteConfig);
sqliteDataSource.setUrl("jdbc:sqlite:" + repository);
var sqliteDataSource = createDataSource(repository);

var hikariConfig = new HikariConfig();
hikariConfig.setDataSource(sqliteDataSource);
Expand All @@ -114,6 +104,22 @@ private TileStore targetTileStore(Tileset source) throws TileStoreException, IOE
}
}

public static SQLiteDataSource createDataSource(Path path) {
var sqliteConfig = new SQLiteConfig();
sqliteConfig.setCacheSize(1000000);
sqliteConfig.setPageSize(65536);
sqliteConfig.setJournalMode(JournalMode.OFF);
sqliteConfig.setLockingMode(LockingMode.EXCLUSIVE);
sqliteConfig.setSynchronous(SynchronousMode.OFF);
sqliteConfig.setTempStore(TempStore.MEMORY);

var sqliteDataSource = new SQLiteDataSource();
sqliteDataSource.setConfig(sqliteConfig);
sqliteDataSource.setUrl("jdbc:sqlite:" + path);

return sqliteDataSource;
}

private Map<String, String> metadata(Tileset tileset) throws JsonProcessingException {
var metadata = new HashMap<String, String>();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,15 @@ void readWriteDeleteTile() throws Exception {
ByteBuffer blob = ByteBuffer.wrap("tile_content".getBytes());

// Write data
tileStore.write(tileCoord, blob);
tileStore.put(tileCoord, blob);

// Read the data
ByteBuffer inputStream = tileStore.read(tileCoord);
ByteBuffer inputStream = tileStore.get(tileCoord);
assertArrayEquals(blob.array(), inputStream.array());

// Delete the data
tileStore.delete(tileCoord);
assertThrows(TileStoreException.class, () -> tileStore.read(tileCoord));
assertThrows(TileStoreException.class, () -> tileStore.get(tileCoord));
}

public abstract TileStore createTileStore() throws Exception;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ public Response getTile(String tileSetId, String tileMatrix, Integer tileRow, In
int y = tileCol;
TileCoord tileCoord = new TileCoord(x, y, z);
try {
ByteBuffer blob = tileStore.read(tileCoord);
ByteBuffer blob = tileStore.get(tileCoord);
if (blob != null) {
return Response.status(200) // lgtm [java/xss]
.header(ACCESS_CONTROL_ALLOW_ORIGIN, "*")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ public Response getTile(@PathParam("z") int z, @PathParam("x") int x, @PathParam
var tileStore = new PostgresTileStore(dataSource,
objectMapper.readValue(configReader.read(tileset), Tileset.class));
var tileCoord = new TileCoord(x, y, z);
var blob = tileStore.read(tileCoord);
var blob = tileStore.get(tileCoord);
if (blob != null) {
return Response.status(200)
.header(CONTENT_TYPE, TILE_TYPE)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public TileJSON getTileset() {
public Response getTile(@PathParam("z") int z, @PathParam("x") int x, @PathParam("y") int y) {
TileCoord tileCoord = new TileCoord(x, y, z);
try {
ByteBuffer blob = tileStore.read(tileCoord);
ByteBuffer blob = tileStore.get(tileCoord);
if (blob != null) {
byte[] bytes = new byte[blob.remaining()];
blob.get(bytes);
Expand Down

0 comments on commit 7cf110e

Please sign in to comment.