├── .gitignore
├── .travis.jvmopts
├── .travis.yml
├── LICENSE
├── Makefile
├── Makefile.common
├── README.md
├── bin
└── apply_license.rb
├── build.sbt
├── include
├── inc_linux
│ └── jni_md.h
├── inc_mac
│ ├── jni.h
│ └── jni_md.h
└── inc_win
│ ├── jni.h
│ └── jni_md.h
├── larray-buffer
└── src
│ ├── main
│ └── java
│ │ └── xerial
│ │ └── larray
│ │ └── buffer
│ │ ├── DefaultMemoryAllocator.java
│ │ ├── LBuffer.java
│ │ ├── LBufferAPI.java
│ │ ├── LBufferConfig.java
│ │ ├── Memory.java
│ │ ├── MemoryAllocator.java
│ │ ├── MemoryReference.java
│ │ ├── OffHeapMemory.java
│ │ ├── OffHeapMemoryReference.java
│ │ ├── UnsafeUtil.java
│ │ ├── WrappedLBuffer.java
│ │ └── WritableChannelWrap.java
│ └── test
│ └── scala
│ └── xerial
│ └── larray
│ ├── DataUnit.scala
│ ├── LArraySpec.scala
│ └── buffer
│ ├── LBufferTest.scala
│ ├── MemoryAllocatorTest.scala
│ └── WrappedLBufferTest.scala
├── larray-mmap
└── src
│ ├── main
│ ├── java
│ │ └── xerial
│ │ │ └── larray
│ │ │ ├── impl
│ │ │ ├── LArrayLoader.java
│ │ │ ├── LArrayNative.c
│ │ │ ├── LArrayNative.h
│ │ │ ├── LArrayNative.java
│ │ │ └── OSInfo.java
│ │ │ └── mmap
│ │ │ ├── MMapBuffer.java
│ │ │ ├── MMapMemory.java
│ │ │ ├── MMapMemoryReference.java
│ │ │ └── MMapMode.java
│ └── resources
│ │ └── xerial
│ │ └── larray
│ │ ├── VERSION
│ │ └── native
│ │ ├── Linux
│ │ ├── amd64
│ │ │ └── liblarray.so
│ │ ├── arm
│ │ │ └── liblarray.so
│ │ ├── armhf
│ │ │ └── liblarray.so
│ │ └── i386
│ │ │ └── liblarray.so
│ │ ├── Mac
│ │ └── x86_64
│ │ │ └── liblarray.jnilib
│ │ └── Windows
│ │ ├── amd64
│ │ └── larray.dll
│ │ └── x86
│ │ └── larray.dll
│ └── test
│ └── scala
│ └── xerial
│ └── larray
│ └── impl
│ └── LArrayLoaderTest.scala
├── larray
└── src
│ ├── main
│ ├── java
│ │ └── xerial
│ │ │ └── larray
│ │ │ └── japi
│ │ │ └── LArrayJ.java
│ └── scala
│ │ └── xerial
│ │ └── larray
│ │ ├── AltLArray.scala
│ │ ├── LArray.scala
│ │ ├── LArray2D.scala
│ │ ├── LArrayBuilder.scala
│ │ ├── LArrayInputStream.scala
│ │ ├── LArrayOutputStream.scala
│ │ ├── LArrayView.scala
│ │ ├── LBitArray.scala
│ │ ├── LByteBuffer.scala
│ │ ├── LIterable.scala
│ │ ├── LIterator.scala
│ │ ├── MappedLByteArray.scala
│ │ ├── UInt32Array.scala
│ │ ├── UnsafeUtil.scala
│ │ ├── example
│ │ ├── LArrayExample.scala
│ │ └── LArrayJavaExample.java
│ │ ├── package.scala
│ │ └── util
│ │ └── Logger.scala
│ ├── multi-jvm
│ └── scala
│ │ └── xerial
│ │ └── larray
│ │ └── SharedMemory.scala
│ └── test
│ ├── java
│ └── xerial
│ │ └── larray
│ │ └── japi
│ │ ├── JLArrayTest.java
│ │ └── JSnappyCompressTest.java
│ └── scala
│ └── xerial
│ └── larray
│ ├── IOPerfTest.scala
│ ├── LArrayBuilderTest.scala
│ ├── LArrayFunctionTest.scala
│ ├── LArrayInputStreamTest.scala
│ ├── LArraySpec.scala
│ ├── LArrayTest.scala
│ ├── LArrayTestWithPBT.scala
│ ├── LBitArrayTest.scala
│ ├── MappedLByteArrayTest.scala
│ ├── SnappyCompressTest.scala
│ ├── UInt32ArrayTest.scala
│ └── example
│ └── LArrayExampleTest.scala
├── project
├── build.properties
└── plugins.sbt
├── sbt
└── version.sbt
/.gitignore:
--------------------------------------------------------------------------------
1 | *.class
2 | *.log
3 | *~
4 |
5 | # sbt specific
6 | bin/.lib
7 | dist/*
8 | target/
9 | lib_managed/
10 | src_managed/
11 | project/boot/
12 | project/plugins/project/
13 | larray/src/test/resources/log-test.properties
14 |
15 | # Scala-IDE specific
16 | .scala_dependencies
17 |
18 | # IntelliJ specific
19 | .idea*
20 |
--------------------------------------------------------------------------------
/.travis.jvmopts:
--------------------------------------------------------------------------------
1 | -Dfile.encoding=UTF8
2 | -Xms1536m
3 | -Xmx1536m
4 | -Xss6M
5 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: scala
2 | scala:
3 | - 2.11.8
4 | - 2.12.1
5 |
6 | sudo: false
7 |
8 | script:
9 | - ./sbt ++$TRAVIS_SCALA_VERSION -jvm-opts .travis.jvmopts "; clean; test"
10 |
11 | # These directories are cached to S3 at the end of the build
12 | cache:
13 | directories:
14 | - $HOME/.ivy2/cache
15 | - $HOME/.sbt/boot/
16 |
17 | before_cache:
18 | # Tricks to avoid unnecessary cache updates
19 | - find $HOME/.ivy2 -name "ivydata-*.properties" -delete
20 | - find $HOME/.sbt -name "*.lock" -delete
21 |
22 | jdk:
23 | - oraclejdk8
24 |
25 | addons:
26 | apt:
27 | packages:
28 | - oracle-java8-installer
29 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 |
2 | all: larray
3 |
4 | include Makefile.common
5 |
6 |
7 | SRC:=larray-mmap/src/main/java
8 |
9 | LARRAY_OUT:=$(TARGET)/larray-$(os_arch)
10 | LARRAY_SRC_DIR:=$(SRC)/xerial/larray/impl
11 | LARRAY_SRC:=$(shell find $(LARRAY_SRC_DIR))
12 | LARRAY_OBJ:=$(LARRAY_OUT)/LArrayNative.o
13 |
14 | VERSION:=$(shell perl -npe "s/version in ThisBuild\s+:=\s+\"(.*)\"/\1/" version.sbt | sed -e "/^$$/d")
15 |
16 |
17 | CFLAGS:=$(CFLAGS) -I$(LARRAY_SRC_DIR)
18 |
19 | LARRAY_HEADER:=$(SRC)/xerial/larray/impl/LArrayNative.h
20 |
21 | $(TARGET)/classes/xerial/larray/impl/%.class : $(LARRAY_SRC_DIR)/%.java
22 | $(JAVAC) -sourcepath $(SRC) -d $(TARGET)/classes $<
23 |
24 | jni-header: $(LARRAY_HEADER)
25 |
26 | $(LARRAY_HEADER): $(SRC)/xerial/larray/impl/LArrayNative.java $(TARGET)/classes/xerial/larray/impl/LArrayNative.class
27 | @mkdir -p $(TARGET)/classes
28 | $(JAVAH) -classpath $(TARGET)/classes -o $@ xerial.larray.impl.LArrayNative
29 |
30 |
31 | $(LARRAY_OUT)/%.o : $(LARRAY_SRC_DIR)/%.c
32 | @mkdir -p $(@D)
33 | $(CC) $(CFLAGS) -c $< -o $@
34 |
35 | $(LARRAY_OUT)/$(LIBNAME): $(LARRAY_OBJ)
36 | $(CC) $(CFLAGS) -o $@ $+ $(LINKFLAGS)
37 | $(STRIP) $@
38 |
39 | clean-native:
40 | rm -rf $(LARRAY_OUT)
41 |
42 | clean:
43 | rm -rf $(TARGET)
44 |
45 | NATIVE_DIR:=larray-mmap/src/main/resources/xerial/larray/native/$(OS_NAME)/$(OS_ARCH)
46 | NATIVE_TARGET_DIR:=$(TARGET)/classes/xerial/native/$(OS_NAME)/$(OS_ARCH)
47 | NATIVE_DLL:=$(NATIVE_DIR)/$(LIBNAME)
48 |
49 | native: osinfo $(NATIVE_DLL)
50 | larray: native $(TARGET)/larray-$(VERSION).jar
51 |
52 | SBT:=./sbt
53 |
54 | $(NATIVE_DLL): $(LARRAY_OUT)/$(LIBNAME)
55 | @mkdir -p $(@D)
56 | cp $< $@
57 | @mkdir -p $(NATIVE_TARGET_DIR)
58 | cp $< $(NATIVE_TARGET_DIR)/$(LIBNAME)
59 |
60 | $(TARGET)/larray-$(VERSION).jar: native $(NATIVE_DLL)
61 | $(SBT) package
62 |
63 | test: $(NATIVE_DLL)
64 | $(SBT) test
65 |
66 | win32:
67 | $(MAKE) native CROSS_PREFIX=i686-w64-mingw32- OS_NAME=Windows OS_ARCH=x86
68 |
69 | # for cross-compilation on Ubuntu, install the g++-mingw-w64-x86-64 package
70 | win64:
71 | $(MAKE) native CROSS_PREFIX=x86_64-w64-mingw32- OS_NAME=Windows OS_ARCH=amd64
72 |
73 | mac32:
74 | $(MAKE) native OS_NAME=Mac OS_ARCH=i386
75 |
76 | linux32:
77 | $(MAKE) native OS_NAME=Linux OS_ARCH=i386
78 |
79 | # for cross-compilation on Ubuntu, install the g++-arm-linux-gnueabi package
80 | linux-arm:
81 | $(MAKE) native CROSS_PREFIX=arm-linux-gnueabi- OS_NAME=Linux OS_ARCH=arm
82 |
83 | # for cross-compilation on Ubuntu, install the g++-arm-linux-gnueabihf package
84 | linux-armhf:
85 | $(MAKE) native CROSS_PREFIX=arm-linux-gnueabihf- OS_NAME=Linux OS_ARCH=armhf
86 |
87 | clean-native-linux32:
88 | $(MAKE) clean-native OS_NAME=Linux OS_ARCH=i386
89 |
90 | clean-native-win32:
91 | $(MAKE) clean-native OS_NAME=Windows OS_ARCH=x86
92 |
93 |
--------------------------------------------------------------------------------
/Makefile.common:
--------------------------------------------------------------------------------
1 | TARGET:=larray-mmap/target
2 | SRC:=larray-mmap/src/main/java
3 |
4 | ifndef JAVA_HOME
5 | $(error Set JAVA_HOME environment variable)
6 | endif
7 |
8 | JAVA := "$$JAVA_HOME/bin/java"
9 | JAVAC := "$$JAVA_HOME/bin/javac"
10 | JAVAH := "$$JAVA_HOME/bin/javah"
11 |
12 | UTIL:=$(TARGET)/util
13 |
14 | OSINFO_CLASS := xerial.larray.impl.OSInfo
15 | OSINFO_PROG := $(UTIL)/xerial/larray/impl/OSInfo.class
16 |
17 | ## building OSInfo.java
18 | osinfo: $(OSINFO_PROG)
19 |
20 | $(OSINFO_PROG):
21 | -mkdir -p $(@D)
22 | $(info compiling OSInfo.java)
23 | $(JAVAC) $(SRC)/xerial/larray/impl/OSInfo.java -d $(UTIL)
24 |
25 | OS_NAME := $(shell $(JAVA) -cp $(UTIL) $(OSINFO_CLASS) --os)
26 | OS_ARCH := $(shell $(JAVA) -cp $(UTIL) $(OSINFO_CLASS) --arch)
27 |
28 | # Windows uses different path separator-)
29 | ifeq ($(OS_NAME),Windows)
30 | sep := ;
31 | else
32 | sep := :
33 | endif
34 |
35 |
36 | jni_md := $(shell find -L "$(JAVA_HOME)" -name jni_md.h)
37 | ifneq ($(jni_md),)
38 | jni_include := $(shell dirname "$(jni_md)")
39 | endif
40 |
41 |
42 | # os=Default is meant to be generic unix/linux
43 |
44 | known_os_archs := Linux-i386 Linux-amd64 Linux-arm Linux-armhf Mac-i386 Mac-x86_64 Windows-x86 Windows-amd64
45 | os_arch := $(OS_NAME)-$(OS_ARCH)
46 |
47 | ifeq (,$(findstring $(strip $(os_arch)),$(known_os_archs)))
48 | os_arch := Default
49 | endif
50 |
51 | # cross-compilation toolchain prefix (e.g. "arm-linux-gnueabi-")
52 | CROSS_PREFIX :=
53 |
54 | Default_CC := $(CROSS_PREFIX)gcc
55 | Default_STRIP := $(CROSS_PREFIX)strip
56 | Default_CFLAGS := -I$(JAVA_HOME)/include -Iinclude/inc_mac -O2 -fPIC -fvisibility=hidden
57 | Default_LINKFLAGS := -shared -static
58 | Default_LIBNAME := liblarray.so
59 |
60 | Linux-i386_CC := $(CROSS_PREFIX)gcc
61 | Linux-i386_STRIP := $(CROSS_PREFIX)strip
62 | Linux-i386_CFLAGS := -include include/inc_linux/jni_md.h -I$(JAVA_HOME)/include -O2 -fPIC -fvisibility=hidden -m32
63 | Linux-i386_LINKFLAGS := -shared -static-libgcc
64 | Linux-i386_LIBNAME := liblarray.so
65 |
66 | Linux-amd64_CC := $(CROSS_PREFIX)gcc
67 | Linux-amd64_STRIP := $(CROSS_PREFIX)strip
68 | Linux-amd64_CFLAGS := -include include/inc_linux/jni_md.h -I$(JAVA_HOME)/include -O2 -fPIC -fvisibility=hidden -m64
69 | Linux-amd64_LINKFLAGS := -shared -static-libgcc
70 | Linux-amd64_LIBNAME := liblarray.so
71 |
72 | # '-include lib/inc_linux/jni_md.h' is used to force the use of our version,
73 | # which defines JNIEXPORT differently; otherwise, since OpenJDK includes
74 | # jni_md.h in same directory as jni.h, the include path is ignored when
75 | # jni_md.h is included from jni.h
76 |
77 | Linux-arm_CC := $(CROSS_PREFIX)gcc
78 | Linux-arm_STRIP := $(CROSS_PREFIX)strip
79 | Linux-arm_CFLAGS := -include include/inc_linux/jni_md.h -I$(JAVA_HOME)/include -O2 -fPIC -fvisibility=hidden -mfloat-abi=softfp
80 | Linux-arm_LINKFLAGS := -shared -static-libgcc
81 | Linux-arm_LIBNAME := liblarray.so
82 |
83 | Linux-armhf_CC := $(CROSS_PREFIX)gcc
84 | Linux-armhf_STRIP := $(CROSS_PREFIX)strip
85 | Linux-armhf_CFLAGS := -include include/inc_linux/jni_md.h -I$(JAVA_HOME)/include -O2 -fPIC -fvisibility=hidden -mfloat-abi=hard
86 | Linux-armhf_LINKFLAGS := -shared -static-libgcc
87 | Linux-armhf_LIBNAME := liblarray.so
88 |
89 | Mac-i386_CC := gcc -arch $(OS_ARCH)
90 | Mac-i386_STRIP := strip -x
91 | Mac-i386_CFLAGS := -Iinclude/inc_mac -I$(JAVA_HOME)/include -O2 -fPIC -mmacosx-version-min=10.4 -fvisibility=hidden
92 | Mac-i386_LINKFLAGS := -dynamiclib -static-libgcc
93 | Mac-i386_LIBNAME := liblarray.jnilib
94 |
95 | Mac-x86_64_CC := gcc -arch $(OS_ARCH)
96 | Mac-x86_64_STRIP := strip -x
97 | Mac-x86_64_CFLAGS := -Iinclude/inc_mac -I$(JAVA_HOME)/include -O2 -fPIC -mmacosx-version-min=10.5 -fvisibility=hidden
98 | Mac-x86_64_LINKFLAGS := -dynamiclib
99 | Mac-x86_64_LIBNAME := liblarray.jnilib
100 |
101 | Windows-x86_CC := $(CROSS_PREFIX)gcc
102 | Windows-x86_STRIP := $(CROSS_PREFIX)strip
103 | Windows-x86_CFLAGS := -Iinclude/inc_win -O2
104 | Windows-x86_LINKFLAGS := -Wl,--kill-at -shared -static
105 | Windows-x86_LIBNAME := larray.dll
106 |
107 | Windows-amd64_CC := $(CROSS_PREFIX)gcc
108 | Windows-amd64_STRIP := $(CROSS_PREFIX)strip
109 | Windows-amd64_CFLAGS := -Iinclude/inc_win -O2
110 | Windows-amd64_LINKFLAGS := -Wl,--kill-at -shared -static
111 | Windows-amd64_LIBNAME := larray.dll
112 |
113 |
114 | CC := $($(os_arch)_CC)
115 | STRIP := $($(os_arch)_STRIP)
116 | CFLAGS := $($(os_arch)_CFLAGS)
117 | LINKFLAGS := $($(os_arch)_LINKFLAGS)
118 | LIBNAME := $($(os_arch)_LIBNAME)
119 |
120 |
121 | CFLAGS := $(CFLAGS) -Iinclude
122 | ifneq ($(jni_include),)
123 | CFLAGS := $(CFLAGS) -I"$(jni_include)"
124 | endif
125 |
126 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | LArray [](https://maven-badges.herokuapp.com/maven-central/org.xerial.larray/larray_2.12/) [](https://travis-ci.org/xerial/larray)
2 | ===
3 | A library for managing large off-heap arrays that can hold more than 2G (2^31) entries in Java and Scala. Notably LArray is *disposable* by calling `LArray.free`. Even if you forget to release it, GC will automatically deallocate the memory acquired by LArray. LArray also supports `mmap` (memory-mapped file) whose size is more than 2GB.
4 |
5 | ## Features
6 | * LArray can create arrays with more than 2G(2^31) entries.
7 | * 2^31 -1 (2G) is the limitation of the default Java/Scala array size, because these arrays use 32-bit signed integer (int) as indexes. LArray uses long type indexes of 64-bit signed integers to resolve this limitation.
8 | * For example, the entire human genome data (3GB) can be stored in LArray.
9 | * LArray can be released immediately from the memory.
10 | * Call `LArray.free`.
11 | * The default arrays in Java/Scala stay in JVM heaps until they are collected by GC, so it is generally difficult to avoid `OutOfMemoryException` when working with large amount of data. For example, call `new Array[Int](1000)` x 10,000 times. You are lucky if you don't see OutOfMemoryException.
12 | * LArray can be collected by Garbage Collector (GC)
13 | * Even if you forget to call LArray.free, the acquired memory will be released when GC sweeps LArray instances.
14 | * To prevent accidental memory release, keep a reference to LArray somewhere (e.g., in List) as in the standard Java/Scala program.
15 | * LArray resides in off-heap memory
16 | * LArray uses a memory space outside the JVM heap, so creating LArrays with more than -Xmx(maximum heap size) is possible. This is useful when you need large amount of memory, or it is unknown how much memory is required in your application.
17 | * Fast memory allocation
18 | * LArray internally uses a concurrent memory allocator suited to multi-threaded programs, which is faster than the default JVM memory allocator.
19 | * LArray by default skips the array initialization (zero-filling), which improves the memory allocation speed significantly.
20 | * LArray can be used as DirectBuffer
21 | * Enables zero-copy transfer to/from files, network, etc.
22 | * Zero-copy compression with [snappy-java](https://github.com/xerial/snappy-java) (supported since version 1.1.0-M4. Pass LArray.address to Snappy.rawCompress etc.)
23 | * Rich set of operations for LArray[A]
24 | * map, filter, reduce, zip, etc. Almost all collection operations in Scala are already implemented for LArray[A].
25 | * Supports Memory-mapped file larger than 2GB
26 | * Use `LArray.mmap`
27 | * It can create memory regions that can be shared between processes.
28 |
29 | ## Limitations
30 |
31 | * LArray[A] of generic objects (e.g., LArray[String], LArray[AnyRef]) cannot be released immedeately from the main memory, because objects other than primitive types need to be created on JVM heaps and they are under the control of GC.
32 | * To release objects from main memory, you need to create *off-heap* objects. For example, create a large `LArray[Byte]`, then align your object data on the array. Object parameters can be retrieved with `LArray[Byte].getInt(offset)`, `getFloat(offset)`, etc.
33 |
34 |
35 | ## Performance
36 |
37 | ### Memory allocation
38 | Here is a simple benchmark result that compares concurrent memory-allocation performances of LArray (with or without zero-filling), java arrays, `ByteBuffer.allocate` and `ByteBuffer.allocateDirect`, using Mac OS X with 2.9GHz Intelli Core i7. This test allocates 100 x 1MB of memory space concurrently using multiple threads, and repeats this process 20 times.
39 |
40 | ```
41 | -concurrent allocation total:2.426 sec. , count: 10, avg:0.243 sec. , core avg:0.236 sec. , min:0.159 sec. , max:0.379 sec.
42 | -without zero-filling total:0.126 sec. , count: 20, avg:6.279 msec., core avg:2.096 msec., min:1.405 msec., max:0.086 sec.
43 | -with zero-filling total:0.476 sec. , count: 20, avg:0.024 sec. , core avg:0.023 sec. , min:0.017 sec. , max:0.037 sec.
44 | -java array total:0.423 sec. , count: 20, avg:0.021 sec. , core avg:0.021 sec. , min:0.014 sec. , max:0.029 sec.
45 | -byte buffer total:1.028 sec. , count: 20, avg:0.051 sec. , core avg:0.044 sec. , min:0.014 sec. , max:0.216 sec.
46 | -direct byte buffer total:0.360 sec. , count: 20, avg:0.018 sec. , core avg:0.018 sec. , min:0.015 sec. , max:0.026 sec.
47 | ```
48 |
49 | All allocators except LArray are orders of magnitude slower than LArray, and consumes CPUs because they need to fill the allocated memory with zeros due to their specification.
50 |
51 | In a single thread execution, you can see more clearly how fast LArray can allocate memories.
52 | ```
53 | -single-thread allocation total:3.655 sec. , count: 10, avg:0.366 sec. , core avg:0.356 sec. , min:0.247 sec. , max:0.558 sec.
54 | -without zero-filling total:0.030 sec. , count: 20, avg:1.496 msec., core avg:1.125 msec., min:0.950 msec., max:8.713 msec.
55 | -with zero-filling total:0.961 sec. , count: 20, avg:0.048 sec. , core avg:0.047 sec. , min:0.044 sec. , max:0.070 sec.
56 | -java array total:0.967 sec. , count: 20, avg:0.048 sec. , core avg:0.037 sec. , min:0.012 sec. , max:0.295 sec.
57 | -byte buffer total:0.879 sec. , count: 20, avg:0.044 sec. , core avg:0.033 sec. , min:0.014 sec. , max:0.276 sec.
58 | -direct byte buffer total:0.812 sec. , count: 20, avg:0.041 sec. , core avg:0.041 sec. , min:0.032 sec. , max:0.049 sec.
59 | ```
60 |
61 | ### Snappy Compression
62 |
63 | LArray (and LBuffer) has memory address that can be used for seamlessly interacting with fast native methods through JNI. Here is an example of using `rawCompress(...)` in [snappy-java](http://github.com/xerial/snappy-java), which can take raw-memory address to compress/uncompress the data using C++ code, and is generally faster than [Dain's pure-java version of Snappy](http://github.com/dain/snappy).
64 |
65 | ```
66 | [SnappyCompressTest]
67 | -compress total:0.017 sec. , count: 10, avg:1.669 msec., core avg:0.769 msec., min:0.479 msec., max:0.010 sec.
68 | -LBuffer -> LBuffer (raw) total:1.760 msec., count: 50, avg:0.035 msec., core avg:0.030 msec., min:0.024 msec., max:0.278 msec.
69 | -Array -> Array (raw) total:1.450 msec., count: 50, avg:0.029 msec., core avg:0.027 msec., min:0.023 msec., max:0.110 msec.
70 | -Array -> Array (dain) total:0.011 sec. , count: 50, avg:0.225 msec., core avg:0.141 msec., min:0.030 msec., max:4.441 msec.
71 | [SnappyCompressTest]
72 | -decompress total:7.722 msec., count: 10, avg:0.772 msec., core avg:0.473 msec., min:0.418 msec., max:3.521 msec.
73 | -LBuffer -> LBuffer (raw) total:1.745 msec., count: 50, avg:0.035 msec., core avg:0.029 msec., min:0.020 msec., max:0.331 msec.
74 | -Array -> Array (raw) total:1.189 msec., count: 50, avg:0.024 msec., core avg:0.021 msec., min:0.018 msec., max:0.149 msec.
75 | -Array -> Array (dain) total:2.571 msec., count: 50, avg:0.051 msec., core avg:0.027 msec., min:0.025 msec., max:1.240 msec.
76 | ```
77 |
78 | * [Test code](larray/src/test/scala/xerial/larray/SnappyCompressTest.scala)
79 |
80 |
81 |
82 | ## Modules
83 |
84 | LArray consists of three-modules.
85 |
86 | * **larray-buffer** (Java) Off-heap memory buffer `LBuffer` and its allocator with GC support.
87 | * **larray-mmap** (Java + JNI (C code)) Memory-mapped file implementation `MMapBuffer`
88 | * **larray** (Scala and Java API) Provides rich set of array operations through `LArray` interface.
89 |
90 | You can use each module independently. For example, if you only need an off-heap memory allocator that collects memory upon GC, use `LBuffer` in **larray-buffer**.
91 |
92 | Simply you can include **larray** to the dependency in Maven or SBT so that all modules will be added to your classpaths.
93 |
94 | ## Supported Platforms
95 |
96 | A standard JVM, (e.g. Oracle JVM (standard JVM, HotSpotVM) or OpenJDK) must be used since
97 | **larray-buffer** depends on `sun.misc.Unsafe` class to allocate off-heap memory.
98 |
99 | **larray-mmap** (MMapBuffer and LArray.mmap) uses JNI and is available for the following major CPU architectures:
100 |
101 | * Windows (32/64-bit)
102 | * Linux (i368, amd64 (Intel 64-bit), arm, armhf)
103 | * Mac OSX (Intel 64bit)
104 |
105 |
106 | ## History
107 | * 2016-12-13: vesrion 0.4.0 - Fix #52. Support Scala 2.12. Use [wvlet-log](https://github.com/wvlet/log) for internal logging.
108 | * 2016-05-12: version 0.3.4 - Minor performance improvement release
109 | * 2016-03-04: version 0.3.3 - Add Scala 2.11.7, 2.10.6 support
110 | * March 4th, 2016 version 0.3.0 - Scala 2.11.7 support
111 | * November 11, 2013 version 0.2.1 - Use orgnization name `org.xerial.larray`. Add LBuffer.view.
112 | * November 11, 2013 version 0.2 - Extracted pure-java modules (larray-buffer.jar and larray-mmap.jar) from larray.jar (for Scala).
113 | * August 28, 2013 version 0.1.2 - improved memory layout
114 | * August 28, 2013 version 0.1.1 (for Scala 2.10.2)
115 | * Apr 23, 2013 Released version 0.1
116 |
117 | ## Usage (Scala)
118 |
119 | ### sbt settings
120 | Add the following sbt dependency to your project settings:
121 |
122 | ```scala
123 | libraryDependencies += "org.xerial.larray" %% "larray" % "0.4.0"
124 | ```
125 |
126 | * Using snapshot versions:
127 |
128 | ```scala
129 | resolvers += "Sonatype shapshot repo" at "https://oss.sonatype.org/content/repositories/snapshots/"
130 |
131 | libraryDependencies += "org.xerial.larray" %% "larray" % "0.4.1-SNAPSHOT"
132 | ```
133 | ### Example
134 |
135 | LArray can be used in the same manner with the standard Scala Arrays:
136 |
137 | ```scala
138 | import xerial.larray._
139 |
140 | val l = LArray(1, 2, 3)
141 | val e = l(0) // 1
142 | println(l.mkString(", ")) // 1, 2, 3
143 | l(1) = 5
144 | println(l.mkString(", ")) // 1, 5, 3
145 |
146 | // Create an LArray of Int type
147 | val l2 = LArray.of[Int](10000L)
148 |
149 | // Release the memory resource
150 | l2.free
151 |
152 | l2(0) // The result of accessing released LArray is undefined
153 | ```
154 |
155 | For more examples, see [xerial/larray/example/LArrayExample.scala](larray/src/main/scala/xerial/larray/example/LArrayExample.scala)
156 |
157 | ## Usage (Java)
158 |
159 | Add the following dependency to your pom.xml (Maven):
160 | ```xml
161 |
162 | org.xerial.larray
163 | larray_2.12
164 | 0.4.0
165 |
166 | ```
167 |
168 | ### Example
169 |
170 | In Java we cannot provide concise syntaxes as in Scala. Instead, use `apply` and `update` methods to read/write values in an array.
171 |
172 | ```java
173 | import xerial.larray.japi.LArrayJ;
174 | import xerial.larray.*;
175 |
176 | LIntArray l = LArrayJ.newLIntArray(10000L);
177 | l.update(0L, 20); // Set l[0L] = 20
178 | int e0 = l.apply(0L); // Get l[0L]
179 |
180 | // release
181 | l.free();
182 | ```
183 | For more examples, see [xerial/larray/example/LArrayJavaExample.java](larray/src/main/scala/xerial/larray/example/LArrayJavaExample.java)
184 |
185 | ## Scaladoc
186 |
187 | * [LArray Scala API](https://oss.sonatype.org/service/local/repositories/releases/archive/org/xerial/larray/larray_2.12/0.4.0/larray_2.12-0.4.0-javadoc.jar/!/index.html#xerial.larray.package)
188 | * [larray-buffer Java API](https://oss.sonatype.org/service/local/repositories/releases/archive/org/xerial/larray/larray-buffer/0.4.0/larray-buffer-0.4.0-javadoc.jar/!/index.html#)
189 | * [larray-mmap Java API](https://oss.sonatype.org/service/local/repositories/releases/archive/org/xerial/larray/larray-mmap/0.4.0/larray-mmap-0.4.0-javadoc.jar/!/index.html?xerial/larray/mmap/package-summary.html)
190 |
191 | ## For developers
192 |
193 | * Building LArray: `./sbt compile`
194 | * Run tests: `./sbt ~test`
195 | * Creating IntelliJ IDEA project: `./sbt gen-idea`
196 |
197 |
198 |
--------------------------------------------------------------------------------
/bin/apply_license.rb:
--------------------------------------------------------------------------------
1 |
2 | require 'tempfile'
3 | require 'fileutils'
4 | require 'nkf'
5 |
6 | Dir["src/**/*.{scala,java}"].each { |file|
7 | lines = open(file) { |f| f.readlines }
8 | next if lines[1].include?("Copyright")
9 |
10 | out = Tempfile.new("tempfile")
11 | puts "apply license to #{file}"
12 | license = < false },
16 | scalaVersion := SCALA_VERSION,
17 | crossScalaVersions := CROSS_SCALA_VERSIONS,
18 | logBuffered in Test := false,
19 | parallelExecution := true,
20 | parallelExecution in Test := false,
21 | javacOptions in Compile ++= Seq("-Xlint:unchecked"),
22 | javacOptions in(Compile, doc) := Seq(
23 | "-locale", "en_US",
24 | "-sourcepath", baseDirectory.value.getAbsolutePath,
25 | "-doctitle", s"LArray ${version.value} API"
26 | ),
27 | scalacOptions ++= Seq("-encoding", "UTF-8", "-unchecked", "-deprecation", "-feature"),
28 | scalacOptions in(Compile, doc) ++= Seq("-sourcepath", baseDirectory.value.getAbsolutePath,
29 | "-doc-source-url", "https://github.com/xerial/larray/tree/develop/€{FILE_PATH}.scala",
30 | "-doc-title", "LArray API",
31 | "-doc-version", version.value,
32 | "-diagrams"
33 | ),
34 | testOptions in Test += Tests.Argument(TestFrameworks.ScalaTest, "-u", s"${target.value / "test-reports"}", "-o"),
35 | crossPaths := true,
36 | licenses += ("Apache-2.0", url("https://www.apache.org/licenses/LICENSE-2.0.html")),
37 | homepage := Some(url("https://github.com/xerial/larray")),
38 | pomExtra := {
39 |
40 | scm:git:github.com/xerial/larray.git
41 | scm:git:git@github.com:xerial/larray.git
42 | github.com/xerial/larray.git
43 |
44 |
45 |
46 | {SCALA_VERSION}
47 |
48 | UTF-8
49 |
50 |
51 |
52 | leo
53 | Taro L. Saito
54 | http://xerial.org/leo
55 |
56 |
57 | },
58 | releaseTagName := { (version in ThisBuild).value },
59 | releaseCrossBuild := true,
60 | releaseProcess := Seq[ReleaseStep](
61 | checkSnapshotDependencies,
62 | inquireVersions,
63 | runClean,
64 | runTest,
65 | setReleaseVersion,
66 | commitReleaseVersion,
67 | tagRelease,
68 | ReleaseStep(action = Command.process("publishSigned", _), enableCrossBuild = true),
69 | setNextVersion,
70 | commitNextVersion,
71 | ReleaseStep(action = Command.process("sonatypeReleaseAll", _), enableCrossBuild = true),
72 | pushChanges
73 | ),
74 | publishTo := Some(
75 | if (isSnapshot.value)
76 | Opts.resolver.sonatypeSnapshots
77 | else
78 | Opts.resolver.sonatypeStaging
79 | )
80 | )
81 |
82 | lazy val root = Project(
83 | id = "larray-root",
84 | base = file("."),
85 | settings = buildSettings ++ Seq(
86 | publish := {},
87 | publishLocal := {},
88 | publishArtifact := false
89 | )
90 | ) aggregate(larrayScala, larrayBuffer, larrayMMap)
91 |
92 | val snappy = "org.xerial.snappy" % "snappy-java" % "1.1.4"
93 | val junit = "junit" % "junit" % "4.11" % "test"
94 | val slf4j = "org.slf4j" % "slf4j-api" % "1.7.25"
95 | val slf4jSimple = "org.slf4j" % "slf4j-simple" % "1.7.25"
96 |
97 | val scope = "test->test;compile->compile"
98 |
99 | lazy val larrayScala = Project(
100 | id = "larray",
101 | base = file("larray"),
102 | settings = buildSettings ++ SbtMultiJvm.multiJvmSettings ++
103 | Seq(
104 | description := "LArray: A Large off-heap arrays for Scala/Java",
105 | logBuffered in MultiJvm := false,
106 | jvmOptions in MultiJvm ++= Seq("-Xmx128M"),
107 | compile in MultiJvm := {(compile in MultiJvm) triggeredBy (compile in Test)}.value,
108 | executeTests in Test := {
109 | val testResults: Tests.Output = (executeTests in Test).value
110 | val multiJvmTestResults: Tests.Output = (executeTests in MultiJvm).value
111 | val results = testResults.events ++ multiJvmTestResults.events
112 | Tests.Output(
113 | Tests.overall(Seq(testResults.overall, multiJvmTestResults.overall)),
114 | results,
115 | testResults.summaries ++ multiJvmTestResults.summaries)
116 | },
117 | libraryDependencies ++= Seq(
118 | // Add dependent jars here
119 | "org.wvlet" %% "wvlet-log" % "1.1",
120 | snappy % "test",
121 | junit,
122 | "org.iq80.snappy" % "snappy" % "0.3" % "test",
123 | "com.novocode" % "junit-interface" % "0.11" % "test",
124 | "org.scalatest" %% "scalatest" % "3.0.1" % "test",
125 | "org.scalacheck" %% "scalacheck" % "1.13.4" % "test",
126 | "com.typesafe.akka" %% "akka-testkit" % "[2.3.14, 2.5)" % "test",
127 | "com.typesafe.akka" %% "akka-multi-node-testkit" % "[2.3.14, 2.5)" % "test"
128 | )
129 | )
130 | ) dependsOn(larrayBuffer % scope, larrayMMap) configs (MultiJvm)
131 |
132 | lazy val larrayBuffer = Project(
133 | id = "larray-buffer",
134 | base = file("larray-buffer"),
135 | settings = buildSettings ++ Seq(
136 | description := "LArray off-heap buffer library",
137 | crossPaths := false,
138 | autoScalaLibrary := false,
139 | libraryDependencies ++= Seq(
140 | "org.scalatest" %% "scalatest" % "3.0.1" % "test",
141 | "org.wvlet" %% "wvlet-log" % "1.1" % "test"
142 | )
143 | )
144 | )
145 |
146 | lazy val larrayMMap = Project(
147 | id = "larray-mmap",
148 | base = file("larray-mmap"),
149 | settings = buildSettings ++
150 | Seq(
151 | description := "LArray mmap implementation",
152 | crossPaths := false,
153 | autoScalaLibrary := false,
154 | libraryDependencies ++= Seq(
155 | snappy % "test",
156 | junit
157 | )
158 | )
159 | ) dependsOn (larrayBuffer % scope)
160 |
--------------------------------------------------------------------------------
/include/inc_linux/jni_md.h:
--------------------------------------------------------------------------------
1 | /*
2 | * %W% %E%
3 | *
4 | * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
5 | * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6 | */
7 |
8 | #ifndef _JAVASOFT_JNI_MD_H_
9 | #define _JAVASOFT_JNI_MD_H_
10 |
11 | #define JNIEXPORT __attribute__((__visibility__("default")))
12 | #define JNIIMPORT
13 | #define JNICALL
14 |
15 | typedef int jint;
16 | #ifdef _LP64 /* 64-bit Solaris */
17 | typedef long jlong;
18 | #else
19 | typedef long long jlong;
20 | #endif
21 |
22 | typedef signed char jbyte;
23 |
24 | #endif /* !_JAVASOFT_JNI_MD_H_ */
25 |
--------------------------------------------------------------------------------
/include/inc_mac/jni_md.h:
--------------------------------------------------------------------------------
1 | /*
2 | * @(#)jni_md.h 1.19 05/11/17
3 | *
4 | * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
5 | * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6 | */
7 |
8 | #ifndef _JAVASOFT_JNI_MD_H_
9 | #define _JAVASOFT_JNI_MD_H_
10 |
11 | #define JNIEXPORT __attribute__((visibility("default")))
12 | #define JNIIMPORT
13 | #define JNICALL
14 |
15 | #if defined(__LP64__) && __LP64__ /* for -Wundef */
16 | typedef int jint;
17 | #else
18 | typedef long jint;
19 | #endif
20 | typedef long long jlong;
21 | typedef signed char jbyte;
22 |
23 | #endif /* !_JAVASOFT_JNI_MD_H_ */
24 |
--------------------------------------------------------------------------------
/include/inc_win/jni_md.h:
--------------------------------------------------------------------------------
1 | /*
2 | * @(#)jni_md.h 1.16 10/03/23
3 | *
4 | * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
5 | * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6 | */
7 |
8 | #ifndef _JAVASOFT_JNI_MD_H_
9 | #define _JAVASOFT_JNI_MD_H_
10 |
11 | #define JNIEXPORT __declspec(dllexport)
12 | #define JNIIMPORT __declspec(dllimport)
13 | #define JNICALL __stdcall
14 |
15 | typedef long jint;
16 | typedef __int64 jlong;
17 | typedef signed char jbyte;
18 |
19 | #endif /* !_JAVASOFT_JNI_MD_H_ */
20 |
--------------------------------------------------------------------------------
/larray-buffer/src/main/java/xerial/larray/buffer/DefaultMemoryAllocator.java:
--------------------------------------------------------------------------------
1 | package xerial.larray.buffer;
2 |
3 |
4 | import java.lang.ref.ReferenceQueue;
5 | import java.util.Map;
6 | import java.util.concurrent.ConcurrentHashMap;
7 | import java.util.concurrent.atomic.AtomicLong;
8 | import java.util.logging.Level;
9 | import java.util.logging.Logger;
10 |
11 |
12 | /**
13 | * A default implementation of MemoryAllocator that allocates off-heap memory and releases allocated memories in a background thread.
14 | *
15 | * @author Taro L. Saito
16 | */
17 | public class DefaultMemoryAllocator implements MemoryAllocator {
18 |
19 | private static Logger logger = Logger.getLogger(DefaultMemoryAllocator.class.getName());
20 |
21 | // Table from address -> MemoryReference
22 | private Map allocatedMemoryReferences = new ConcurrentHashMap();
23 | private ReferenceQueue queue = new ReferenceQueue();
24 |
25 | {
26 | // Start OffHeapMemory collector that releases the allocated memory when the corresponding Memory object is collected by GC.
27 | Thread collector = new Thread(new Runnable() {
28 | @Override
29 | public void run() {
30 | while(true) {
31 | try {
32 | MemoryReference ref = MemoryReference.class.cast(queue.remove());
33 | if(logger.isLoggable(Level.FINER)) {
34 | logger.finer(String.format("Found GC target at %x", ref.address));
35 | }
36 | release(ref);
37 | }
38 | catch(Exception e) {
39 | e.printStackTrace(System.err);
40 | }
41 | }
42 | }
43 | });
44 | collector.setName("LArray-GC");
45 | collector.setDaemon(true);
46 | logger.finer("Start memory collector");
47 | collector.start();
48 | }
49 |
50 | private AtomicLong totalAllocatedSize = new AtomicLong(0L);
51 |
52 | /**
53 | * Get the total amount of allocated memory
54 | */
55 | public long allocatedSize() { return totalAllocatedSize.get(); }
56 |
57 | /**
58 | * Allocate a memory of the specified byte length. The allocated memory must be released via `release`
59 | * as in malloc() in C/C++.
60 | * @param size byte length of the memory
61 | * @return allocated memory information
62 | */
63 | public Memory allocate(long size) {
64 | if(size == 0L)
65 | return new OffHeapMemory();
66 |
67 | // Allocate memory of the given size + HEADER space
68 | long memorySize = size + OffHeapMemory.HEADER_SIZE;
69 | long address = UnsafeUtil.unsafe.allocateMemory(memorySize);
70 | Memory m = new OffHeapMemory(address, size);
71 | register(m);
72 | return m;
73 | }
74 |
75 | public void register(Memory m) {
76 | // Register a memory reference that will be collected upon GC
77 | MemoryReference ref = m.toRef(queue);
78 | allocatedMemoryReferences.put(ref.address, ref);
79 | totalAllocatedSize.getAndAdd(m.size());
80 | }
81 |
82 |
83 |
84 | /**
85 | * Release all memory addresses taken by this allocator.
86 | * Be careful in using this method, since all of the memory addresses become invalid.
87 | */
88 | public void releaseAll() {
89 | synchronized(this) {
90 | Object[] refSet = allocatedMemoryReferences.values().toArray();
91 | if(refSet.length != 0) {
92 | logger.finer("Releasing allocated memory regions");
93 | }
94 | for(Object ref : refSet) {
95 | release((MemoryReference) ref);
96 | }
97 | }
98 | }
99 |
100 |
101 | public void release(MemoryReference ref) {
102 | release(ref.toMemory());
103 | }
104 |
105 | public void release(Memory m) {
106 | synchronized(this) {
107 | long address = m.headerAddress();
108 | if(allocatedMemoryReferences.containsKey(address)) {
109 | if(logger.isLoggable(Level.FINER)) {
110 | logger.finer(String.format("Released memory at %x (size:%,d)", address, m.dataSize()));
111 | }
112 | totalAllocatedSize.getAndAdd(-m.size());
113 | allocatedMemoryReferences.remove(address);
114 | m.release();
115 | }
116 | }
117 | }
118 |
119 |
120 | }
121 |
--------------------------------------------------------------------------------
/larray-buffer/src/main/java/xerial/larray/buffer/LBuffer.java:
--------------------------------------------------------------------------------
1 | package xerial.larray.buffer;
2 |
3 | /**
4 | * Off-heap memory buffer of int and long type indexes.
5 | * LBuffer is used as a backend of LArray.
6 | *
7 | * @author Taro L. Saito
8 | */
9 | public class LBuffer extends LBufferAPI {
10 | /**
11 | * Allocate a memory of the specified byte size
12 | *
13 | * @param size byte size of the array
14 | */
15 | public LBuffer(long size) {
16 | super(LBufferConfig.allocator.allocate(size));
17 | }
18 | }
19 |
20 |
21 |
--------------------------------------------------------------------------------
/larray-buffer/src/main/java/xerial/larray/buffer/LBufferConfig.java:
--------------------------------------------------------------------------------
1 | package xerial.larray.buffer;
2 |
3 | /**
4 | * Holding the default memory allocator
5 | * @author Taro L. Saito
6 | */
7 | public class LBufferConfig {
8 |
9 | public static MemoryAllocator allocator = new DefaultMemoryAllocator();
10 | }
11 |
--------------------------------------------------------------------------------
/larray-buffer/src/main/java/xerial/larray/buffer/Memory.java:
--------------------------------------------------------------------------------
1 | package xerial.larray.buffer;
2 |
3 | import java.lang.ref.ReferenceQueue;
4 |
5 | /**
6 | * Allocated memory information
7 | * @author Taro L. Saito
8 | */
9 | public interface Memory {
10 |
11 | /**
12 | * Allocated memory address
13 | * @return
14 | */
15 | long headerAddress();
16 |
17 | /**
18 | * data-part address
19 | * @return data address
20 | */
21 | long address();
22 |
23 | /**
24 | * Allocated memory size
25 | * @return
26 | */
27 | long size();
28 |
29 | /**
30 | * data-part size
31 | * @return
32 | */
33 | long dataSize();
34 |
35 | void release();
36 |
37 | MemoryReference toRef(ReferenceQueue queue);
38 | }
39 |
--------------------------------------------------------------------------------
/larray-buffer/src/main/java/xerial/larray/buffer/MemoryAllocator.java:
--------------------------------------------------------------------------------
1 | package xerial.larray.buffer;
2 |
3 | /**
4 | * Memory allocator interface
5 | * @author Taro L. Saito
6 | */
7 | public interface MemoryAllocator {
8 |
9 | /**
10 | * Allocate a memory of the specified byte length. The allocated memory must be released via `release`
11 | * as in malloc() in C/C++.
12 | * @param size byte length of the memory
13 | * @return allocated memory information
14 | */
15 | Memory allocate(long size);
16 |
17 | /**
18 | * Get the total amount of allocated memories
19 | */
20 | long allocatedSize();
21 |
22 | /**
23 | * Register a memory
24 | * @param m
25 | */
26 | void register(Memory m);
27 |
28 | /**
29 | * Release a memory
30 | */
31 | void release(Memory m);
32 |
33 | /**
34 | * Release a memory, referenced by ref
35 | */
36 | void release(MemoryReference ref);
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/larray-buffer/src/main/java/xerial/larray/buffer/MemoryReference.java:
--------------------------------------------------------------------------------
1 | package xerial.larray.buffer;
2 |
3 | import java.lang.ref.PhantomReference;
4 | import java.lang.ref.ReferenceQueue;
5 |
6 | /**
7 | * Phantom reference to the allocated memory that will be queued to the ReferenceQueue upon GC time
8 | */
9 | public abstract class MemoryReference extends PhantomReference {
10 | public final long address;
11 |
12 | /**
13 | * Create a phantom reference
14 | * @param m the allocated memory
15 | * @param queue the reference queue to which GCed reference of the Memory will be put
16 | */
17 | public MemoryReference(Memory m, ReferenceQueue queue) {
18 | super(m, queue);
19 | this.address = m.headerAddress();
20 | }
21 |
22 | abstract public Memory toMemory();
23 | abstract public String name();
24 | }
25 |
--------------------------------------------------------------------------------
/larray-buffer/src/main/java/xerial/larray/buffer/OffHeapMemory.java:
--------------------------------------------------------------------------------
1 | package xerial.larray.buffer;
2 |
3 | import java.lang.ref.ReferenceQueue;
4 |
5 | import static xerial.larray.buffer.UnsafeUtil.unsafe;
6 |
7 | /**
8 | * Stores |(memory size:long)| data ... |
9 | */
10 | public class OffHeapMemory implements Memory {
11 |
12 | private final long _data;
13 |
14 | public static long HEADER_SIZE = 8L;
15 |
16 | /**
17 | * Create an empty memory
18 | */
19 | public OffHeapMemory() {
20 | this._data = 0L;
21 | }
22 |
23 | public OffHeapMemory(long address) {
24 | if(address != 0L)
25 | this._data = address + HEADER_SIZE;
26 | else
27 | this._data = 0L;
28 | }
29 |
30 | public OffHeapMemory(long address, long size) {
31 | if(address != 0L) {
32 | this._data = address + HEADER_SIZE;
33 | unsafe.putLong(address, size);
34 | }
35 | else {
36 | this._data = 0L;
37 | }
38 | }
39 |
40 |
41 |
42 | public long headerAddress() {
43 | return _data - HEADER_SIZE;
44 | }
45 | public long size() {
46 | return (_data == 0) ? 0L : unsafe.getLong(headerAddress()) + HEADER_SIZE;
47 | }
48 |
49 | public long address() {
50 | return _data;
51 | }
52 |
53 | public long dataSize() {
54 | return (_data == 0) ? 0L : unsafe.getLong(headerAddress());
55 | }
56 |
57 | public MemoryReference toRef(ReferenceQueue queue) {
58 | return new OffHeapMemoryReference(this, queue);
59 | }
60 |
61 | public void release() {
62 | if(_data != 0)
63 | UnsafeUtil.unsafe.freeMemory(headerAddress());
64 | }
65 | }
66 |
67 |
68 |
--------------------------------------------------------------------------------
/larray-buffer/src/main/java/xerial/larray/buffer/OffHeapMemoryReference.java:
--------------------------------------------------------------------------------
1 | package xerial.larray.buffer;
2 |
3 | import java.lang.ref.ReferenceQueue;
4 |
5 | /**
6 | * @author Taro L. Saito
7 | */
8 | public class OffHeapMemoryReference extends MemoryReference {
9 |
10 | /**
11 | * Create a phantom reference
12 | * @param m the allocated memory
13 | * @param queue the reference queue to which GCed reference of the Memory will be inserted
14 | */
15 | public OffHeapMemoryReference(Memory m, ReferenceQueue queue) {
16 | super(m, queue);
17 | }
18 |
19 | public Memory toMemory() {
20 | if(address != 0)
21 | return new OffHeapMemory(address);
22 | else
23 | return new OffHeapMemory();
24 | }
25 |
26 | public String name() { return "off-heap"; }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/larray-buffer/src/main/java/xerial/larray/buffer/UnsafeUtil.java:
--------------------------------------------------------------------------------
1 | package xerial.larray.buffer;
2 |
3 | import sun.misc.Unsafe;
4 |
5 | import java.lang.reflect.Constructor;
6 | import java.lang.reflect.Field;
7 | import java.nio.ByteBuffer;
8 |
9 | /**
10 | * Helper methods for using sun.misc.Unsafe.
11 | *
12 | * @author Taro L. Saito
13 | */
14 | public class UnsafeUtil {
15 |
16 | public static Unsafe getUnsafe() {
17 | try {
18 | Field f = Unsafe.class.getDeclaredField("theUnsafe");
19 | f.setAccessible(true);
20 | return Unsafe.class.cast(f.get(null));
21 | }
22 | catch(NoSuchFieldException e) {
23 | throw new IllegalStateException("sun.misc.Unsafe is not available in this JVM");
24 | }
25 | catch(IllegalAccessException e) {
26 | throw new IllegalStateException("sun.misc.Unsafe is not available in this JVM");
27 | }
28 | }
29 |
30 | public static Unsafe unsafe = getUnsafe();
31 |
32 | private static ByteBufferCreator findDirectByteBufferConstructor() {
33 | try {
34 | return constructorWithAttStrategy();
35 | }
36 | catch(ClassNotFoundException e) {
37 | throw new IllegalStateException(
38 | String.format("Failed to find java.nio.DirectByteBuffer: $s", e.getMessage()));
39 | }
40 | catch(NoSuchMethodException e) {
41 | try {
42 | return constructorWithoutAttStrategy();
43 | } catch (NoSuchMethodException e2) {
44 | throw new IllegalStateException(
45 | String.format("Failed to find constructor f java.nio.DirectByteBuffer: $s", e2.getMessage()), e2);
46 | } catch (ClassNotFoundException e2) {
47 | throw new IllegalStateException(
48 | String.format("Failed to find constructor f java.nio.DirectByteBuffer: $s", e2.getMessage()), e2);
49 | }
50 | }
51 | }
52 |
53 | private static ByteBufferCreator byteBufferCreator = findDirectByteBufferConstructor();
54 |
55 | /**
56 | * Create a new DirectByteBuffer from a given address and size.
57 | * The returned DirectByteBuffer does not release the memory by itself.
58 | *
59 | * @param addr
60 | * @param size
61 | * @param att object holding the underlying memory to attach to the buffer.
62 | * This will prevent the garbage collection of the memory area that's
63 | * associated with the new DirectByteBuffer
64 | * @return
65 | */
66 | public static ByteBuffer newDirectByteBuffer(long addr, int size, Object att) {
67 | return byteBufferCreator.newDirectByteBuffer(addr, size, att);
68 | }
69 |
70 | private static ByteBufferCreator constructorWithAttStrategy()
71 | throws ClassNotFoundException, NoSuchMethodException {
72 | final Constructor extends ByteBuffer> dbbCC =
73 | (Constructor extends ByteBuffer>) Class.forName("java.nio.DirectByteBuffer")
74 | .getDeclaredConstructor(Long.TYPE, Integer.TYPE, Object.class);
75 | return new ByteBufferCreator() {
76 | @Override
77 | public ByteBuffer newDirectByteBuffer(long addr, int size, Object att) {
78 | dbbCC.setAccessible(true);
79 | try {
80 | return dbbCC.newInstance(Long.valueOf(addr), Integer.valueOf(size), att);
81 | } catch (Exception e) {
82 | throw new IllegalStateException(
83 | String.format("Failed to create DirectByteBuffer: %s", e.getMessage()), e);
84 | }
85 | }
86 | };
87 | }
88 |
89 | private static ByteBufferCreator constructorWithoutAttStrategy()
90 | throws ClassNotFoundException, NoSuchMethodException {
91 | final Constructor extends ByteBuffer> dbbCC =
92 | (Constructor extends ByteBuffer>) Class.forName("java.nio.DirectByteBuffer")
93 | .getDeclaredConstructor(Long.TYPE, Integer.TYPE);
94 | return new ByteBufferCreator() {
95 | @Override
96 | public ByteBuffer newDirectByteBuffer(long addr, int size, Object att) {
97 | dbbCC.setAccessible(true);
98 | try {
99 | return dbbCC.newInstance(Long.valueOf(addr), Integer.valueOf(size));
100 | } catch (Exception e) {
101 | throw new IllegalStateException(
102 | String.format("Failed to create DirectByteBuffer: %s", e.getMessage()), e);
103 | }
104 | }
105 | };
106 | }
107 |
108 | private interface ByteBufferCreator {
109 | ByteBuffer newDirectByteBuffer(long addr, int size, Object att);
110 | }
111 |
112 |
113 | }
114 |
--------------------------------------------------------------------------------
/larray-buffer/src/main/java/xerial/larray/buffer/WrappedLBuffer.java:
--------------------------------------------------------------------------------
1 | package xerial.larray.buffer;
2 |
3 | /**
4 | * A subrange of memory
5 | *
6 | * @author Taro L. Saito
7 | */
8 | public class WrappedLBuffer extends LBufferAPI {
9 |
10 | private final long offset;
11 | private final long size;
12 |
13 | public WrappedLBuffer(Memory m, long offset, long size) {
14 | super(m);
15 | this.offset = offset;
16 | this.size = size;
17 | }
18 |
19 | @Override
20 | public long address() {
21 | return m.address() + offset;
22 | }
23 |
24 | @Override
25 | public long size() {
26 | return size;
27 | }
28 |
29 | @Override
30 | protected long offset() {
31 | return offset;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/larray-buffer/src/main/java/xerial/larray/buffer/WritableChannelWrap.java:
--------------------------------------------------------------------------------
1 | package xerial.larray.buffer;
2 |
3 | import java.io.IOException;
4 | import java.nio.ByteBuffer;
5 | import java.nio.channels.WritableByteChannel;
6 |
7 | import static xerial.larray.buffer.UnsafeUtil.unsafe;
8 |
9 | /**
10 | * @author Taro L. Saito
11 | */
12 | class WritableChannelWrap implements WritableByteChannel {
13 |
14 | private final LBuffer b;
15 | int cursor = 0;
16 |
17 | WritableChannelWrap(LBuffer b) {
18 | this.b = b;
19 | }
20 |
21 | @Override
22 | public int write(ByteBuffer src) throws IOException {
23 | int len = (int) Math.max(src.limit() - src.position(), 0);
24 | int writeLen = 0;
25 | if(src.isDirect()) {
26 | src.put(b.toDirectByteBuffer(cursor, len));
27 | writeLen = len;
28 | }
29 | else if(src.hasArray()) {
30 | writeLen = b.readFrom(src.array(), src.position(), cursor, len);
31 | }
32 | else {
33 | for(long i=0; i 1K
33 | * @param byteSize
34 | * @return string representation of the byte size
35 | */
36 | def toHumanReadableFormat(byteSize:Long) : String = {
37 | // kilo, mega, giga, tera, peta, exa, zetta, yotta
38 | val unitName = Seq("", "K", "M", "G", "T", "P", "E", "Z", "Y")
39 |
40 | def loop(index:Int, v:Long) : (Long, String) = {
41 | if(index >= unitName.length)
42 | (byteSize, "")
43 | val next = v >> 10L
44 | if(next == 0L)
45 | (v, unitName(index))
46 | else
47 | loop(index+1, next)
48 | }
49 |
50 | val (prefix, unit) = if(byteSize > 0)
51 | loop(0, byteSize)
52 | else
53 | loop(0, -byteSize) match { case (p, u) => (-p, u)}
54 | s"$prefix$unit"
55 | }
56 |
57 | // implicit class DataSize(size:Long) {
58 | // def K = size * KB
59 | // def M = size * MB
60 | // def G = size * GB
61 | // def P = size * PB
62 | // }
63 |
64 | // data size unit
65 | val KB = 1L << 10
66 | val MB = 1L << 20
67 | val GB = 1L << 30
68 | val PB = 1L << 40
69 |
70 | }
71 |
--------------------------------------------------------------------------------
/larray-buffer/src/test/scala/xerial/larray/LArraySpec.scala:
--------------------------------------------------------------------------------
1 | package xerial.larray
2 |
3 | import org.scalatest._
4 | import wvlet.log.LogFormatter.SourceCodeLogFormatter
5 | import wvlet.log.{LogSupport, Logger}
6 | import wvlet.log.io.{ResourceReader, StopWatch, Timer}
7 |
8 | import scala.language.implicitConversions
9 |
10 | /**
11 | * @author Taro L. Saito
12 | */
13 | trait LArraySpec
14 | extends WordSpec
15 | with Matchers
16 | with ResourceReader
17 | with Timer
18 | with LogSupport
19 | with BeforeAndAfterAll
20 | with BeforeAndAfter
21 | with BeforeAndAfterEach
22 | with GivenWhenThen {
23 |
24 | implicit def toTag(t:String) = Tag(t)
25 |
26 | Logger.setDefaultFormatter(SourceCodeLogFormatter)
27 |
28 | override protected def beforeAll(): Unit = {
29 | // Run LogLevel scanner (log-test.properties or log.properties in classpath) every 1 minute
30 | Logger.scheduleLogLevelScan
31 | super.beforeAll()
32 | }
33 |
34 | override protected def afterAll(): Unit = {
35 | Logger.stopScheduledLogLevelScan
36 | super.afterAll()
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/larray-buffer/src/test/scala/xerial/larray/buffer/LBufferTest.scala:
--------------------------------------------------------------------------------
1 | //--------------------------------------
2 | //
3 | // RawByteArrayTestTest.scala
4 | // Since: 2013/12/03 12:02 PM
5 | //
6 | //--------------------------------------
7 |
8 | package xerial.larray.buffer
9 |
10 | import java.nio.ByteBuffer
11 |
12 | import xerial.larray.{DataUnit, LArraySpec}
13 |
14 | /**
15 | * @author Taro L. Saito
16 | */
17 | class LBufferTest extends LArraySpec {
18 |
19 | implicit class RichArray(m:LBuffer) {
20 | def toCSV = m.toArray.mkString(", ")
21 | }
22 |
23 |
24 | "LBuffer" should {
25 |
26 | "allocate memory" in {
27 | val size = 1000
28 | val m = new LBuffer(size)
29 | m.putInt(0, 0)
30 | m.putInt(4, 1)
31 | m.putInt(8, 130)
32 |
33 | m.getInt(0) shouldBe 0
34 | m.getInt(4) shouldBe 1
35 | m.getInt(8) shouldBe 130
36 |
37 | m.size() shouldBe size.toLong
38 |
39 | (0 until size).foreach(i => m.putByte(i, (i % 128).toByte))
40 | (0 until size).forall(i => m.getByte(i) == (i % 128).toByte) should be (true)
41 |
42 | m.clear()
43 |
44 | (0 until size).forall(i => m.getByte(i) == 0) should be (true)
45 |
46 | m.release()
47 | }
48 |
49 | "convert to array" in {
50 | val size = 12
51 | val m = new LBuffer(size);
52 | for(i <- 0 until size)
53 | m(i) = i.toByte
54 | debug(m.toCSV)
55 |
56 | m.clear()
57 | debug(m.toCSV)
58 | }
59 |
60 |
61 | "allocate in single-thread" taggedAs("bench-single") in {
62 |
63 | val N = 100
64 | def range = (0 until N)
65 | val R = 2
66 | val S = 1024 * 1024
67 |
68 | info("start buffer allocation test")
69 |
70 | time("single-thread allocation", repeat=10, blockRepeat = R) {
71 | block("without zero-filling") {
72 | for(i <- range) yield {
73 | new LBuffer(S)
74 | }
75 | }
76 |
77 | block("with zero-filling") {
78 | for(i <- range) yield {
79 | val m = new LBuffer(S)
80 | m.clear()
81 | m
82 | }
83 | }
84 |
85 | block("java array") {
86 | for(i <- range) yield {
87 | new Array[Byte](S)
88 | }
89 | }
90 |
91 | block("byte buffer") {
92 | for(i <- range) yield {
93 | ByteBuffer.allocate(S)
94 | }
95 | }
96 |
97 | block("direct byte buffer") {
98 | for(i <- range) yield {
99 | ByteBuffer.allocateDirect(S)
100 | }
101 | }
102 |
103 | }
104 | }
105 |
106 | "allocate concurrently" taggedAs("bench") in {
107 |
108 | val N = 100
109 | def range = (0 until N).par
110 | val R = 2
111 | val S = 1024 * 1024
112 |
113 | info("start buffer allocation test")
114 |
115 | time("concurrent allocation", repeat=10, blockRepeat = R) {
116 | block("without zero-filling") {
117 | for(i <- range) yield {
118 | new LBuffer(S)
119 | }
120 | }
121 |
122 | block("with zero-filling") {
123 | for(i <- range) yield {
124 | val m = new LBuffer(S)
125 | m.clear()
126 | m
127 | }
128 | }
129 |
130 | block("java array") {
131 | for(i <- range) yield {
132 | new Array[Byte](S)
133 | }
134 | }
135 |
136 | block("byte buffer") {
137 | for(i <- range) yield {
138 | ByteBuffer.allocate(S)
139 | }
140 | }
141 |
142 | block("direct byte buffer") {
143 | for(i <- range) yield {
144 | ByteBuffer.allocateDirect(S)
145 | }
146 | }
147 |
148 | }
149 | }
150 |
151 | "Use less memory" taggedAs("heap") in {
152 |
153 | // Need to produce meaningful memory usage
154 | pending
155 |
156 | val N = 100000
157 | val M = 1024
158 |
159 | val rt = Runtime.getRuntime
160 |
161 | case class Report(tag:String, free:Long, offHeap:Long, total:Long) {
162 | override def toString = s"[${tag}] free:${DataUnit.toHumanReadableFormat(free)}, offheap:${DataUnit.toHumanReadableFormat(offHeap)}"
163 | }
164 |
165 | val memUsage = Seq.newBuilder[Report]
166 |
167 | def report(tag:String) = {
168 | val offHeap = LBufferConfig.allocator.allocatedSize()
169 | val rep = Report(tag, rt.freeMemory(), offHeap, rt.totalMemory())
170 | //memUsage += rep
171 | rep
172 | }
173 |
174 | var r1 : Seq[Array[Byte]] = null
175 | var r2 : Seq[LBuffer] = null
176 |
177 | time("memory allocation", repeat=3) {
178 | Thread.sleep(5000)
179 | block("Array") {
180 | info(report("Array"))
181 | val result = for(i <- 0 until N) yield {
182 | val a = new Array[Byte](M)
183 | report("Array")
184 | a
185 | }
186 | info(report("Array"))
187 | }
188 |
189 | // info("gc")
190 | // System.gc()
191 | Thread.sleep(5000)
192 |
193 | block("LBuffer") {
194 | info(report("LBuffer"))
195 | val result = for(i <- 0 until N) yield {
196 | val l = new LBuffer(M)
197 | report("LBuffer")
198 | l
199 | }
200 | info(report("LBuffer"))
201 | }
202 |
203 | }
204 |
205 |
206 | }
207 |
208 | "read from ByteBuffer" in {
209 | val bytes = Array[Byte](1, 2, 3)
210 | val byteBuffer = ByteBuffer.wrap(bytes)
211 | val lbuffer = new LBuffer(3)
212 | lbuffer.readFrom(byteBuffer, 0)
213 | byteBuffer.array() === lbuffer.toArray
214 | }
215 | }
216 | }
--------------------------------------------------------------------------------
/larray-buffer/src/test/scala/xerial/larray/buffer/MemoryAllocatorTest.scala:
--------------------------------------------------------------------------------
1 | /*--------------------------------------------------------------------------
2 | * Copyright 2013 Taro L. Saito
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *--------------------------------------------------------------------------*/
16 | //--------------------------------------
17 | //
18 | // MemoryAllocatorTest.scala
19 | // Since: 2013/03/22 12:02
20 | //
21 | //--------------------------------------
22 |
23 | package xerial.larray.buffer
24 |
25 | import xerial.larray.LArraySpec
26 |
27 |
28 | /**
29 | * @author Taro L. Saito
30 | */
31 | class MemoryAllocatorTest extends LArraySpec {
32 | "ConcurrentMemoryAllocator" should {
33 | "perform better than the default heap allocator" in {
34 |
35 | val N = 1000
36 | val B = 64 * 1024
37 |
38 | val t = time("alloc", repeat = 5) {
39 | block("concurrent") {
40 | val l = for (i <- (0 until N).par) yield {
41 | val a = new LBuffer(B)
42 | a(B-1) = 1.toByte
43 | a
44 | }
45 | l.foreach(_.release)
46 | }
47 |
48 | block("Array") {
49 | val l = for (i <- (0 until N).par) yield {
50 | val a = new Array[Int](B)
51 | a(B-1) = 1
52 | a
53 | }
54 | }
55 | }
56 | t("concurrent") should be <= (t("Array"))
57 | }
58 | }
59 | }
--------------------------------------------------------------------------------
/larray-buffer/src/test/scala/xerial/larray/buffer/WrappedLBufferTest.scala:
--------------------------------------------------------------------------------
1 | //--------------------------------------
2 | //
3 | // WrappedLBufferTest.scala
4 | // Since: 2013/12/11 23:07
5 | //
6 | //--------------------------------------
7 |
8 | package xerial.larray.buffer
9 |
10 | import xerial.larray.LArraySpec
11 |
12 | /**
13 | * @author Taro L. Saito
14 | */
15 | class WrappedLBufferTest extends LArraySpec {
16 |
17 | "WrappedLBuffer" should {
18 |
19 | "be a subrange of LBuffer" in {
20 | val l = new LBuffer(10)
21 | for(i <- 0 until l.size().toInt) {
22 | l(i) = (10 - i).toByte
23 | }
24 |
25 | debug(l.toArray.mkString(", "))
26 | val v = l.view(3, 8)
27 |
28 | debug(v.toArray.mkString(", "))
29 | v.size() shouldBe 8 - 3
30 | v.toArray.zipWithIndex.forall{case (a, i) => a == l(i+3)}
31 | }
32 |
33 | }
34 | }
--------------------------------------------------------------------------------
/larray-mmap/src/main/java/xerial/larray/impl/LArrayLoader.java:
--------------------------------------------------------------------------------
1 | /*--------------------------------------------------------------------------
2 | * Copyright 2013 Taro L. Saito
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *--------------------------------------------------------------------------*/
16 | //--------------------------------------
17 | //
18 | // LArrayLoader.scala
19 | // Since: 2013/03/18 10:35 AM
20 | //
21 | //--------------------------------------
22 |
23 | package xerial.larray.impl;
24 |
25 |
26 | import java.io.*;
27 | import java.security.DigestInputStream;
28 | import java.security.MessageDigest;
29 | import java.security.NoSuchAlgorithmException;
30 | import java.util.UUID;
31 |
32 |
33 | /**
34 | * Internal only - Do not use this class. This class loads a native
35 | * library of larray (larray.dll, liblarray.so, etc.) according to the
36 | * user platform (os.name and os.arch).
37 |
38 | * In default, no configuration is required to use larray, but you can load
39 | * your own native library created by 'make native' command.
40 | *
41 | * This LArrayLoader load a native library (larray.dll, larray.so, etc.) using the following procedure:
42 | *
43 | *
Extract one of the libraries embedded in larray-(version).jar into
44 | * (System property: java.io.tempdir). If
45 | * xerial.larray.tempdir is set, use this folder instead of
46 | * java.io.tempdir.
47 | *
48 | *
49 | *
50 | * If you do not want to use folder java.io.tempdir, set the System
51 | * property xerial.larray.tempdir. For example, to use
52 | * /tmp/leo as a temporary folder to copy native libraries, use -D option
53 | * of JVM:
54 | *
55 | *