Skip to content

Commit 8fd8a8c

Browse files
committed
BoxStoreBuilder: add noReaderThreadLocals flag
1 parent 40aa3f8 commit 8fd8a8c

File tree

2 files changed

+40
-7
lines changed

2 files changed

+40
-7
lines changed

objectbox-java/src/main/java/io/objectbox/BoxStoreBuilder.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ public class BoxStoreBuilder {
9292
int fileMode;
9393

9494
int maxReaders;
95+
boolean noReaderThreadLocals;
9596

9697
int queryAttempts;
9798

@@ -288,20 +289,36 @@ public BoxStoreBuilder fileMode(int mode) {
288289
}
289290

290291
/**
291-
* Sets the maximum number of concurrent readers. For most applications, the default is fine (> 100 readers).
292+
* Sets the maximum number of concurrent readers. For most applications, the default is fine (~ 126 readers).
292293
* <p>
293294
* A "reader" is short for a thread involved in a read transaction.
294295
* <p>
295296
* If you hit {@link io.objectbox.exception.DbMaxReadersExceededException}, you should first worry about the
296297
* amount of threads you are using.
297298
* For highly concurrent setups (e.g. you are using ObjectBox on the server side) it may make sense to increase the
298299
* number.
300+
*
301+
* Note: Each thread that performed a read transaction and is still alive holds on to a reader slot.
302+
* These slots only get vacated when the thread ends. Thus, be mindful with the number of active threads.
303+
* Alternatively, you can opt to try the experimental noReaderThreadLocals option flag.
299304
*/
300305
public BoxStoreBuilder maxReaders(int maxReaders) {
301306
this.maxReaders = maxReaders;
302307
return this;
303308
}
304309

310+
/**
311+
* Disables the usage of thread locals for "readers" related to read transactions.
312+
* This can make sense if you are using a lot of threads that are kept alive.
313+
*
314+
* Note: This is still experimental, as it comes with subtle behavior changes at a low level and may affect
315+
* corner cases with e.g. transactions, which may not be fully tested at the moment.
316+
*/
317+
public BoxStoreBuilder noReaderThreadLocals() {
318+
this.noReaderThreadLocals = true;
319+
return this;
320+
}
321+
305322
@Internal
306323
public void entity(EntityInfo<?> entityInfo) {
307324
entityInfoList.add(entityInfo);
@@ -477,6 +494,7 @@ byte[] buildFlatStoreOptions(String canonicalPath) {
477494
if(skipReadSchema) FlatStoreOptions.addSkipReadSchema(fbb, skipReadSchema);
478495
if(usePreviousCommit) FlatStoreOptions.addUsePreviousCommit(fbb, usePreviousCommit);
479496
if(readOnly) FlatStoreOptions.addReadOnly(fbb, readOnly);
497+
if(noReaderThreadLocals) FlatStoreOptions.addNoReaderThreadLocals(fbb, noReaderThreadLocals);
480498
if (debugFlags != 0) {
481499
FlatStoreOptions.addDebugFlags(fbb, debugFlags);
482500
}

objectbox-java/src/main/java/io/objectbox/model/FlatStoreOptions.java

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,15 +64,19 @@ public final class FlatStoreOptions extends Table {
6464
*/
6565
public long fileMode() { int o = __offset(10); return o != 0 ? (long)bb.getInt(o + bb_pos) & 0xFFFFFFFFL : 0L; }
6666
/**
67-
* The maximum number of readers.
67+
* The maximum number of readers (related to read transactions).
6868
* "Readers" are an finite resource for which we need to define a maximum number upfront.
6969
* The default value is enough for most apps and usually you can ignore it completely.
7070
* However, if you get the OBX_ERROR_MAX_READERS_EXCEEDED error, you should verify your
7171
* threading. For each thread, ObjectBox uses multiple readers. Their number (per thread) depends
7272
* on number of types, relations, and usage patterns. Thus, if you are working with many threads
7373
* (e.g. in a server-like scenario), it can make sense to increase the maximum number of readers.
74-
* Note: The internal default is currently around 120.
75-
* So when hitting this limit, try values around 200-500.
74+
*
75+
* Note: The internal default is currently 126. So when hitting this limit, try value s around 200-500.
76+
*
77+
* Note: Each thread that performed a read transaction and is still alive holds on to a reader slot.
78+
* These slots only get vacated when the thread ends. Thus be mindful with the number of active threads.
79+
* Alternatively, you can opt to try the experimental noReaderThreadLocals option flag.
7680
*/
7781
public long maxReaders() { int o = __offset(12); return o != 0 ? (long)bb.getInt(o + bb_pos) & 0xFFFFFFFFL : 0L; }
7882
/**
@@ -123,6 +127,14 @@ public final class FlatStoreOptions extends Table {
123127
* For debugging purposes you may want enable specific logging.
124128
*/
125129
public long debugFlags() { int o = __offset(28); return o != 0 ? (long)bb.getInt(o + bb_pos) & 0xFFFFFFFFL : 0L; }
130+
/**
131+
* Disables the usage of thread locals for "readers" related to read transactions.
132+
* This can make sense if you are using a lot of threads that are kept alive.
133+
*
134+
* Note: This is still experimental, as it comes with subtle behavior changes at a low level and may affect
135+
* corner cases with e.g. transactions, which may not be fully tested at the moment.
136+
*/
137+
public boolean noReaderThreadLocals() { int o = __offset(30); return o != 0 ? 0!=bb.get(o + bb_pos) : false; }
126138

127139
public static int createFlatStoreOptions(FlatBufferBuilder builder,
128140
int directoryPathOffset,
@@ -137,8 +149,9 @@ public static int createFlatStoreOptions(FlatBufferBuilder builder,
137149
boolean usePreviousCommit,
138150
boolean usePreviousCommitOnValidationFailure,
139151
boolean readOnly,
140-
long debugFlags) {
141-
builder.startTable(13);
152+
long debugFlags,
153+
boolean noReaderThreadLocals) {
154+
builder.startTable(14);
142155
FlatStoreOptions.addValidateOnOpenPageLimit(builder, validateOnOpenPageLimit);
143156
FlatStoreOptions.addMaxDbSizeInKByte(builder, maxDbSizeInKByte);
144157
FlatStoreOptions.addDebugFlags(builder, debugFlags);
@@ -148,14 +161,15 @@ public static int createFlatStoreOptions(FlatBufferBuilder builder,
148161
FlatStoreOptions.addDirectoryPath(builder, directoryPathOffset);
149162
FlatStoreOptions.addPutPaddingMode(builder, putPaddingMode);
150163
FlatStoreOptions.addValidateOnOpen(builder, validateOnOpen);
164+
FlatStoreOptions.addNoReaderThreadLocals(builder, noReaderThreadLocals);
151165
FlatStoreOptions.addReadOnly(builder, readOnly);
152166
FlatStoreOptions.addUsePreviousCommitOnValidationFailure(builder, usePreviousCommitOnValidationFailure);
153167
FlatStoreOptions.addUsePreviousCommit(builder, usePreviousCommit);
154168
FlatStoreOptions.addSkipReadSchema(builder, skipReadSchema);
155169
return FlatStoreOptions.endFlatStoreOptions(builder);
156170
}
157171

158-
public static void startFlatStoreOptions(FlatBufferBuilder builder) { builder.startTable(13); }
172+
public static void startFlatStoreOptions(FlatBufferBuilder builder) { builder.startTable(14); }
159173
public static void addDirectoryPath(FlatBufferBuilder builder, int directoryPathOffset) { builder.addOffset(0, directoryPathOffset, 0); }
160174
public static void addModelBytes(FlatBufferBuilder builder, int modelBytesOffset) { builder.addOffset(1, modelBytesOffset, 0); }
161175
public static int createModelBytesVector(FlatBufferBuilder builder, byte[] data) { return builder.createByteVector(data); }
@@ -172,6 +186,7 @@ public static int createFlatStoreOptions(FlatBufferBuilder builder,
172186
public static void addUsePreviousCommitOnValidationFailure(FlatBufferBuilder builder, boolean usePreviousCommitOnValidationFailure) { builder.addBoolean(10, usePreviousCommitOnValidationFailure, false); }
173187
public static void addReadOnly(FlatBufferBuilder builder, boolean readOnly) { builder.addBoolean(11, readOnly, false); }
174188
public static void addDebugFlags(FlatBufferBuilder builder, long debugFlags) { builder.addInt(12, (int) debugFlags, (int) 0L); }
189+
public static void addNoReaderThreadLocals(FlatBufferBuilder builder, boolean noReaderThreadLocals) { builder.addBoolean(13, noReaderThreadLocals, false); }
175190
public static int endFlatStoreOptions(FlatBufferBuilder builder) {
176191
int o = builder.endTable();
177192
return o;

0 commit comments

Comments
 (0)