GlueGen v2.6.0-rc-20250712
GlueGen, Native Binding Generator for Java™ (public API).
TestByteBufferInputStream.java
Go to the documentation of this file.
1/**
2 * Copyright 2014 JogAmp Community. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without modification, are
5 * permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice, this list of
8 * conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 * of conditions and the following disclaimer in the documentation and/or other materials
12 * provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
15 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 * The views and conclusions contained in the software and documentation are those of the
25 * authors and should not be interpreted as representing official policies, either expressed
26 * or implied, of JogAmp Community.
27 */
28package com.jogamp.common.nio;
29
30import java.io.BufferedInputStream;
31import java.io.File;
32import java.io.FileInputStream;
33import java.io.IOException;
34import java.io.InputStream;
35import java.io.RandomAccessFile;
36import java.nio.MappedByteBuffer;
37import java.nio.channels.FileChannel;
38
39import org.junit.AfterClass;
40import org.junit.Assert;
41import org.junit.BeforeClass;
42import org.junit.Test;
43
44import com.jogamp.common.os.Platform;
45import com.jogamp.common.util.IOUtil;
46import com.jogamp.junit.util.SingletonJunitCase;
47
48import org.junit.FixMethodOrder;
49import org.junit.runners.MethodSorters;
50
51/**
52 * Testing serial read of {@link ByteBufferInputStream} and {@link MappedByteBufferInputStream},
53 * i.e. basic functionality only.
54 * <p>
55 * Focusing on comparison with {@link BufferedInputStream} regarding
56 * performance, used memory heap and used virtual memory.
57 * </p>
58 */
59@FixMethodOrder(MethodSorters.NAME_ASCENDING)
61 /** {@value} */
62 static final int buffer__8KiB = 1 << 13;
63
64 /** {@value} */
65 static final int halfMiB = 1 << 19;
66 /** {@value} */
67 static final int oneMiB = 1 << 20;
68 /** {@value} */
69 static final int tenMiB = 1 << 24;
70 /** {@value} */
71 static final int hunMiB = 1 << 27;
72 /** {@value} */
73 static final int halfGiB = 1 << 29;
74 /** {@value} */
75 static final int oneGiB = 1 << 30;
76 /** {@value} */
77 static final long twoPlusGiB = ( 2L << 30 ) + halfMiB;
78
79 static final String fileHalfMiB = "./testHalfMiB.bin" ;
80 static final String fileOneMiB = "./testOneMiB.bin" ;
81 static final String fileTenMiB = "./testTenMiB.bin" ;
82 static final String fileHunMiB = "./testHunMiB.bin" ;
83 static final String fileHalfGiB = "./testHalfGiB.bin" ;
84 static final String fileOneGiB = "./testOneGiB.bin" ;
85 static final String fileTwoPlusGiB = "./testTwoPlusGiB.bin" ;
86 static final String fileOut = "./testOut.bin" ;
87
88 public static final String PrintPrecision = "%8.3f";
89 public static final double MIB = 1024.0*1024.0;
90
91
92 @BeforeClass
93 public static void setup() throws IOException {
94 final Runtime runtime = Runtime.getRuntime();
95 System.err.printf("Total Memory : "+PrintPrecision+" MiB%n", runtime.totalMemory() / MIB);
96 System.err.printf("Max Memory : "+PrintPrecision+" MiB%n", runtime.maxMemory() / MIB);
97
98 setup(fileHalfMiB, halfMiB);
99 setup(fileOneMiB, oneMiB);
100 setup(fileTenMiB, tenMiB);
101 setup(fileHunMiB, hunMiB);
102 setup(fileHalfGiB, halfGiB);
103 setup(fileOneGiB, oneGiB);
104 setup(fileTwoPlusGiB, twoPlusGiB);
105 }
106 static void setup(final String fname, final long size) throws IOException {
107 final File file = new File(fname);
108 final RandomAccessFile out = new RandomAccessFile(file, "rws");
109 out.setLength(size);
110 out.close();
111 }
112
113 @AfterClass
114 public static void cleanup() {
115 cleanup(fileHalfMiB);
116 cleanup(fileOneMiB);
117 cleanup(fileTenMiB);
118 cleanup(fileHunMiB);
119 cleanup(fileHalfGiB);
120 cleanup(fileOneGiB);
121 cleanup(fileTwoPlusGiB);
122 cleanup(fileOut);
123 }
124 static void cleanup(final String fname) {
125 final File file = new File(fname);
126 file.delete();
127 }
128
129 @Test
130 public void test01MixedIntSize() throws IOException {
131 // testCopyIntSize1Impl(fileHalfMiB, halfMiB);
132
133 // testCopyIntSize1Impl(fileOneMiB, oneMiB);
134
135 testCopyIntSize1Impl(fileTenMiB, tenMiB);
136
137 testCopyIntSize1Impl(fileHunMiB, hunMiB);
138
139 testCopyIntSize1Impl(fileHalfGiB, halfGiB);
140
141 // testCopyIntSize1Impl(fileOneGiB, oneGiB);
142 }
143
144 static enum SrcType { COPY, MMAP1, MMAP2_NONE, MMAP2_SOFT, MMAP2_HARD };
145
146 @Test
147 public void test11MMap1GiBFlushNone() throws IOException {
148 if( !manualTest && Platform.OSType.MACOS == Platform.getOSType() ) {
149 testCopyIntSize1Impl2(0, SrcType.MMAP2_NONE, 0, fileOneMiB, oneMiB);
150 } else {
151 testCopyIntSize1Impl2(0, SrcType.MMAP2_NONE, 0, fileOneGiB, oneGiB);
152 // testCopyIntSize1Impl2(0, SrcType.MMAP2_NONE, 0, fileTwoPlusGiB, twoPlusGiB);
153 }
154 }
155
156 @Test
157 public void test12MMap1GiBFlushSoft() throws IOException {
158 if( !manualTest && Platform.OSType.MACOS == Platform.getOSType() ) {
159 testCopyIntSize1Impl2(0, SrcType.MMAP2_SOFT, 0, fileOneMiB, oneMiB);
160 } else {
161 testCopyIntSize1Impl2(0, SrcType.MMAP2_SOFT, 0, fileOneGiB, oneGiB);
162 // testCopyIntSize1Impl2(0, SrcType.MMAP2_SOFT, 0, fileTwoPlusGiB, twoPlusGiB);
163 }
164 }
165
166 @Test
167 public void test13MMap2GiBFlushHard() throws IOException {
168 if( !manualTest && Platform.OSType.MACOS == Platform.getOSType() ) {
169 testCopyIntSize1Impl2(0, SrcType.MMAP2_HARD, 0, fileOneMiB, oneMiB);
170 } else {
171 // testCopyIntSize1Impl2(0, SrcType.MMAP2_HARD, 0, fileOneGiB, oneGiB);
172 testCopyIntSize1Impl2(0, SrcType.MMAP2_HARD, 0, fileTwoPlusGiB, twoPlusGiB);
173 }
174 }
175
176 void testCopyIntSize1Impl(final String testFileName, final long expSize) throws IOException {
177 testCopyIntSize1Impl2(0, SrcType.COPY, buffer__8KiB, testFileName, expSize);
178 testCopyIntSize1Impl2(0, SrcType.COPY, hunMiB, testFileName, expSize);
179 testCopyIntSize1Impl2(0, SrcType.MMAP1, 0, testFileName, expSize);
180 testCopyIntSize1Impl2(0, SrcType.MMAP2_SOFT, 0, testFileName, expSize);
181 System.err.println();
182 }
183 boolean testCopyIntSize1Impl2(final int iter, final SrcType srcType, final int reqBufferSize, final String testFileName, final long expSize) throws IOException {
184 final int expSizeI = (int) ( expSize <= Integer.MAX_VALUE ? expSize : Integer.MAX_VALUE );
185 final int bufferSize = reqBufferSize < expSizeI ? reqBufferSize : expSizeI;
186 final File testFile = new File(testFileName);
187 final long hasSize1 = testFile.length();
188 final long t0 = System.currentTimeMillis();
189 Assert.assertEquals(expSize, hasSize1);
190
191 final Runtime runtime = Runtime.getRuntime();
192 final long[] usedMem0 = { 0 };
193 final long[] freeMem0 = { 0 };
194 final long[] usedMem1 = { 0 };
195 final long[] freeMem1 = { 0 };
196
197 final String prefix = "test #"+iter+" "+String.format(PrintPrecision+" MiB", expSize/MIB);
198 System.err.printf("%s: mode %-5s, bufferSize %9d: BEGIN%n", prefix, srcType.toString(), bufferSize);
199 dumpMem(prefix+" before", runtime, -1, -1, usedMem0, freeMem0 );
200
201 final IOException[] ioe = { null };
202 OutOfMemoryError oome = null;
203 InputStream bis = null;
204 FileInputStream fis = null;
205 FileChannel fic = null;
206 boolean isMappedByteBufferInputStream = false;
207 try {
208 fis = new FileInputStream(testFile);
209 if( SrcType.COPY == srcType ) {
210 if( hasSize1 > Integer.MAX_VALUE ) {
211 fis.close();
212 throw new IllegalArgumentException("file size > MAX_INT for "+srcType+": "+hasSize1+" of "+testFile);
213 }
214 bis = new BufferedInputStream(fis, bufferSize);
215 } else if( SrcType.MMAP1 == srcType ) {
216 if( hasSize1 > Integer.MAX_VALUE ) {
217 fis.close();
218 throw new IllegalArgumentException("file size > MAX_INT for "+srcType+": "+hasSize1+" of "+testFile);
219 }
220 fic = fis.getChannel();
221 final MappedByteBuffer fmap = fic.map(FileChannel.MapMode.READ_ONLY, 0, hasSize1); // survives channel/stream closing until GC'ed!
222 bis = new ByteBufferInputStream(fmap);
223 } else {
224 isMappedByteBufferInputStream = true;
225 MappedByteBufferInputStream.CacheMode cmode;
226 switch(srcType) {
227 case MMAP2_NONE: cmode = MappedByteBufferInputStream.CacheMode.FLUSH_NONE;
228 break;
229 case MMAP2_SOFT: cmode = MappedByteBufferInputStream.CacheMode.FLUSH_PRE_SOFT;
230 break;
231 case MMAP2_HARD: cmode = MappedByteBufferInputStream.CacheMode.FLUSH_PRE_HARD;
232 break;
233 default: fis.close();
234 throw new InternalError("XX: "+srcType);
235 }
236 final MappedByteBufferInputStream mis = new MappedByteBufferInputStream(fis.getChannel(), FileChannel.MapMode.READ_ONLY, cmode);
237 Assert.assertEquals(expSize, mis.remaining());
238 Assert.assertEquals(expSize, mis.length());
239 Assert.assertEquals(0, mis.position());
240 bis = mis;
241 }
242 } catch (final IOException e) {
243 if( e.getCause() instanceof OutOfMemoryError ) {
244 oome = (OutOfMemoryError) e.getCause(); // oops
245 } else {
246 ioe[0] = e;
247 }
248 } catch (final OutOfMemoryError m) {
249 oome = m; // oops
250 }
251 IOException ioe2 = null;
252 try {
253 if( null != ioe[0] || null != oome ) {
254 if( null != oome ) {
255 System.err.printf("%s: mode %-5s, bufferSize %9d: OutOfMemoryError.1 %s%n",
256 prefix, srcType.toString(), bufferSize, oome.getMessage());
257 oome.printStackTrace();
258 } else {
259 Assert.assertNull(ioe[0]);
260 }
261 return false;
262 }
263 Assert.assertEquals(expSizeI, bis.available());
264
265 final long t1 = System.currentTimeMillis();
266
267 final File out = new File(fileOut);
268 IOUtil.copyStream2File(bis, out);
269 final long t2 = System.currentTimeMillis();
270
271 final String suffix;
272 if( isMappedByteBufferInputStream ) {
273 suffix = ", cacheMode "+((MappedByteBufferInputStream)bis).getCacheMode();
274 } else {
275 suffix = "";
276 }
277 System.err.printf("%s: mode %-5s, bufferSize %9d: total %5d, setup %5d, copy %5d ms%s%n",
278 prefix, srcType.toString(), bufferSize, t2-t0, t1-t0, t2-t1, suffix);
279
280 Assert.assertEquals(expSize, out.length());
281 out.delete();
282
283 Assert.assertEquals(0, bis.available());
284 if( isMappedByteBufferInputStream ) {
285 final MappedByteBufferInputStream mis = (MappedByteBufferInputStream)bis;
286 Assert.assertEquals(0, mis.remaining());
287 Assert.assertEquals(expSize, mis.length());
288 Assert.assertEquals(expSize, mis.position());
289 }
290 dumpMem(prefix+" after ", runtime, usedMem0[0], freeMem0[0], usedMem1, freeMem1 );
291 System.gc();
292 try {
293 Thread.sleep(500);
294 } catch (final InterruptedException e) { }
295 dumpMem(prefix+" gc'ed ", runtime, usedMem0[0], freeMem0[0], usedMem1, freeMem1 );
296 } catch( final IOException e ) {
297 if( e.getCause() instanceof OutOfMemoryError ) {
298 oome = (OutOfMemoryError) e.getCause(); // oops
299 } else {
300 ioe2 = e;
301 }
302 } catch (final OutOfMemoryError m) {
303 oome = m; // oops
304 } finally {
305 if( null != fic ) {
306 fic.close();
307 }
308 if( null != fis ) {
309 fis.close();
310 }
311 if( null != bis ) {
312 bis.close();
313 }
314 System.err.printf("%s: mode %-5s, bufferSize %9d: END%n", prefix, srcType.toString(), bufferSize);
315 System.err.println();
316 }
317 if( null != ioe2 || null != oome ) {
318 if( null != oome ) {
319 System.err.printf("%s: mode %-5s, bufferSize %9d: OutOfMemoryError.2 %s%n",
320 prefix, srcType.toString(), bufferSize, oome.getMessage());
321 oome.printStackTrace();
322 } else {
323 Assert.assertNull(ioe2);
324 }
325 return false;
326 } else {
327 return true;
328 }
329 }
330
331 public static void dumpMem(final String pre,
332 final Runtime runtime, final long usedMem0,
333 final long freeMem0, final long[] usedMemN,
334 final long[] freeMemN )
335 {
336 usedMemN[0] = runtime.totalMemory() - runtime.freeMemory();
337 freeMemN[0] = runtime.freeMemory();
338
339 System.err.printf("%s Used Memory : "+PrintPrecision, pre, usedMemN[0] / MIB);
340 if( 0 < usedMem0 ) {
341 System.err.printf(", delta "+PrintPrecision, (usedMemN[0]-usedMem0) / MIB);
342 }
343 System.err.println(" MiB");
344 /**
345 System.err.printf("%s Free Memory : "+printPrecision, pre, freeMemN[0] / mib);
346 if( 0 < freeMem0 ) {
347 System.err.printf(", delta "+printPrecision, (freeMemN[0]-freeMem0) / mib);
348 }
349 System.err.println(" MiB"); */
350 }
351
352 static boolean manualTest = false;
353
354 public static void main(final String args[]) throws IOException {
355 for(int i=0; i<args.length; i++) {
356 if(args[i].equals("-manual")) {
357 manualTest = true;
358 }
359 }
360 final String tstname = TestByteBufferInputStream.class.getName();
361 org.junit.runner.JUnitCore.main(tstname);
362 }
363}
Testing serial read of ByteBufferInputStream and MappedByteBufferInputStream, i.e.
static void dumpMem(final String pre, final Runtime runtime, final long usedMem0, final long freeMem0, final long[] usedMemN, final long[] freeMemN)
Utility class for querying platform specific properties.
Definition: Platform.java:58
static OSType getOSType()
Returns the OS type.
Definition: Platform.java:401