Skip to content

Instantly share code, notes, and snippets.

@gdela
Last active July 10, 2019 17:04
Show Gist options
  • Save gdela/9fe6bb38efcf7c4e1b847655cd9d6246 to your computer and use it in GitHub Desktop.
Save gdela/9fe6bb38efcf7c4e1b847655cd9d6246 to your computer and use it in GitHub Desktop.
Benchmark used for improving performance of committing transaction in Hazelcast: https://github.com/hazelcast/hazelcast/issues/15301
/*
* Copyright (c) 2008-2019, Hazelcast, Inc. All Rights Reserved.
*
* 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 com.hazelcast.transaction.impl;
import com.hazelcast.config.Config;
import com.hazelcast.core.Hazelcast;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.core.TransactionalMap;
import com.hazelcast.nio.ObjectDataInput;
import com.hazelcast.nio.ObjectDataOutput;
import com.hazelcast.nio.serialization.DataSerializable;
import com.hazelcast.partition.PartitionAware;
import com.hazelcast.transaction.TransactionContext;
import com.hazelcast.transaction.TransactionOptions;
import java.io.IOException;
import java.util.Map;
import java.util.Objects;
import java.util.TreeMap;
import static com.hazelcast.transaction.TransactionOptions.TransactionType.TWO_PHASE;
import static java.lang.System.nanoTime;
import static java.util.concurrent.TimeUnit.MINUTES;
public class MyTransactionCommitMain {
private HazelcastInstance instance;
private Map<Integer, Double> measurements = new TreeMap<>();
public static void main(String[] args) throws Exception {
MyTransactionCommitMain main = new MyTransactionCommitMain();
main.setup();
try {
main.performTransaction(1);
main.performTransaction(10);
main.performTransaction(100);
main.performTransaction(1000);
main.performTransaction(10000);
main.performTransaction(20000);
main.performTransaction(40000);
//commented out, as these are really slow
//main.performTransaction(80000);
//main.performTransaction(160000);
} finally {
main.tearDown();
}
System.out.println("Times it took to commit:");
main.measurements.forEach((numOfEntries, timeTaken) -> {
System.out.printf("%7d entries - %7.3f seconds%n", numOfEntries, timeTaken);
});
}
public void setup() throws InterruptedException {
Config config = new Config();
instance = Hazelcast.newHazelcastInstance(config);
instance.getMap("map");
}
public void tearDown() {
Hazelcast.shutdownAll();
}
private TransactionOptions options() {
return new TransactionOptions()
.setTransactionType(TWO_PHASE)
.setDurability(2)
.setTimeout(30, MINUTES);
}
private void performTransaction(int numOfEntries) {
System.out.printf("measuring commit of %d entries...%n", numOfEntries);
TransactionContext context = instance.newTransactionContext(options());
context.beginTransaction();
TransactionalMap<Key, Pojo> txMap = context.getMap("map");
String partitionKey = "xxx"; // all objects will be in same partition
for (int id = 0; id < numOfEntries; id++) {
txMap.put(new Key(id, partitionKey), new Pojo("dummy nr "+id));
}
long startTime = nanoTime();
context.commitTransaction();
long endTime = nanoTime();
double timeTakenInSeconds = (endTime - startTime) / 1000.0 / 1000.0 / 1000.0;
System.out.printf("commit of %d entries %.3f took seconds%n", numOfEntries, timeTakenInSeconds);
measurements.put(numOfEntries, timeTakenInSeconds);
}
@SuppressWarnings("all")
public static class Key implements PartitionAware<String>, DataSerializable {
private long id;
private String partitionKey;
public Key() {}
public Key(long id, String partitionKey) {
this.id = id;
this.partitionKey = partitionKey;
}
@Override
public String getPartitionKey() {
return partitionKey;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Key key = (Key) o;
return id == key.id && partitionKey.equals(key.partitionKey);
}
@Override
public int hashCode() {
return Objects.hash(id, partitionKey);
}
@Override
public void writeData(ObjectDataOutput out) throws IOException {
out.writeLong(id);
out.writeUTF(partitionKey);
}
@Override
public void readData(ObjectDataInput in) throws IOException {
id = in.readLong();
partitionKey = in.readUTF();
}
}
@SuppressWarnings("all")
public static class Pojo implements DataSerializable {
public String value;
public Pojo() {}
public Pojo(String value) {
this.value = value;
}
@Override
public void writeData(ObjectDataOutput out) throws IOException {
out.writeUTF(value);
}
@Override
public void readData(ObjectDataInput in) throws IOException {
value = in.readUTF();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment