Skip to content

Commit e78c077

Browse files
committed
add maxMemory for RootAllocator
1 parent 5207fb7 commit e78c077

4 files changed

Lines changed: 56 additions & 5 deletions

File tree

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,18 @@ SpiceClient client = SpiceClient.builder()
122122
Retries are performed for connection and system internal errors. It is the SDK user's responsibility to properly
123123
handle other errors, for example RESOURCE_EXHAUSTED (HTTP 429).
124124

125+
### Memory Configuration
126+
127+
The `SpiceClient` uses an Arrow `RootAllocator` for managing off-heap memory. By default, it allows unlimited memory allocation. To prevent OOM issues in constrained environments, you can limit the maximum memory:
128+
129+
```java
130+
SpiceClient client = SpiceClient.builder()
131+
.withMaxMemory(1024 * 1024 * 1024L) // 1GB limit
132+
.build();
133+
```
134+
135+
You can also set the limit via the `SPICE_MAX_MEMORY` environment variable (in bytes). If both are provided, the builder method takes precedence.
136+
125137
### Spice.ai Runtime commands
126138

127139
#### Accelerated dataset refresh

src/main/java/ai/spice/Config.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,27 @@ public static URI getCloudHttpAddressUri() throws URISyntaxException {
9393
return new URI(CLOUD_HTTP_ADDRESS);
9494
}
9595

96+
/**
97+
* Returns the maximum memory allocation for the Arrow RootAllocator from the
98+
* SPICE_MAX_MEMORY environment variable.
99+
*
100+
* @return the maximum memory in bytes, or Long.MAX_VALUE if not set or invalid.
101+
*/
102+
public static long getMaxMemory() {
103+
String maxMemoryStr = System.getenv("SPICE_MAX_MEMORY");
104+
if (maxMemoryStr != null && !maxMemoryStr.isEmpty()) {
105+
try {
106+
long maxMemory = Long.parseLong(maxMemoryStr);
107+
if (maxMemory > 0) {
108+
return maxMemory;
109+
}
110+
} catch (NumberFormatException e) {
111+
// Invalid value, fall back to default
112+
}
113+
}
114+
return Long.MAX_VALUE;
115+
}
116+
96117
/**
97118
* Returns the Spice SDK user agent for this system, including the package
98119
* version, system OS, version and arch.
@@ -127,4 +148,4 @@ public static String getUserAgent() {
127148
+ System.getProperty("os.version") + " "
128149
+ osArch + ")";
129150
}
130-
}
151+
}

src/main/java/ai/spice/SpiceClient.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,10 @@ public static SpiceClientBuilder builder() throws URISyntaxException {
9191
* @param httpAddress the URI of the Spice.ai runtime HTTP address
9292
*
9393
* @param maxRetries the maximum number of connection retries for the client
94+
* @param userAgent the user agent string
95+
* @param maxMemory the maximum memory allocation for the Arrow RootAllocator
9496
*/
95-
public SpiceClient(String appId, String apiKey, URI flightAddress, URI httpAddress, int maxRetries, String userAgent) {
97+
public SpiceClient(String appId, String apiKey, URI flightAddress, URI httpAddress, int maxRetries, String userAgent, long maxMemory) {
9698
this.appId = appId;
9799
this.apiKey = apiKey;
98100
this.maxRetries = maxRetries;
@@ -108,7 +110,7 @@ public SpiceClient(String appId, String apiKey, URI flightAddress, URI httpAddre
108110
this.flightAddress = flightAddress;
109111
}
110112

111-
Builder builder = FlightClient.builder(new RootAllocator(Long.MAX_VALUE), new Location(this.flightAddress));
113+
Builder builder = FlightClient.builder(new RootAllocator(maxMemory), new Location(this.flightAddress));
112114

113115
if (Strings.isNullOrEmpty(apiKey)) {
114116
this.flightClient = new FlightSqlClient(builder.build());

src/main/java/ai/spice/SpiceClientBuilder.java

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ public class SpiceClientBuilder {
3838
private URI flightAddress;
3939
private URI httpAddress;
4040
private int maxRetries = 3;
41+
private long maxMemory = Long.MAX_VALUE;
4142

4243
/**
4344
* Constructs a new SpiceClientBuilder instance
@@ -47,6 +48,7 @@ public class SpiceClientBuilder {
4748
SpiceClientBuilder() throws URISyntaxException {
4849
this.flightAddress = Config.getLocalFlightAddressUri();
4950
this.httpAddress = Config.getLocalHttpAddressUri();
51+
this.maxMemory = Config.getMaxMemory();
5052
}
5153

5254
/**
@@ -139,12 +141,26 @@ public SpiceClientBuilder withMaxRetries(int maxRetries) {
139141
return this;
140142
}
141143

144+
/**
145+
* Sets the maximum memory allocation for the Arrow RootAllocator.
146+
*
147+
* @param maxMemory The maximum memory in bytes for the RootAllocator (must be > 0)
148+
* @return The current instance of SpiceClientBuilder for method chaining.
149+
*/
150+
public SpiceClientBuilder withMaxMemory(long maxMemory) {
151+
if (maxMemory <= 0) {
152+
throw new IllegalArgumentException("maxMemory must be greater than 0");
153+
}
154+
this.maxMemory = maxMemory;
155+
return this;
156+
}
157+
142158
/**
143159
* Creates SpiceClient with provided parameters.
144160
*
145161
* @return The SpiceClient instance
146162
*/
147163
public SpiceClient build() {
148-
return new SpiceClient(appId, apiKey, flightAddress, httpAddress, maxRetries, userAgent);
164+
return new SpiceClient(appId, apiKey, flightAddress, httpAddress, maxRetries, userAgent, maxMemory);
149165
}
150-
}
166+
}

0 commit comments

Comments
 (0)