added benchmark and renamed packages

This commit is contained in:
Shautvast 2023-08-22 14:38:38 +02:00
parent f61a1e672d
commit f7f999bd53
56 changed files with 873 additions and 136 deletions

View file

@ -9,3 +9,7 @@
* Still in a very early stage
* the code is working
* but it remains to be seen if this is a good idea
-javaagent:/Users/Shautvast/dev/perfix/target/perfix-agent-0.1-SNAPSHOT.jar
-Dperfix.includes=nl.sanderhautvast.contiguous

102
benchmark/pom.xml Normal file
View file

@ -0,0 +1,102 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.github.shautvast</groupId>
<artifactId>contiguous-pom</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>benchmark</artifactId>
<properties>
<maven.compiler.source>20</maven.compiler.source>
<maven.compiler.target>20</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.github.shautvast</groupId>
<artifactId>contiguous-jdbc</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.github.shautvast</groupId>
<artifactId>contiguous-jackson</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<version>1.36</version>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>1.36</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<compilerVersion>9</compilerVersion>
<source>9</source>
<target>9</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<finalName>benchmark</finalName>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>org.openjdk.jmh.Main</mainClass>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
</transformers>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View file

@ -0,0 +1,20 @@
package com.github.shautvast.contiguous.benchmark;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/* copied from demo, need common module */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Customer {
String name;
String email;
String streetname;
int housenumber;
String city;
String country;
}

View file

@ -0,0 +1,63 @@
package com.github.shautvast.contiguous.benchmark;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.github.shautvast.contiguous.ContiguousList;
import com.github.shautvast.contiguous.ListSerializer;
import org.openjdk.jmh.annotations.*;
import java.util.*;
import java.util.concurrent.TimeUnit;
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Fork(value = 1)
public class JmhBenchmark {
@org.openjdk.jmh.annotations.State(Scope.Benchmark)
public static class State {
//mimick database
final List<Customer> customers = new ArrayList<>();
final ObjectMapper jacksonMapper = new ObjectMapper();
@Setup()
public void setup() {
final SimpleModule contiguousListModule = new SimpleModule("contiguous_module");
contiguousListModule.addSerializer(new ListSerializer());
jacksonMapper.registerModule(contiguousListModule);
final RandomStuffGenerator generator = new RandomStuffGenerator();
for (int i = 0; i < 10_000; i++) {
Customer customer = new Customer();
String firstName = generator.generateFirstName();
String lastName = generator.generateLastName();
customer.name = firstName + " " + lastName;
customer.email = firstName + "." + lastName + "@icemail.com";
customer.streetname = generator.generateStreetName();
customer.housenumber = generator.generateSomeNumber();
customer.city = generator.generateSomeCityInIceland();
customer.country = generator.generateIceland();
customers.add(customer);
}
}
}
@Benchmark
public String contiguous(State state) throws JsonProcessingException {
//naive mimick read from database and add to ContiguousList
ContiguousList<Customer> customers = new ContiguousList<>(Customer.class);
customers.addAll(state.customers);
return state.jacksonMapper.writeValueAsString(customers);
}
@Benchmark
public String classic(State state) throws JsonProcessingException {
//naive mimick read from database and add to ArrayList
List<Customer> customers = new ArrayList<>();
customers.addAll(state.customers);
return state.jacksonMapper.writeValueAsString(customers);
}
}

View file

@ -0,0 +1,55 @@
package com.github.shautvast.contiguous.benchmark;
import java.util.List;
import java.util.Random;
/* Duplicate from demo */
public class RandomStuffGenerator {
private final List<String> firstNameParts = List.of("sa", "ka", "zo", "ja", "za", "ka", "po", "ji", "ne", "si", "wi", "ha", "ut", "va", "no", "bo"
, "jo", "fe", "gu");
private final List<String> lastNameParts = List.of("fin", "wil", "cat", "loc", "der", "ter", "asp", "pen", "ill", "raf", "gut", "dax", "yin");
private final List<String> cities = List.of("Reykjavík", "Kópavogur", "Hafnarfjörður", "Akureyri", "Reykjanesbær", "Garðabær", "Mosfellsbær", "Selfoss", "Akranes", "Seltjarnarnes", "Vestmannaeyjar", "Grindavík", "Ísafjörður", "Álftanes", "Sauðárkrókur", "Hveragerði", "Egilsstaðir", "Húsavík", "Borgarnes", "Sandgerði", "Höfn", "Þorlákshöfn", "Garður", "Neskaupstaður", "Dalvík", "Reyðarfjörður", "Siglufjörður", "Vogar", "Stykkishólmur", "Eskifjörður", "Ólafsvík", "Hvolsvöllur", "Bolungarvík", "Hella", "Grundarfjörður", "Blönduós", "Ólafsfjörður", "Fáskrúðsfjörður", "Patreksfjörður", "Seyðisfjörður", "Grundarhverfi", "Hvammstangi", "Stokkseyri", "Eyrarbakki", "Vopnafjörður", "Skagaströnd", "Flúðir", "Vík", "Fellabær", "Hellissandur", "Djúpivogur", "Þórshöfn", "Svalbarðseyri", "Hólmavík", "Grenivík", "Hvanneyri", "Þingeyri", "Búðardalur", "Reykholt", "Hrafnagil", "Suðureyri", "Tálknafjörður", "Bíldudalur", "Mosfellsdalur", "Hnífsdalur", "Reykjahlíð", "Laugarvatn", "Raufarhöfn", "Stöðvarfjörður", "Bifröst", "Flateyri", "Kirkjubæjarklaustur", "Súðavík", "Hrísey", "Hofsós", "Breiðdalsvík", "Rif", "Reykhólar", "Varmahlíð", "Kópasker", "Laugarás", "Borg", "Hauganes", "Hafnir", "Laugar", "Melahverfi", "Tjarnabyggð", "Árskógssandur", "Lónsbakki", "Hólar", "Nesjahverfi", "Sólheimar", "Brúnahlíð", "Drangsnes", "Borgarfjörður eystri", "Árbæjarhverfi", "Brautarholt", "Rauðalækur", "Bakkafjörður", "Innnes", "Grímsey", "Þykkvabær", "Laugarbakki", "Reykholt", "Árnes", "Kristnes", "Kleppjárnsreykir");
private final Random random = new Random();
public String generateFirstName() {
return generateName(firstNameParts);
}
public String generateLastName() {
return generateName(lastNameParts);
}
public String generateStreetName() {
StringBuilder name = new StringBuilder();
int nLastNameParts = random.nextInt(5) + 1;
for (int i = 0; i < nLastNameParts; i++) {
name.append(firstNameParts.get(random.nextInt(firstNameParts.size())));
name.append(lastNameParts.get(random.nextInt(lastNameParts.size())));
}
name.append("götu");
return name.toString();
}
public int generateSomeNumber() {
return random.nextInt(1000);
}
public String generateSomeCityInIceland() {
return cities.get(random.nextInt(cities.size()));
}
public String generateIceland() {
return "Iceland"; // meant to be humorous
}
private String generateName(List<String> parts) {
StringBuilder name = new StringBuilder();
int size = random.nextInt(2) + 2;
for (int i = 0; i < size; i++) {
name.append(parts.get(random.nextInt(parts.size())));
}
return name.toString();
}
}

View file

@ -4,7 +4,7 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>nl.sanderhautvast</groupId>
<groupId>com.github.shautvast</groupId>
<artifactId>contiguous-pom</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
@ -21,12 +21,12 @@
<dependencies>
<dependency>
<groupId>nl.sanderhautvast</groupId>
<groupId>com.github.shautvast</groupId>
<artifactId>contiguous-jdbc</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>nl.sanderhautvast</groupId>
<groupId>com.github.shautvast</groupId>
<artifactId>contiguous-jackson</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
@ -66,7 +66,8 @@
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.7.12</version>
<configuration>
<mainClass>nl.sanderhautvast.contiguous.demo.DemoApplication</mainClass>
<mainClass>com.github.shautvast.contiguous.demo.DemoApplication</mainClass>
</configuration>
</plugin>
</plugins>

View file

@ -1,10 +1,10 @@
package nl.sanderhautvast.contiguous.demo;
package com.github.shautvast.contiguous.demo;
import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.databind.module.SimpleModule;
import lombok.extern.slf4j.Slf4j;
import nl.sanderhautvast.contiguous.ListSerializer;
import nl.sanderhautvast.contiguous.demo.repository.RandomStuffGenerator;
import com.github.shautvast.contiguous.ListSerializer;
import com.github.shautvast.contiguous.demo.repository.RandomStuffGenerator;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;

View file

@ -1,4 +1,4 @@
package nl.sanderhautvast.contiguous.demo.model;
package com.github.shautvast.contiguous.demo.model;
import lombok.AllArgsConstructor;
import lombok.Builder;

View file

@ -1,10 +1,10 @@
package nl.sanderhautvast.contiguous.demo.repository;
package com.github.shautvast.contiguous.demo.repository;
import com.github.shautvast.contiguous.ContiguousList;
import com.github.shautvast.contiguous.JdbcResults;
import com.github.shautvast.contiguous.demo.model.Customer;
import lombok.extern.slf4j.Slf4j;
import nl.sanderhautvast.contiguous.ContiguousList;
import nl.sanderhautvast.contiguous.JdbcResults;
import nl.sanderhautvast.contiguous.demo.model.Customer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

View file

@ -1,4 +1,4 @@
package nl.sanderhautvast.contiguous.demo.repository;
package com.github.shautvast.contiguous.demo.repository;
import java.util.List;
import java.util.Random;

View file

@ -1,9 +1,9 @@
package nl.sanderhautvast.contiguous.demo.rest;
package com.github.shautvast.contiguous.demo.rest;
import com.github.shautvast.contiguous.ContiguousList;
import lombok.extern.slf4j.Slf4j;
import nl.sanderhautvast.contiguous.ContiguousList;
import nl.sanderhautvast.contiguous.demo.model.Customer;
import nl.sanderhautvast.contiguous.demo.repository.CustomerRepository;
import com.github.shautvast.contiguous.demo.model.Customer;
import com.github.shautvast.contiguous.demo.repository.CustomerRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@ -23,7 +23,12 @@ public class DemoRestApi {
@GetMapping(value = "/api/customers", produces = "application/json")
public ContiguousList<Customer> getCustomers() {
return customerRepository.getAllCustomers();
try {
return customerRepository.getAllCustomers();
} catch (Exception e) {
log.error("",e);
throw e;
}
}
@GetMapping(value = "/api/customers/traditional", produces = "application/json")
@ -35,4 +40,5 @@ public class DemoRestApi {
public List<Customer> getCustomersHybrid() {
return customerRepository.getAllCustomersHybrid();
}
}

View file

@ -4,7 +4,7 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>nl.sanderhautvast</groupId>
<groupId>com.github.shautvast</groupId>
<artifactId>contiguous-pom</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
@ -23,7 +23,7 @@
<dependencies>
<dependency>
<groupId>nl.sanderhautvast</groupId>
<groupId>com.github.shautvast</groupId>
<artifactId>contiguous</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>

View file

@ -1,4 +1,4 @@
package nl.sanderhautvast.contiguous;
package com.github.shautvast.contiguous;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
@ -7,9 +7,9 @@ import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import java.io.IOException;
import java.util.Iterator;
public class ListSerializer<E> extends StdSerializer<ContiguousList<?>> {
public class ListSerializer extends StdSerializer<ContiguousList<?>> {
@SuppressWarnings("unchecked")
@SuppressWarnings({"unchecked", "rawtypes"})
public ListSerializer() {
super((Class) ContiguousList.class); // ?
}
@ -26,6 +26,7 @@ public class ListSerializer<E> extends StdSerializer<ContiguousList<?>> {
}
generator.writeEndArray();
clist.close();
}
}

View file

@ -1,4 +1,4 @@
package nl.sanderhautvast.contiguous;
package com.github.shautvast.contiguous;
public class AdamsObject {
private String name;

View file

@ -1,4 +1,4 @@
package nl.sanderhautvast.contiguous;
package com.github.shautvast.contiguous;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
@ -17,7 +17,7 @@ class ListSerializerTest {
public void setup(){
mapper = new ObjectMapper();
final SimpleModule module = new SimpleModule("mySerializers");
module.addSerializer(new ListSerializer<>());
module.addSerializer(new ListSerializer());
mapper.registerModule(module);
}
@Test

View file

@ -4,7 +4,7 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>nl.sanderhautvast</groupId>
<groupId>com.github.shautvast</groupId>
<artifactId>contiguous-pom</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
@ -23,7 +23,7 @@
<dependencies>
<dependency>
<groupId>nl.sanderhautvast</groupId>
<groupId>com.github.shautvast</groupId>
<artifactId>contiguous</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>

View file

@ -1,4 +1,4 @@
package nl.sanderhautvast.contiguous;
package com.github.shautvast.contiguous;
import java.sql.ResultSet;
import java.sql.SQLException;

View file

@ -1,6 +1,5 @@
package nl.sanderhautvast.contiguous;
package com.github.shautvast.contiguous;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;

View file

@ -1,4 +1,4 @@
package nl.sanderhautvast.contiguous;
package com.github.shautvast.contiguous;
import lombok.AllArgsConstructor;
import lombok.Data;

View file

@ -1,4 +1,4 @@
package nl.sanderhautvast.contiguous;
package com.github.shautvast.contiguous;
import lombok.AllArgsConstructor;
import lombok.Data;

View file

@ -16,17 +16,17 @@
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
<boolProp name="LoopController.continue_forever">false</boolProp>
<stringProp name="LoopController.loops">100</stringProp>
<stringProp name="LoopController.loops">1000</stringProp>
</elementProp>
<stringProp name="ThreadGroup.num_threads">1</stringProp>
<stringProp name="ThreadGroup.ramp_time">1</stringProp>
<stringProp name="ThreadGroup.num_threads">3</stringProp>
<stringProp name="ThreadGroup.ramp_time">10</stringProp>
<boolProp name="ThreadGroup.scheduler">false</boolProp>
<stringProp name="ThreadGroup.duration"></stringProp>
<stringProp name="ThreadGroup.delay"></stringProp>
<boolProp name="ThreadGroup.same_user_on_next_iteration">true</boolProp>
</ThreadGroup>
<hashTree>
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="contiguous" enabled="false">
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="contiguous" enabled="true">
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
@ -34,7 +34,7 @@
<stringProp name="HTTPSampler.port">8080</stringProp>
<stringProp name="HTTPSampler.protocol">http</stringProp>
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
<stringProp name="HTTPSampler.path">/api/customers</stringProp>
<stringProp name="HTTPSampler.path">/api/customers/streamon</stringProp>
<stringProp name="HTTPSampler.method">GET</stringProp>
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
@ -45,7 +45,7 @@
<stringProp name="HTTPSampler.response_timeout"></stringProp>
</HTTPSamplerProxy>
<hashTree/>
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="traditional" enabled="true">
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="traditional" enabled="false">
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
@ -83,6 +83,49 @@
<stringProp name="HTTPSampler.response_timeout"></stringProp>
</HTTPSamplerProxy>
<hashTree/>
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="toy" enabled="false">
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
<stringProp name="HTTPSampler.domain">localhost</stringProp>
<stringProp name="HTTPSampler.port">8080</stringProp>
<stringProp name="HTTPSampler.protocol">http</stringProp>
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
<stringProp name="HTTPSampler.path">api/customers/toy</stringProp>
<stringProp name="HTTPSampler.method">GET</stringProp>
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
<stringProp name="HTTPSampler.response_timeout"></stringProp>
</HTTPSamplerProxy>
<hashTree/>
<UniformRandomTimer guiclass="UniformRandomTimerGui" testclass="UniformRandomTimer" testname="Uniform Random Timer" enabled="true">
<stringProp name="ConstantTimer.delay">0</stringProp>
<stringProp name="RandomTimer.range">100.0</stringProp>
</UniformRandomTimer>
<hashTree/>
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="streamon" enabled="false">
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
<stringProp name="HTTPSampler.domain">localhost</stringProp>
<stringProp name="HTTPSampler.port">8080</stringProp>
<stringProp name="HTTPSampler.protocol">http</stringProp>
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
<stringProp name="HTTPSampler.path">/api/customers/streamon2</stringProp>
<stringProp name="HTTPSampler.method">GET</stringProp>
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
<stringProp name="HTTPSampler.response_timeout"></stringProp>
</HTTPSamplerProxy>
<hashTree/>
</hashTree>
<ResultCollector guiclass="StatVisualizer" testclass="ResultCollector" testname="Aggregate Report" enabled="true">
<boolProp name="ResultCollector.error_logging">false</boolProp>

View file

@ -5,7 +5,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>nl.sanderhautvast</groupId>
<groupId>com.github.shautvast</groupId>
<artifactId>contiguous-pom</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
@ -16,8 +16,8 @@
<packaging>jar</packaging>
<properties>
<maven.compiler.source>9</maven.compiler.source>
<maven.compiler.target>9</maven.compiler.target>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>

View file

@ -1,4 +1,4 @@
package nl.sanderhautvast.contiguous;
package com.github.shautvast.contiguous;
import java.lang.invoke.MethodHandle;
import java.math.BigDecimal;

View file

@ -1,4 +1,4 @@
package nl.sanderhautvast.contiguous;
package com.github.shautvast.contiguous;
import java.lang.invoke.MethodHandle;
import java.math.BigInteger;

View file

@ -0,0 +1,24 @@
package com.github.shautvast.contiguous;
import java.lang.ref.SoftReference;
import java.nio.ByteBuffer;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
/**
* Boundless cache something
*/
class BufferCache {
private static final ConcurrentHashMap<Integer, ByteBuffer> cache = new ConcurrentHashMap<>();
static ByteBuffer get(int size) {
ByteBuffer byteBuffer = Optional.ofNullable(cache.get(size)).orElseGet(() -> ByteBuffer.allocate(size));
byteBuffer.position(0);
return byteBuffer;
}
static void release(ByteBuffer byteBuffer) {
cache.put(byteBuffer.capacity(), byteBuffer);
}
}

View file

@ -1,4 +1,4 @@
package nl.sanderhautvast.contiguous;
package com.github.shautvast.contiguous;
import java.lang.invoke.MethodHandle;
@ -11,7 +11,7 @@ import java.lang.invoke.MethodHandle;
* of the bean that it needs to call 'runtime' (after instantiation of the list),
* ie. when a bean is added or retrieved from the list
*/
public abstract class BuiltinTypeHandler<T> extends TypeHandler {
abstract class BuiltinTypeHandler<T> extends TypeHandler {
public BuiltinTypeHandler(Class<?> type, String name, MethodHandle getter, MethodHandle setter) {
super(type, name, getter, setter);
}

View file

@ -1,4 +1,4 @@
package nl.sanderhautvast.contiguous;
package com.github.shautvast.contiguous;
import java.lang.invoke.MethodHandle;

View file

@ -1,4 +1,4 @@
package nl.sanderhautvast.contiguous;
package com.github.shautvast.contiguous;
import java.lang.reflect.Field;
import java.util.*;

View file

@ -1,4 +1,4 @@
package nl.sanderhautvast.contiguous;
package com.github.shautvast.contiguous;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
@ -56,22 +56,27 @@ public class ContiguousList<E> extends NotImplementedList<E> implements List<E>
/*
* storage for dehydated objects
*/
private ByteBuffer data = ByteBuffer.allocate(4096);//TODO create constructor with capacity
private ByteBuffer data = BufferCache.get(4096);
private int bufferPosition;
private ArrayList<Integer> elementIndices = new ArrayList<>(); // avoids autoboxing. Could also use standard ArrayList though
private final ArrayList<Integer> elementIndices = new ArrayList<>(); // avoids autoboxing. Could also use standard ArrayList though
// is there a standard lib IntList??
private int size;
private TypeHandler rootHandler;
private final TypeHandler rootHandler;
private static final Map<Class<?>, TypeHandler> TYPE_HANDLERS = new HashMap<>();
public ContiguousList(Class<E> type) {
inspectType(type);
this.rootHandler = inspectType(type);
elementIndices.add(0); // index of first element
}
public void close(){
BufferCache.release(this.data);
}
/*
* Get a list of setters and getters to execute later on to get/set the values of the object
*
@ -80,25 +85,22 @@ public class ContiguousList<E> extends NotImplementedList<E> implements List<E>
* The advantage of the current implementation is that the binary data is not aware of the actual
* object graph. It only knows the 'primitive' values.
*/
private void inspectType(Class<?> elementClass) {
if (PropertyHandlerFactory.isBuiltInType(elementClass)) {
this.rootHandler = PropertyHandlerFactory.forType(elementClass);
} else {
CompoundTypeHandler compoundType = new CompoundTypeHandler(elementClass);
this.rootHandler = compoundType;
try {
addPropertyHandlersForCompoundType(elementClass, compoundType);
} catch (IllegalAccessException e) {
throw new IllegalStateException(e);
}
}
private TypeHandler inspectType(Class<?> elementClass) {
return TYPE_HANDLERS.computeIfAbsent(elementClass, k ->
PropertyHandlerFactory.forType(elementClass)
.orElseGet(() -> {
TypeHandler compoundTypeHandler = new CompoundTypeHandler(elementClass);
addPropertyHandlersForCompoundType(elementClass, (CompoundTypeHandler) compoundTypeHandler);
return compoundTypeHandler;
})
);
}
/*
* using reflection find all properties in the element, recursing down when the property is compound
*/
private void addPropertyHandlersForCompoundType(Class<?> type, CompoundTypeHandler parentCompoundType) throws IllegalAccessException {
final MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(type, MethodHandles.lookup());
private void addPropertyHandlersForCompoundType(Class<?> type, CompoundTypeHandler parentCompoundType) {
final MethodHandles.Lookup lookup = getLookup(type);
Arrays.stream(type.getDeclaredFields())
.forEach(field -> {
try {
@ -106,18 +108,16 @@ public class ContiguousList<E> extends NotImplementedList<E> implements List<E>
MethodHandle getter = lookup.findGetter(type, field.getName(), fieldType);
MethodHandle setter = lookup.findSetter(type, field.getName(), fieldType);
if (PropertyHandlerFactory.isBuiltInType(fieldType)) {
BuiltinTypeHandler<?> primitiveType =
PropertyHandlerFactory.forType(fieldType, field.getName(), getter, setter);
parentCompoundType.addHandler(field.getName(), primitiveType);
Optional<TypeHandler> typeHandler = PropertyHandlerFactory.forType(fieldType, field.getName(), getter, setter);
if (typeHandler.isPresent()) {
parentCompoundType.addHandler(field.getName(), (BuiltinTypeHandler<?>) typeHandler.get());
} else {
CompoundTypeHandler newParent = new CompoundTypeHandler(fieldType, field.getName());
newParent.setGetter(getter);
newParent.setSetter(setter);
parentCompoundType.addChild(field, newParent);
CompoundTypeHandler handler = new CompoundTypeHandler(fieldType, field.getName());
handler.setGetter(getter);
handler.setSetter(setter);
parentCompoundType.addChild(field, handler);
addPropertyHandlersForCompoundType(fieldType, newParent);
addPropertyHandlersForCompoundType(fieldType, handler);
}
} catch (Exception e) {
throw new RuntimeException(e);
@ -125,6 +125,14 @@ public class ContiguousList<E> extends NotImplementedList<E> implements List<E>
});
}
private static MethodHandles.Lookup getLookup(Class<?> type) {
try {
return MethodHandles.privateLookupIn(type, MethodHandles.lookup());
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
@Override
@SuppressWarnings("Contract")
public boolean add(E element) {
@ -270,7 +278,6 @@ public class ContiguousList<E> extends NotImplementedList<E> implements List<E>
}
data.position(elementIndices.get(index));
if (rootHandler instanceof BuiltinTypeHandler<?>) {
BuiltinTypeHandler<?> handler = (BuiltinTypeHandler<?>) rootHandler;
return getValue(handler);
}
@ -280,16 +287,14 @@ public class ContiguousList<E> extends NotImplementedList<E> implements List<E>
copyDataIntoStringBuilder(s, (CompoundTypeHandler) rootHandler);
s.append("}");
return s.toString();
}
private String getValue(BuiltinTypeHandler<?> handler) {
Object read = ValueReader.read(data);
String out = handler.cast(read).toString();
String value = String.valueOf(ValueReader.read(data));
if (handler instanceof StringHandler) {
out = quote(out);
return quote(value);
}
return out;
return value;
}
private static String quote(String out) {
@ -305,8 +310,9 @@ public class ContiguousList<E> extends NotImplementedList<E> implements List<E>
compoundType.getProperties().forEach(property -> {
if (property instanceof BuiltinTypeHandler) {
BuiltinTypeHandler<?> typeHandler = (BuiltinTypeHandler<?>) property;
s.append(quote(typeHandler.getName()))
.append(": ")
s.append("\"")
.append(typeHandler.getName())
.append("\": ")
.append(getValue(typeHandler));
} else {
CompoundTypeHandler p = (CompoundTypeHandler) property;
@ -608,8 +614,9 @@ public class ContiguousList<E> extends NotImplementedList<E> implements List<E>
private void ensureFree(int length) {
while (bufferPosition + length > data.capacity()) {
byte[] bytes = this.data.array();
this.data = ByteBuffer.allocate(this.data.capacity() * 2);
ByteBuffer bytes = this.data;
BufferCache.release(this.data);
this.data = BufferCache.get((int)(bytes.capacity() * 1.5));
this.data.put(bytes);
}
}

View file

@ -1,4 +1,4 @@
package nl.sanderhautvast.contiguous;
package com.github.shautvast.contiguous;
import java.lang.invoke.MethodHandle;

View file

@ -1,4 +1,4 @@
package nl.sanderhautvast.contiguous;
package com.github.shautvast.contiguous;
import java.lang.invoke.MethodHandle;

View file

@ -1,4 +1,4 @@
package nl.sanderhautvast.contiguous;
package com.github.shautvast.contiguous;
import java.lang.invoke.MethodHandle;

View file

@ -1,4 +1,4 @@
package nl.sanderhautvast.contiguous;
package com.github.shautvast.contiguous;
import java.lang.invoke.MethodHandle;

View file

@ -1,4 +1,4 @@
package nl.sanderhautvast.contiguous;
package com.github.shautvast.contiguous;
import java.util.*;
import java.util.function.UnaryOperator;

View file

@ -1,17 +1,16 @@
package nl.sanderhautvast.contiguous;
package com.github.shautvast.contiguous;
import java.lang.invoke.MethodHandle;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;
import java.util.*;
/*
* Maps the propertyvalue type to a PropertyHandler
*/
final class PropertyHandlerFactory {
private static final Map<Class<?>, Class<? extends BuiltinTypeHandler<?>>> TYPE_HANDLERS = new HashMap<>();
private static final Map<Class<?>, Class<? extends BuiltinTypeHandler<?>>> BUILTIN = new HashMap<>();
private PropertyHandlerFactory() {
}
@ -35,27 +34,23 @@ final class PropertyHandlerFactory {
register(BigDecimal.class, BigDecimalHandler.class);
//Date/Timestamp
//LocalDate/time
}
public static boolean isBuiltInType(Class<?> type) {
return TYPE_HANDLERS.containsKey(type);
}
public static <T> BuiltinTypeHandler<T> forType(Class<T> type, String name, MethodHandle getter, MethodHandle setter) {
try {
Class<? extends BuiltinTypeHandler<?>> appenderClass = TYPE_HANDLERS.get(type);
if (appenderClass == null) {
throw new IllegalStateException("No Handler for " + type.getName());
@SuppressWarnings("unchecked")
public static <T> Optional<TypeHandler> forType(Class<T> type, String name, MethodHandle getter, MethodHandle setter) {
return Optional.ofNullable(BUILTIN.get(type)).map(appenderClass -> {
try {
return (BuiltinTypeHandler<T>) appenderClass.getDeclaredConstructor(String.class, MethodHandle.class, MethodHandle.class)
.newInstance(name, getter, setter);
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException |
InvocationTargetException e) {
throw new IllegalStateException(e);
}
return (BuiltinTypeHandler<T>) appenderClass.getDeclaredConstructor(String.class, MethodHandle.class, MethodHandle.class)
.newInstance(name, getter, setter);
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException |
InvocationTargetException e) {
throw new IllegalStateException(e);
}
});
}
public static <T> BuiltinTypeHandler<T> forType(Class<T> type) {
public static <T> Optional<TypeHandler> forType(Class<T> type) {
return forType(type, null, null, null);
}
@ -63,6 +58,6 @@ final class PropertyHandlerFactory {
* register a new TypeHandler that cannot be derived from bean properties
*/
public static void register(Class<?> type, Class<? extends BuiltinTypeHandler<?>> typehandler) {
TYPE_HANDLERS.put(type, typehandler);
BUILTIN.put(type, typehandler);
}
}

View file

@ -1,4 +1,4 @@
package nl.sanderhautvast.contiguous;
package com.github.shautvast.contiguous;
import java.lang.invoke.MethodHandle;

View file

@ -1,4 +1,4 @@
package nl.sanderhautvast.contiguous;
package com.github.shautvast.contiguous;
import java.lang.invoke.MethodHandle;

View file

@ -1,9 +1,9 @@
package nl.sanderhautvast.contiguous;
package com.github.shautvast.contiguous;
import java.lang.invoke.MethodHandle;
/**
* Abstract basertype over handlers for 'primitives' (ie. long, but also Long,
* Abstract basetype over handlers for 'primitives' (ie. long, but also Long,
* String..=> built-in types) and compound types (your own).
* Common ancestor primarily to iterator over properties of any type.
* The respective functions are completely different though, and we need `instanceof` to check for the

View file

@ -1,4 +1,4 @@
package nl.sanderhautvast.contiguous;
package com.github.shautvast.contiguous;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
@ -8,7 +8,7 @@ import java.nio.charset.StandardCharsets;
* the layout is SQLite-like type:Varint, value byte[]
* Varint: byte[]
*/
class ValueReader {
public class ValueReader {
/**
* Reads a value from the buffer.

View file

@ -1,4 +1,4 @@
package nl.sanderhautvast.contiguous;
package com.github.shautvast.contiguous;
import java.nio.ByteBuffer;
@ -6,7 +6,7 @@ import java.nio.ByteBuffer;
* Writes integers to byte representation like Sqlite's putVarint64
* not threadsafe (take out B8 and B9 if you need that)
*/
final class Varint {
public final class Varint {
private Varint() {
}

View file

@ -0,0 +1,147 @@
package com.github.shautvast.contiguous.asm;
import com.github.shautvast.contiguous.ValueReader;
import com.github.shautvast.contiguous.Varint;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
public class AsmContiguousList<E> {
private static final byte[] DOUBLE_TYPE = {7};
private static final byte[] FLOAT_TYPE = {10}; // not in line with SQLite anymore
private static final int STRING_OFFSET = 13;
private static final int BYTES_OFFSET = 12; // blob TODO decide if include
public static final int MAX_24BITS = 8388607;
public static final long MAX_48BITS = 140737488355327L;
/*
* storage for dehydrated objects
*/
private ByteBuffer data = ByteBuffer.allocate(4096);//TODO create constructor with capacity
private int bufferPosition;
private final ArrayList<Integer> elementIndices = new ArrayList<>();
private int size;
private final AsmTypeHandler<?> rootHandler;
// private static final Map<Class<?>, TypeHandler> TYPE_HANDLERS = new HashMap<>();
public AsmContiguousList(Class<E> elementType) {
this.rootHandler = new StringHandler();
elementIndices.add(0); // index of first element
bufferPosition = 0;
}
public boolean add(E element) {
if (element == null) {
return false;
}
storePropertyData(element, rootHandler);
extend();
return true;
}
@SuppressWarnings("unchecked")
public E get(int index) {
checkbounds(index);
data.position(elementIndices.get(index));
Object read = ValueReader.read(data);
return (E) rootHandler.cast(read);
// create a new instance of the list element type
}
public String getAsJson(int index) {
checkbounds(index);
data.position(elementIndices.get(index));
if (rootHandler instanceof BuiltinHandler<?>) {
return getValue(rootHandler);
}
return null;
}
private void checkbounds(int index) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException("index <0 or >" + size);
}
}
private String getValue(AsmTypeHandler<?> handler) {
String value = String.valueOf(ValueReader.read(data));
if (handler instanceof BuiltinHandler<?>) {
return quote(value);
}
return value;
}
public int size() {
return size;
}
public boolean isEmpty() {
return size == 0;
}
private void storePropertyData(Object element, AsmTypeHandler<?> typeHandler) {
if (typeHandler instanceof BuiltinHandler<?>) {
typeHandler.storePropertyValue(element);
}
}
private String quote(String out) {
out = "\"" + out + "\"";
return out;
}
private void store(byte[] bytes) {
ensureFree(bytes.length);
data.position(bufferPosition); // ensures intermittent reads/writes are safe
data.put(bytes);
bufferPosition += bytes.length;
}
private void store0() {
ensureFree(1);
data.put((byte) 0);
bufferPosition += 1;
}
void storeString(String value) {
if (value == null) {
store0();
} else {
byte[] utf = value.getBytes(StandardCharsets.UTF_8);
store(Varint.write(((long) (utf.length) << 1) + STRING_OFFSET));
store(utf);
}
}
private void ensureFree(int length) {
while (bufferPosition + length > data.capacity()) {
ByteBuffer bytes = this.data;
this.data = ByteBuffer.allocate(this.data.capacity() * 2);
this.data.put(bytes);
}
}
void extend() {
size += 1;
// keep track of index of element in data
elementIndices.add(bufferPosition);
}
class StringHandler extends BuiltinHandler<String> {
@Override
protected String getValue(Object instance) {
return instance.toString();
}
public void store(String value){
storeString(value);
}
}
}

View file

@ -0,0 +1,16 @@
package com.github.shautvast.contiguous.asm;
public abstract class AsmTypeHandler<T> {
public Object cast(Object value) {
return value;
}
void storePropertyValue(Object instance) {
T propertyValue = getValue(instance);
store(propertyValue);
}
protected abstract T getValue(Object instance);
public abstract void store(T value);
}

View file

@ -0,0 +1,4 @@
package com.github.shautvast.contiguous.asm;
public abstract class BuiltinHandler<T> extends AsmTypeHandler<T> {
}

View file

@ -1,4 +1,4 @@
package nl.sanderhautvast.contiguous;
package com.github.shautvast.contiguous;
import lombok.AllArgsConstructor;
import lombok.Data;

View file

@ -1,4 +1,4 @@
package nl.sanderhautvast.contiguous;
package com.github.shautvast.contiguous;
import org.junit.jupiter.api.Test;
@ -74,7 +74,6 @@ public class ContiguousListTest {
assertArrayEquals(new byte[]{1, 42},
beanList.getData());
assertArrayEquals(new int[]{0, 2}, beanList.getElementIndices());
}
@Test
@ -84,7 +83,6 @@ public class ContiguousListTest {
assertArrayEquals(new byte[]{1, -42},
beanList.getData());
assertArrayEquals(new int[]{0, 2}, beanList.getElementIndices());
}
@Test
@ -206,7 +204,7 @@ public class ContiguousListTest {
@Test
public void testSetterIterator() {
void testSetterIterator() {
ContiguousList<NestedBean> integers = new ContiguousList<>(NestedBean.class);
ContiguousList<NestedBean>.SetterIterator iterator = integers.setterIterator();
@ -222,4 +220,17 @@ public class ContiguousListTest {
assertEquals("Magrathea", nestedBean.getStringBean().getName());
assertEquals(42, nestedBean.getIntBean().getValue());
}
@Test
void testLargeAllocations(){
ContiguousList<String> strings = new ContiguousList<>(String.class);
for (int i=0; i<1000; i++){
strings.add("...................");
}
ContiguousList<String> strings3 = new ContiguousList<>(String.class);
for (int i=0; i<1000; i++){
strings3.add("...................");
}
}
}

View file

@ -1,4 +1,4 @@
package nl.sanderhautvast.contiguous;
package com.github.shautvast.contiguous;
import lombok.AllArgsConstructor;
import lombok.Data;

View file

@ -1,4 +1,4 @@
package nl.sanderhautvast.contiguous;
package com.github.shautvast.contiguous;
import lombok.AllArgsConstructor;
import lombok.Data;

View file

@ -1,4 +1,4 @@
package nl.sanderhautvast.contiguous;
package com.github.shautvast.contiguous;
import lombok.AllArgsConstructor;
import lombok.Data;

View file

@ -1,4 +1,4 @@
package nl.sanderhautvast.contiguous;
package com.github.shautvast.contiguous;
import lombok.AllArgsConstructor;
import lombok.Data;

View file

@ -1,4 +1,4 @@
package nl.sanderhautvast.contiguous;
package com.github.shautvast.contiguous;
import lombok.AllArgsConstructor;
import lombok.Data;

View file

@ -1,4 +1,4 @@
package nl.sanderhautvast.contiguous;
package com.github.shautvast.contiguous;
import lombok.AllArgsConstructor;
import lombok.Data;

View file

@ -0,0 +1,11 @@
package com.github.shautvast.contiguous;
public class NestedBeanHandler extends CompoundTypeHandler{
NestedBeanHandler(Class<NestedBean> type) {
super(type);
}
NestedBeanHandler(Class<?> type, String propertyName) {
super(type, propertyName);
}
}

View file

@ -1,4 +1,4 @@
package nl.sanderhautvast.contiguous;
package com.github.shautvast.contiguous;
import lombok.AllArgsConstructor;
import lombok.Data;

View file

@ -1,4 +1,4 @@
package nl.sanderhautvast.contiguous;
package com.github.shautvast.contiguous;
import lombok.AllArgsConstructor;
import lombok.Data;

View file

@ -0,0 +1,227 @@
package com.github.shautvast.contiguous.asm;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
public class AsmContiguousListTest {
@Test
public void testAddAndGetString() {
AsmContiguousList<String> list = new AsmContiguousList<>(String.class);
assertTrue(list.isEmpty());
list.add("hitchhikersguide to the galaxy");
assertFalse(list.isEmpty());
assertEquals(1, list.size());
list.add("the publishing houses of Ursa Minor");
assertFalse(list.isEmpty());
assertEquals(2, list.size());
String title = list.get(0);
assertEquals("hitchhikersguide to the galaxy", title);
String titleJson = list.getAsJson(0);
assertEquals("\"hitchhikersguide to the galaxy\"", titleJson);
String publisher = list.get(1);
assertEquals("the publishing houses of Ursa Minor", publisher);
}
// @Test
// public void testStringBean() {
// ContiguousList<StringBean> beanList = new ContiguousList<>(StringBean.class);
// beanList.add(new StringBean("Douglas Adams"));
//
// assertArrayEquals(new byte[]{39, 68, 111, 117, 103, 108, 97, 115, 32, 65, 100, 97, 109, 115}, beanList.getData());
//
// StringBean douglas = beanList.get(0);
// assertEquals("Douglas Adams", douglas.getName());
//
// String douglasJson = beanList.getAsJson(0);
// assertEquals("{\"name\": \"Douglas Adams\"}", douglasJson);
//
// // now add new data to see if existing data remains intact
// beanList.add(new StringBean("Ford Prefect"));
//
// assertEquals("Douglas Adams", beanList.get(0).getName());
// assertEquals("Ford Prefect", beanList.get(1).getName());
//
// assertEquals(2, beanList.size());
// }
//
// @Test
// public void testIntBean() {
// ContiguousList<IntBean> beanList = new ContiguousList<>(IntBean.class);
// beanList.add(new IntBean(42));
//
// assertArrayEquals(new byte[]{1, 42},
// beanList.getData());
// assertEquals(42, beanList.get(0).getValue());
// }
//
// @Test
// public void testLong() {
// ContiguousList<LongBean> beanList = new ContiguousList<>(LongBean.class);
// beanList.add(new LongBean(42));
//
// assertArrayEquals(new byte[]{1, 42},
// beanList.getData());
// assertEquals(42, beanList.get(0).getValue());
// }
//
// @Test
// public void testShort() {
// ContiguousList<ShortBean> beanList = new ContiguousList<>(ShortBean.class);
// beanList.add(new ShortBean((short) 42));
//
// assertArrayEquals(new byte[]{1, 42},
// beanList.getData());
// }
//
// @Test
// public void testByte() {
// ContiguousList<ByteBean> beanList = new ContiguousList<>(ByteBean.class);
// beanList.add(new ByteBean((byte) -42));
//
// assertArrayEquals(new byte[]{1, -42},
// beanList.getData());
// }
//
// @Test
// public void testNestedBean() {
// ContiguousList<NestedBean> beanList = new ContiguousList<>(NestedBean.class);
// beanList.add(new NestedBean(new StringBean("vogon constructor fleet"), new IntBean(42)));
//
// NestedBean expected = new NestedBean(new StringBean("vogon constructor fleet"), new IntBean(42));
// assertEquals(expected, beanList.get(0));
// }
//
// @Test
// public void testFloat() {
// ContiguousList<FloatBean> beanList = new ContiguousList<>(FloatBean.class);
// beanList.add(new FloatBean(1.1F));
//
//
// assertEquals(1.1F, beanList.get(0).getValue());
// }
//
// @Test
// public void testDouble() {
// ContiguousList<DoubleBean> beanList = new ContiguousList<>(DoubleBean.class);
// beanList.add(new DoubleBean(1.1));
//
// assertEquals(1.1, beanList.get(0).getValue());
// }
//
// @Test
// public void testNullFloat() {
// ContiguousList<FloatBean> beanList = new ContiguousList<>(FloatBean.class);
// beanList.add(new FloatBean(null));
//
// assertNull(beanList.get(0).getValue());
// }
//
// @Test
// public void testNullString() {
// ContiguousList<StringBean> beanList = new ContiguousList<>(StringBean.class);
// beanList.add(new StringBean(null));
//
// assertNull(beanList.get(0).getName());
// }
//
// @Test
// public void test100Elements() {
// ContiguousList<StringBean> beanList = new ContiguousList<>(StringBean.class);
// for (int i = 0; i < 100; i++) {
// beanList.add(new StringBean(null));
// }
// assertEquals(100, beanList.size());
// for (int i = 0; i < 100; i++) {
// assertNull(beanList.get(i).getName());
// }
// }
//
// @Test
// public void testBigInteger() {
// ContiguousList<BigInteger> bigIntegers = new ContiguousList<>(BigInteger.class);
// bigIntegers.add(new BigInteger("1000000000"));
// assertEquals(1_000_000_000L, bigIntegers.get(0).longValue());
// }
//
// @Test
// public void testIterator() {
// ContiguousList<Integer> integers = new ContiguousList<>(Integer.class);
// for (int i = 0; i < 100; i++) {
// integers.add(i);
// }
// int prevValue = -1;
// for (int value : integers) {
// assertEquals(prevValue, value - 1);
// prevValue = value;
// }
//
// integers.add(100);
//
// assertEquals(100, integers.get(100));
// }
//
// @Test
// public void testPrimitiveIterator() {
// ContiguousList<Integer> integers = new ContiguousList<>(Integer.class);
// for (int i = 0; i < 100; i++) {
// integers.add(i);
// }
// long prevValue = -1;
// for (Iterator<?> intIter = integers.valueIterator(); intIter.hasNext(); ) {
// int value = (int) intIter.next();
// assertEquals(prevValue, value - 1);
// prevValue = value;
// }
//
//
// integers.add(100);
//
// assertEquals(100, integers.get(100));
// }
//
// @Test
// public void testCompoundValueIterator() {
// ContiguousList<IntBean> integers = new ContiguousList<>(IntBean.class);
// for (int i = 0; i < 100; i++) {
// integers.add(new IntBean(i));
// }
// long prevValue = -1;
// for (Iterator<?> intIter = integers.valueIterator(); intIter.hasNext(); ) {
// int value = (int) intIter.next();
// assertEquals(prevValue, value - 1);
// prevValue = value;
// }
//
//
// integers.add(new IntBean(100));
//
// assertEquals(new IntBean(100), integers.get(100)); // here an instance
// }
//
//
//
// @Test
// public void testSetterIterator() {
// ContiguousList<NestedBean> integers = new ContiguousList<>(NestedBean.class);
// ContiguousList<NestedBean>.SetterIterator iterator = integers.setterIterator();
//
// if (iterator.hasNext()) {
// iterator.next().set("Magrathea");
// }
// if (iterator.hasNext()) {
// iterator.next().set(42);
// }
// iterator.finishObject();
//
// NestedBean nestedBean = integers.get(0);
// assertEquals("Magrathea", nestedBean.getStringBean().getName());
// assertEquals(42, nestedBean.getIntBean().getValue());
// }
}

View file

@ -3,7 +3,7 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>nl.sanderhautvast</groupId>
<groupId>com.github.shautvast</groupId>
<artifactId>contiguous-pom</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
@ -13,6 +13,7 @@
<module>demo</module>
<module>jdbc</module>
<module>jackson</module>
<module>benchmark</module>
</modules>
<name>contiguous</name>
<description>contiguous storage for java</description>