Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/sun/nio/ch/TestMaxCachedBufferSize.java
38840 views
1
/*
2
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*/
23
24
import java.io.IOException;
25
26
import java.lang.management.BufferPoolMXBean;
27
import java.lang.management.ManagementFactory;
28
29
import java.nio.ByteBuffer;
30
31
import java.nio.channels.FileChannel;
32
33
import java.nio.file.Path;
34
import java.nio.file.Paths;
35
36
import static java.nio.file.StandardOpenOption.CREATE;
37
import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
38
import static java.nio.file.StandardOpenOption.WRITE;
39
40
import java.util.List;
41
import java.util.Random;
42
43
/*
44
* @test
45
* @requires sun.arch.data.model == "64"
46
* @build TestMaxCachedBufferSize
47
* @run main/othervm TestMaxCachedBufferSize
48
* @run main/othervm -Djdk.nio.maxCachedBufferSize=0 TestMaxCachedBufferSize
49
* @run main/othervm -Djdk.nio.maxCachedBufferSize=2000 TestMaxCachedBufferSize
50
* @run main/othervm -Djdk.nio.maxCachedBufferSize=100000 TestMaxCachedBufferSize
51
* @run main/othervm -Djdk.nio.maxCachedBufferSize=10000000 TestMaxCachedBufferSize
52
* @summary Test the implementation of the jdk.nio.maxCachedBufferSize property.
53
*/
54
public class TestMaxCachedBufferSize {
55
private static final int DEFAULT_ITERS = 10 * 1000;
56
private static final int DEFAULT_THREAD_NUM = 4;
57
58
private static final int SMALL_BUFFER_MIN_SIZE = 4 * 1024;
59
private static final int SMALL_BUFFER_MAX_SIZE = 64 * 1024;
60
private static final int SMALL_BUFFER_DIFF_SIZE =
61
SMALL_BUFFER_MAX_SIZE - SMALL_BUFFER_MIN_SIZE;
62
63
private static final int LARGE_BUFFER_MIN_SIZE = 512 * 1024;
64
private static final int LARGE_BUFFER_MAX_SIZE = 4 * 1024 * 1024;
65
private static final int LARGE_BUFFER_DIFF_SIZE =
66
LARGE_BUFFER_MAX_SIZE - LARGE_BUFFER_MIN_SIZE;
67
68
private static final int LARGE_BUFFER_FREQUENCY = 100;
69
70
private static final String FILE_NAME_PREFIX = "nio-out-file-";
71
private static final int VERBOSE_PERIOD = 5 * 1000;
72
73
private static int iters = DEFAULT_ITERS;
74
private static int threadNum = DEFAULT_THREAD_NUM;
75
76
private static BufferPoolMXBean getDirectPool() {
77
final List<BufferPoolMXBean> pools =
78
ManagementFactory.getPlatformMXBeans(BufferPoolMXBean.class);
79
for (BufferPoolMXBean pool : pools) {
80
if (pool.getName().equals("direct")) {
81
return pool;
82
}
83
}
84
throw new Error("could not find direct pool");
85
}
86
private static final BufferPoolMXBean directPool = getDirectPool();
87
88
// Each worker will do write operations on a file channel using
89
// buffers of various sizes. The buffer size is randomly chosen to
90
// be within a small or a large range. This way we can control
91
// which buffers can be cached (all, only the small ones, or none)
92
// by setting the jdk.nio.maxCachedBufferSize property.
93
private static class Worker implements Runnable {
94
private final int id;
95
private final Random random = new Random();
96
private long smallBufferCount = 0;
97
private long largeBufferCount = 0;
98
99
private int getWriteSize() {
100
int minSize = 0;
101
int diff = 0;
102
if (random.nextInt() % LARGE_BUFFER_FREQUENCY != 0) {
103
// small buffer
104
minSize = SMALL_BUFFER_MIN_SIZE;
105
diff = SMALL_BUFFER_DIFF_SIZE;
106
smallBufferCount += 1;
107
} else {
108
// large buffer
109
minSize = LARGE_BUFFER_MIN_SIZE;
110
diff = LARGE_BUFFER_DIFF_SIZE;
111
largeBufferCount += 1;
112
}
113
return minSize + random.nextInt(diff);
114
}
115
116
private void loop() {
117
final String fileName = String.format("%s%d", FILE_NAME_PREFIX, id);
118
119
try {
120
for (int i = 0; i < iters; i += 1) {
121
final int writeSize = getWriteSize();
122
123
// This will allocate a HeapByteBuffer. It should not
124
// be a direct buffer, otherwise the write() method on
125
// the channel below will not create a temporary
126
// direct buffer for the write.
127
final ByteBuffer buffer = ByteBuffer.allocate(writeSize);
128
129
// Put some random data on it.
130
while (buffer.hasRemaining()) {
131
buffer.put((byte) random.nextInt());
132
}
133
buffer.rewind();
134
135
final Path file = Paths.get(fileName);
136
try (FileChannel outChannel = FileChannel.open(file, CREATE, TRUNCATE_EXISTING, WRITE)) {
137
// The write() method will create a temporary
138
// direct buffer for the write and attempt to cache
139
// it. It's important that buffer is not a
140
// direct buffer, otherwise the temporary buffer
141
// will not be created.
142
long res = outChannel.write(buffer);
143
}
144
145
if ((i + 1) % VERBOSE_PERIOD == 0) {
146
System.out.printf(
147
" Worker %3d | %8d Iters | Small %8d Large %8d | Direct %4d / %7dK\n",
148
id, i + 1, smallBufferCount, largeBufferCount,
149
directPool.getCount(), directPool.getTotalCapacity() / 1024);
150
}
151
}
152
} catch (IOException e) {
153
throw new Error("I/O error", e);
154
}
155
}
156
157
@Override
158
public void run() {
159
loop();
160
}
161
162
public Worker(int id) {
163
this.id = id;
164
}
165
}
166
167
public static void checkDirectBuffers(long expectedCount, long expectedMax) {
168
final long directCount = directPool.getCount();
169
final long directTotalCapacity = directPool.getTotalCapacity();
170
System.out.printf("Direct %d / %dK\n",
171
directCount, directTotalCapacity / 1024);
172
173
// Note that directCount could be < expectedCount. This can
174
// happen if a GC occurs after one of the worker threads exits
175
// since its thread-local DirectByteBuffer could be cleaned up
176
// before we reach here.
177
if (directCount > expectedCount) {
178
throw new Error(String.format(
179
"inconsistent direct buffer total count, expected = %d, found = %d",
180
expectedCount, directCount));
181
}
182
183
if (directTotalCapacity > expectedMax) {
184
throw new Error(String.format(
185
"inconsistent direct buffer total capacity, expectex max = %d, found = %d",
186
expectedMax, directTotalCapacity));
187
}
188
}
189
190
public static void main(String[] args) {
191
final String maxBufferSizeStr = System.getProperty("jdk.nio.maxCachedBufferSize");
192
final long maxBufferSize =
193
(maxBufferSizeStr != null) ? Long.valueOf(maxBufferSizeStr) : Long.MAX_VALUE;
194
195
// We assume that the max cannot be equal to a size of a
196
// buffer that can be allocated (makes sanity checking at the
197
// end easier).
198
if ((SMALL_BUFFER_MIN_SIZE <= maxBufferSize &&
199
maxBufferSize <= SMALL_BUFFER_MAX_SIZE) ||
200
(LARGE_BUFFER_MIN_SIZE <= maxBufferSize &&
201
maxBufferSize <= LARGE_BUFFER_MAX_SIZE)) {
202
throw new Error(String.format("max buffer size = %d not allowed",
203
maxBufferSize));
204
}
205
206
System.out.printf("Threads %d | Iterations %d | MaxBufferSize %d\n",
207
threadNum, iters, maxBufferSize);
208
System.out.println();
209
210
final Thread[] threads = new Thread[threadNum];
211
for (int i = 0; i < threadNum; i += 1) {
212
threads[i] = new Thread(new Worker(i));
213
threads[i].start();
214
}
215
216
try {
217
for (int i = 0; i < threadNum; i += 1) {
218
threads[i].join();
219
}
220
} catch (InterruptedException e) {
221
throw new Error("join() interrupted!", e);
222
}
223
224
// There is an assumption here that, at this point, only the
225
// cached DirectByteBuffers should be active. Given we
226
// haven't used any other DirectByteBuffers in this test, this
227
// should hold.
228
//
229
// Also note that we can only do the sanity checking at the
230
// end and not during the run given that, at any time, there
231
// could be buffers currently in use by some of the workers
232
// that will not be cached.
233
234
System.out.println();
235
if (maxBufferSize < SMALL_BUFFER_MAX_SIZE) {
236
// The max buffer size is smaller than all buffers that
237
// were allocated. No buffers should have been cached.
238
checkDirectBuffers(0, 0);
239
} else if (maxBufferSize < LARGE_BUFFER_MIN_SIZE) {
240
// The max buffer size is larger than all small buffers
241
// but smaller than all large buffers that were
242
// allocated. Only small buffers could have been cached.
243
checkDirectBuffers(threadNum,
244
(long) threadNum * (long) SMALL_BUFFER_MAX_SIZE);
245
} else {
246
// The max buffer size is larger than all buffers that
247
// were allocated. All buffers could have been cached.
248
checkDirectBuffers(threadNum,
249
(long) threadNum * (long) LARGE_BUFFER_MAX_SIZE);
250
}
251
}
252
}
253
254