Skip to content

Commit b20c557

Browse files
authored
Merge pull request #60 from Chessray/eb/ffm-iterators
Benchmarks for iterators in Java 8 and FFM
2 parents 820cdb8 + 1747014 commit b20c557

11 files changed

Lines changed: 577 additions & 0 deletions

File tree

jmh_iterators.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"benchmark": "IteratorBenchmark",
3+
"jvmargs": ["Xmx4G", "XX:ErrorFile=./results/hs_err_pid%p.log", "XX:+HeapDumpOnOutOfMemoryError"],
4+
"params": {
5+
"numElements": [10, 100, 1000],
6+
"elementSize": [16, 128, 1024]
7+
},
8+
"options": {
9+
"batchsize": 1,
10+
"warmupiterations": 5,
11+
"warmuptime": "10ms",
12+
"iterations": 5,
13+
"time": "50ms"
14+
},
15+
"result.path": "./results",
16+
"java.library.path": "target/jni-benchmarks-1.0.1-SNAPSHOT-application/jni-benchmarks-1.0.1-SNAPSHOT/lib",
17+
"jar": "target/jni-benchmarks-1.0.1-SNAPSHOT-benchmarks.nar"
18+
}

jmh_iterators_java21.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"benchmark": "IteratorBenchmarkJavaFfm",
3+
"jvmargs": ["Xmx4G", "XX:ErrorFile=./results/hs_err_pid%p.log", "XX:+HeapDumpOnOutOfMemoryError", "-enable-preview"],
4+
"params": {
5+
"numElements": [10, 100, 1000],
6+
"elementSize": [16, 128, 1024]
7+
},
8+
"options": {
9+
"batchsize": 1,
10+
"warmupiterations": 5,
11+
"warmuptime": "10ms",
12+
"iterations": 5,
13+
"time": "50ms"
14+
},
15+
"result.path": "./results",
16+
"java.library.path": "target/jni-benchmarks-1.0.1-SNAPSHOT-application/jni-benchmarks-1.0.1-SNAPSHOT/lib",
17+
"jar": "target/jni-benchmarks-1.0.1-SNAPSHOT-benchmarks.nar"
18+
}

jmh_iterators_java25.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"benchmark": "IteratorBenchmarkJavaFfm",
3+
"jvmargs": ["Xmx4G", "XX:ErrorFile=./results/hs_err_pid%p.log", "XX:+HeapDumpOnOutOfMemoryError"],
4+
"params": {
5+
"numElements": [10, 100, 1000],
6+
"elementSize": [16, 128, 1024]
7+
},
8+
"options": {
9+
"batchsize": 1,
10+
"warmupiterations": 5,
11+
"warmuptime": "10ms",
12+
"iterations": 5,
13+
"time": "50ms"
14+
},
15+
"result.path": "./results",
16+
"java.library.path": "target/jni-benchmarks-1.0.1-SNAPSHOT-application/jni-benchmarks-1.0.1-SNAPSHOT/lib",
17+
"jar": "target/jni-benchmarks-1.0.1-SNAPSHOT-benchmarks.nar"
18+
}

jmh_plot_iterator.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"plots": [
3+
{
4+
"xaxisparam": {
5+
"name": "numElements"
6+
},
7+
"label": "all"
8+
}
9+
],
10+
"result.path": "./analysis/testplots"
11+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/**
2+
* Copyright © 2026, Evolved Binary Ltd
3+
* All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions are met:
7+
* * Redistributions of source code must retain the above copyright
8+
* notice, this list of conditions and the following disclaimer.
9+
* * Redistributions in binary form must reproduce the above copyright
10+
* notice, this list of conditions and the following disclaimer in the
11+
* documentation and/or other materials provided with the distribution.
12+
* * Neither the name of the <organization> nor the
13+
* names of its contributors may be used to endorse or promote products
14+
* derived from this software without specific prior written permission.
15+
*
16+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19+
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
20+
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23+
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26+
*/
27+
#include "Iterator.h"
28+
#include <stdexcept>
29+
#include <algorithm>
30+
31+
Iterator::Iterator(int num_elements, size_t element_size)
32+
: m_num_elements(num_elements), m_element_size(element_size), m_current_index(0) {
33+
34+
m_elements.reserve(num_elements);
35+
36+
std::random_device rd;
37+
std::mt19937 gen(rd());
38+
std::uniform_int_distribution<int> dis(0, 255);
39+
40+
for (int i = 0; i < num_elements; ++i) {
41+
std::vector<char> element(element_size);
42+
std::generate(element.begin(), element.end(), [&]() {
43+
return static_cast<char>(dis(gen));
44+
});
45+
m_elements.push_back(std::move(element));
46+
}
47+
}
48+
49+
bool Iterator::hasNext() const {
50+
return m_current_index < m_num_elements;
51+
}
52+
53+
const std::vector<char>& Iterator::next() {
54+
if (!hasNext()) {
55+
throw std::out_of_range("No more elements in iterator");
56+
}
57+
return m_elements[m_current_index++];
58+
}

src/main/c++/iterators/Iterator.h

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/**
2+
* Copyright © 2026, Evolved Binary Ltd
3+
* All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions are met:
7+
* * Redistributions of source code must retain the above copyright
8+
* notice, this list of conditions and the following disclaimer.
9+
* * Redistributions in binary form must reproduce the above copyright
10+
* notice, this list of conditions and the following disclaimer in the
11+
* documentation and/or other materials provided with the distribution.
12+
* * Neither the name of the <organization> nor the
13+
* names of its contributors may be used to endorse or promote products
14+
* derived from this software without specific prior written permission.
15+
*
16+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19+
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
20+
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23+
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26+
*/
27+
#ifndef ITERATOR_H
28+
#define ITERATOR_H
29+
30+
#include <vector>
31+
#include <cstddef>
32+
#include <random>
33+
34+
class Iterator {
35+
public:
36+
/**
37+
* @param num_elements Number of elements to generate.
38+
* @param element_size Size of each individual element in bytes.
39+
*/
40+
Iterator(int num_elements, size_t element_size);
41+
42+
/**
43+
* @return true if the iteration has more elements.
44+
*/
45+
bool hasNext() const;
46+
47+
/**
48+
* @return The next element in the iteration.
49+
* Note: In a real Java Iterator, next() returns the element.
50+
* Here we return a pointer to the random data.
51+
*/
52+
const std::vector<char>& next();
53+
54+
private:
55+
int m_num_elements;
56+
size_t m_element_size;
57+
int m_current_index;
58+
std::vector<std::vector<char>> m_elements;
59+
};
60+
61+
#endif // ITERATOR_H
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/**
2+
* Copyright © 2026, Evolved Binary Ltd
3+
* All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions are met:
7+
* * Redistributions of source code must retain the above copyright
8+
* notice, this list of conditions and the following disclaimer.
9+
* * Redistributions in binary form must reproduce the above copyright
10+
* notice, this list of conditions and the following disclaimer in the
11+
* documentation and/or other materials provided with the distribution.
12+
* * Neither the name of the <organization> nor the
13+
* names of its contributors may be used to endorse or promote products
14+
* derived from this software without specific prior written permission.
15+
*
16+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19+
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
20+
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23+
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26+
*/
27+
#include <jni.h>
28+
29+
#include <algorithm>
30+
#include <cstring>
31+
#include <stdexcept>
32+
33+
#include "Iterator.h"
34+
35+
#ifdef __cplusplus
36+
extern "C" {
37+
#endif
38+
39+
/*
40+
* Class: com_evolvedbinary_jnibench_common_iterators_NativeIterator
41+
* Method: createIterator
42+
* Signature: (IJ)J
43+
*/
44+
JNIEXPORT jlong JNICALL Java_com_evolvedbinary_jnibench_common_iterators_NativeIterator_createIterator
45+
(JNIEnv *env, jobject obj, jint num_elements, jlong element_size) {
46+
Iterator* iterator = new Iterator(num_elements, static_cast<size_t>(element_size));
47+
return reinterpret_cast<jlong>(iterator);
48+
}
49+
50+
/*
51+
* Class: com_evolvedbinary_jnibench_common_iterators_NativeIterator
52+
* Method: hasNext
53+
* Signature: (J)B
54+
*/
55+
JNIEXPORT jboolean JNICALL Java_com_evolvedbinary_jnibench_common_iterators_NativeIterator_hasNext
56+
(JNIEnv *env, jobject obj, jlong handle) {
57+
Iterator* iterator = reinterpret_cast<Iterator*>(handle);
58+
return iterator->hasNext() ? JNI_TRUE : JNI_FALSE;
59+
}
60+
61+
/*
62+
* Class: com_evolvedbinary_jnibench_common_iterators_NativeIterator
63+
* Method: next
64+
* Signature: (J)[B
65+
*/
66+
JNIEXPORT jbyteArray JNICALL Java_com_evolvedbinary_jnibench_common_iterators_NativeIterator_next
67+
(JNIEnv *env, jobject obj, jlong handle) {
68+
Iterator* iterator = reinterpret_cast<Iterator*>(handle);
69+
try {
70+
const std::vector<char>& data = iterator->next();
71+
jbyteArray result = env->NewByteArray(static_cast<jsize>(data.size()));
72+
if (result == nullptr) {
73+
return nullptr;
74+
}
75+
env->SetByteArrayRegion(result, 0, static_cast<jsize>(data.size()), reinterpret_cast<const jbyte*>(data.data()));
76+
return result;
77+
} catch (const std::out_of_range& e) {
78+
jclass exClass = env->FindClass("java/util/NoSuchElementException");
79+
if (exClass != nullptr) {
80+
env->ThrowNew(exClass, e.what());
81+
}
82+
return nullptr;
83+
}
84+
}
85+
86+
/*
87+
* Class: com_evolvedbinary_jnibench_common_iterators_NativeIterator
88+
* Method: disposeInternal
89+
* Signature: (J)V
90+
*/
91+
JNIEXPORT void JNICALL Java_com_evolvedbinary_jnibench_common_iterators_NativeIterator_disposeInternal
92+
(JNIEnv *env, jobject obj, jlong handle) {
93+
Iterator* iterator = reinterpret_cast<Iterator*>(handle);
94+
delete iterator;
95+
}
96+
97+
extern "C" void* iterator_create(int num_elements, size_t element_size) {
98+
return new Iterator(num_elements, element_size);
99+
}
100+
101+
extern "C" int iterator_has_next(void* handle) {
102+
auto* iterator = reinterpret_cast<Iterator*>(handle);
103+
return iterator->hasNext() ? 1 : 0;
104+
}
105+
106+
extern "C" int iterator_next(void* handle, char* dest, int dest_len) {
107+
auto* iterator = reinterpret_cast<Iterator*>(handle);
108+
try {
109+
const auto& data = iterator->next();
110+
const int size = std::min(static_cast<int>(data.size()), dest_len);
111+
std::memcpy(dest, data.data(), static_cast<size_t>(size));
112+
return size;
113+
} catch (const std::out_of_range&) {
114+
return -1;
115+
}
116+
}
117+
118+
extern "C" void iterator_dispose(void* handle) {
119+
auto* iterator = reinterpret_cast<Iterator*>(handle);
120+
delete iterator;
121+
}
122+
123+
#ifdef __cplusplus
124+
}
125+
#endif
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/**
2+
* Copyright © 2026, Evolved Binary Ltd
3+
* All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions are met:
7+
* * Redistributions of source code must retain the above copyright
8+
* notice, this list of conditions and the following disclaimer.
9+
* * Redistributions in binary form must reproduce the above copyright
10+
* notice, this list of conditions and the following disclaimer in the
11+
* documentation and/or other materials provided with the distribution.
12+
* * Neither the name of the <organization> nor the
13+
* names of its contributors may be used to endorse or promote products
14+
* derived from this software without specific prior written permission.
15+
*
16+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19+
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
20+
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23+
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26+
*/
27+
package com.evolvedbinary.jnibench.common.iterators;
28+
29+
import com.evolvedbinary.jnibench.common.NativeBackedObject;
30+
31+
public class NativeIterator extends NativeBackedObject {
32+
33+
public NativeIterator(int numElements, long elementSize) {
34+
_nativeHandle = createIterator(numElements, elementSize);
35+
}
36+
37+
public boolean hasNext() {
38+
return hasNext(_nativeHandle);
39+
}
40+
41+
public byte[] next() {
42+
return next(_nativeHandle);
43+
}
44+
45+
@Override
46+
protected void disposeInternal() {
47+
disposeInternal(_nativeHandle);
48+
}
49+
50+
private native long createIterator(int numElements, long elementSize);
51+
private native boolean hasNext(long handle);
52+
private native byte[] next(long handle);
53+
private native void disposeInternal(long handle);
54+
}

0 commit comments

Comments
 (0)