pmem / pcj Goto Github PK
View Code? Open in Web Editor NEWPersistent Collections for Java
License: Other
Persistent Collections for Java
License: Other
Java conventions and the recommendation from Oracle is to use reverse DNS names for package names.
Any suggestion for the following error? I was following the instructions for building this project.
~/bin/god/pcj$ make && make tests
g++ -O3 -DNDEBUG -fPIC -I/home/lizhichao/bin/jdk1.8.0_101//include -I/home/lizhichao/bin/jdk1.8.0_101//include/linux -o target/cppbuild/lib_xpersistent_UncheckedPersistentMemoryRegion.o -c src/main/cpp/lib_xpersistent_UncheckedPersistentMemoryRegion.cpp
In file included from src/main/cpp/persistent_heap.h:22:0,
from src/main/cpp/lib_xpersistent_UncheckedPersistentMemoryRegion.cpp:23:
src/main/cpp/persistent_structs.h:22:24: fatal error: libpmemobj.h: No such file or directory
#include <libpmemobj.h>
A mutable class that inherits from an immutable one does not respect the Liskov Substitution Principle, a.k.a. the L in SOLID. An immutable object and its responses to getters can be cached indefinitely whereas a mutable object does not allow this.
For example, AbstractPersistentArray
inherits from AbstractPersistentImmutableArray
, adding setters that render what should be immutable, per the contract of AbstractPersistentImmutableArray
.
This may just be a naming issue. If a suitable replacement for the term Immutable
were found that doesn't imply a specific contract, for instance Readable
.
I've fixed a minor bug about this. JerryYangSH@ef74184
I tested the latency PersistentSkipListMap and PersistentSkipListMap2. It looks PersistentSkipListMap is doing a better job than PersistentSkipListMap2 regarding the avg latency. What makes this difference? Which one is preferred?
Testing benchmark PersistentSkipListMap******
[Key Count 1000] avg lat:
DELETE : 151 (us)
CREATE : 158 (us)
GET : 74 (us)
UPDATE : 120 (us)
[Key Count 10000] avg lat:
DELETE : 71 (us)
CREATE : 130 (us)
GET : 143 (us)
UPDATE : 82 (us)
[Key Count 50000] avg lat:
DELETE : 102 (us)
CREATE : 117 (us)
GET : 45 (us)
UPDATE : 126 (us)
Testing benchmark PersistentSkipListMap2******
[Key Count 1000] avg lat:
DELETE : 201 (us)
CREATE : 214 (us)
GET : 64 (us)
UPDATE : 152 (us)
[Key Count 10000] avg lat:
DELETE : 122 (us)
CREATE : 198 (us)
GET : 68 (us)
UPDATE : 163 (us)
My Test code is below:
jerry@u19:~/opensources/pcj$ git diff
diff --git a/src/test/java/tests/PersistentSkipListMapTest.java b/src/test/java/tests/PersistentSkipListMapTest.java
index cfdbc4d..1782295 100644
--- a/src/test/java/tests/PersistentSkipListMapTest.java
+++ b/src/test/java/tests/PersistentSkipListMapTest.java
@@ -43,6 +43,8 @@ static boolean verbose = false;
System.out.println("****************PersistentSkipListMap Tests************");
return testInsertion() &&
testRemoval() &&
+ testBenchmark(getPersistentSkipListMap()) &&
+ testBenchmark(getPersistentSkipListMap2()) &&
testIteration() &&
testSubMap() &&
testPutAll() &&
@@ -64,6 +66,26 @@ static boolean verbose = false;
return map;
}
+ private static PersistentSkipListMap<PersistentString, PersistentString> getPersistentSkipListMap() {
+ String id = threadSafeId("tests.PersistentSkipListMap");
+ PersistentSkipListMap<PersistentString, PersistentString> map = ObjectDirectory.get(id,PersistentSkipListMap.class);
+ if(map == null) {
+ map = new PersistentSkipListMap<>();
+ ObjectDirectory.put(id, map);
+ }
+ return map;
+ }
+
+ private static PersistentSkipListMap2<PersistentString, PersistentString> getPersistentSkipListMap2() {
+ String id = threadSafeId("tests.PersistentSkipListMap2");
+ PersistentSkipListMap2<PersistentString, PersistentString> map = ObjectDirectory.get(id,PersistentSkipListMap2.class);
+ if(map == null) {
+ map = new PersistentSkipListMap2<>();
+ ObjectDirectory.put(id, map);
+ }
+ return map;
+ }
+
@SuppressWarnings("unchecked")
public static boolean testInsertion() {
if (verbose) System.out.println("****************Testing insertion**********************");
@@ -93,6 +115,82 @@ static boolean verbose = false;
return true;
}
+ @SuppressWarnings("unchecked")
+ public static boolean testBenchmark(PersistentSortedMap<PersistentString, PersistentString> map) {
+ System.out.println(String.format("****************Testing benchmark %s**********************", map.getClass().getSimpleName()));
+
+ assert (map != null);
+ map.clear();
+ assert(map.size() == 0);
+
+ final int KeySize = 128;
+ final int ValueSize = 1024;
+ StringBuilder keyPrefixBuilder = new StringBuilder();
+ for (int i = 0; i < KeySize; i++) {
+ keyPrefixBuilder.append('~');
+ }
+ String keyPrefix = keyPrefixBuilder.toString();
+ StringBuilder valuePrefixBuilder = new StringBuilder();
+ for (int i = 0; i < ValueSize; i++) {
+ valuePrefixBuilder.append('&');
+ }
+ String valuePrefix = valuePrefixBuilder.toString();
+
+ final int[] LoopCounts = new int[] {1000, 10000, 50000};
+ for (int LoopCount : LoopCounts) {
+ System.out.println(String.format("[Key Count %6d] avg lat:", LoopCount));
+ map.clear();
+ assert(map.size() == 0);
+ Map<String, Long> latencies = new HashMap<>();
+
+ // CREATE:
+ long start = System.nanoTime();
+ for (int l = 0; l < LoopCount; l++) {
+ PersistentString key = new PersistentString(keyPrefix + l);
+ PersistentString val = new PersistentString(valuePrefix + l);
+ PersistentString out = map.put(key, val);
+ if (out != null) {
+ System.out.println(String.format("CREATING key %s failed, out = %s", keyPrefix + l, out.toString()));
+ }
+ assert(out == null);
+ }
+ latencies.put("CREATE", (System.nanoTime() - start) / LoopCount);
+
+ // GET
+ start = System.nanoTime();
+ for (int l = 0; l < LoopCount; l++) {
+ PersistentString key = new PersistentString(keyPrefix + l);
+ assert(map.get(key).toString().equals(valuePrefix + l));
+ }
+ latencies.put("GET", (System.nanoTime() - start) / LoopCount);
+
+ // UPDATE
+ start = System.nanoTime();
+ for (int l = 0; l < LoopCount; l++) {
+ PersistentString key = new PersistentString(keyPrefix + l);
+ PersistentString val = new PersistentString(valuePrefix);
+ PersistentString out = map.put(key, val);
+ assert(out.toString().equals(valuePrefix + l));
+ }
+ latencies.put("UPDATE", (System.nanoTime() - start) / LoopCount);
+
+ // DELETE
+ start = System.nanoTime();
+ for (int l = 0; l < LoopCount; l++) {
+ PersistentString key = new PersistentString(keyPrefix + l);
+ PersistentString out = map.remove(key);
+ }
+ latencies.put("DELETE", (System.nanoTime() - start) / LoopCount);
+
+ for (Map.Entry<String, Long> lat : latencies.entrySet()) {
+ System.out.println(String.format("\t%8s : %8d (us)", lat.getKey(), lat.getValue() / 1000));
+ }
+ }
+
+ map.clear();
+ return true;
+ }
Java 7 introduces the "diamond operator" that makes code with generics less verbose. The code base claims to be Java 8 but does not seem to make use of the diamond operator.
The HTML Javadoc files are generated, best practices say generated artifacts should not be checked in source repository.
Using a unit test framework is a common and established way to develop, organize and run unit tests.
In order to make the library easy to consume publish an artifact to Maven Central.
root@ubuntu:/home/wayne/pmem/pcj# sudo make tests
/usr/lib/jvm/java-8-openjdk-amd64/bin/javac -Xlint:unchecked -XDenableSunApiLintControl -proc:none -d target/test_classes -cp src:target/classes:lib:src:lib/ST-4.0.8.jar: src/test/java/tests/PersistentLinkedQueueTest.java src/test/java/tests/TestCases.java src/test/java/tests/PersistentSIHashMapTest.java src/test/java/tests/PersistentFPTree2Test.java src/test/java/tests/PersistentArrayTest.java src/test/java/tests/PersistentTestRunner.java src/test/java/tests/ObjectDirectoryTest.java src/test/java/tests/PersistentFPTree1Test.java src/test/java/tests/PersistentHashMapTest.java src/test/java/tests/PersistentTupleTest.java src/test/java/tests/PersistentAtomicReferenceTest.java src/test/java/tests/PersistentSkipListMapTest.java src/test/java/tests/MultithreadTest.java src/test/java/tests/PersistentLinkedListTest.java src/test/java/tests/PersistentByteBufferTest.java src/test/java/tests/PersistentArrayListTest.java
/usr/lib/jvm/java-8-openjdk-amd64/bin/java -ea -cp target/classes:lib:src:lib/ST-4.0.8.jar::target/test_classes:src -Djava.library.path=target/cppbuild tests.PersistentTestRunner
Opening heap... Encountered error opening pool. Please check if /mnt/mem/persistent_heap exists and accessible.
make: *** [Makefile:84: tests] Error 255
root@ubuntu:/home/wayne/pmem/pcj# sudo make tests
/usr/lib/jvm/java-8-openjdk-amd64/bin/javac -Xlint:unchecked -XDenableSunApiLintControl -proc:none -d target/test_classes -cp src:target/classes:lib:src:lib/ST-4.0.8.jar: src/test/java/tests/PersistentLinkedQueueTest.java src/test/java/tests/TestCases.java src/test/java/tests/PersistentSIHashMapTest.java src/test/java/tests/PersistentFPTree2Test.java src/test/java/tests/PersistentArrayTest.java src/test/java/tests/PersistentTestRunner.java src/test/java/tests/ObjectDirectoryTest.java src/test/java/tests/PersistentFPTree1Test.java src/test/java/tests/PersistentHashMapTest.java src/test/java/tests/PersistentTupleTest.java src/test/java/tests/PersistentAtomicReferenceTest.java src/test/java/tests/PersistentSkipListMapTest.java src/test/java/tests/MultithreadTest.java src/test/java/tests/PersistentLinkedListTest.java src/test/java/tests/PersistentByteBufferTest.java src/test/java/tests/PersistentArrayListTest.java
/usr/lib/jvm/java-8-openjdk-amd64/bin/java -ea -cp target/classes:lib:src:lib/ST-4.0.8.jar::target/test_classes:src -Djava.library.path=target/cppbuild tests.PersistentTestRunner
Opening heap... Encountered error opening pool. Please check if /mnt/mem/persistent_heap exists and accessible.
make: *** [Makefile:84: tests] Error 255
root@ubuntu:/home/wayne/pmem/pcj#
===PMDK simple copy works fine===
wayne@ubuntu:~/pmdk/src/examples/libpmem$ sudo ./simple_copy /mnt/mem/1.txt /mnt/mem/2.txt
wayne: /mnt/mem/1.txt src-file
wayne: /mnt/mem/2.txt dst-file
None of the types seem to have documentation, see for example Transaction.
The code base has printStackTrace
sprinkled over various places in place of proper error handling and logging. In cases where exceptions are wrapped the cause is not passed on. Interruption is not handled properly.
Actually I have two questions (to support Java):
I am wondering is there any java wrapper for libpmemlog? I can not find these stuff in PCJ.
I assume PersistentLinkedQueue has same funcition as libpmemlog. like add / append, or pop / truncate... When I need a LogStore in Persistent Memory , between PersistentLinkedQueue and libpmemlog, which one should I choose ? In term of performance, any data?
I switched from file dax to dev dax mode (by "sudo ndctl create-namespace --mode devdax --map dev -e namespace0.0 -f"). and hit below error.
# Fork: 1 of 1
# Warmup Iteration 1: opening 0 ...Opening heap... Encountered error opening pool. Please check if /dev/dax0.0 exists and accessible.
<forked VM failed with exit code 255>
<stdout last='20 lines'>
Encountered error opening pool. Please check if /dev/dax0.0 exists and accessible.
</stdout>
<stderr last='20 lines'>
</stderr>
My config is :
jerry@u19:~$ ls /dev/dax0.0 -lr
crw-rw-rw- 1 root root 250, 1 Dec 18 08:26 /dev/dax0.0
jerry@u19:~$ ndctl list
[
{
"dev":"namespace0.0",
"mode":"devdax",
"map":"dev",
"size":4225761280,
"uuid":"bee3770d-cfc6-46e4-a254-5ce12c22ef43",
"chardev":"dax0.0"
}
]
jerry@u19:~/$ cat config.properties
# HOW-TO
# Two parameters MUST be specified:
# - path: path to persistent memory pool; this could be one of the following:
# - path to a file acting as the memory pool, possibly in a PMEM-aware file system; e.g. /mnt/mem/persistent_heap
# - path to a device DAX, e.g. /dev/dax0.0
# - path to a fused poolset configuration file, e.g. ~/pcj/myobjpool.set
# - size: size of the memory pool; this could be one of the following:
# - if using a file-based memory pool: set to any desired pool size not exceeding the size of the device the file is on
# - if using a device DAX or fused poolset: MUST set to 0; the whole device(s) will be used; any other value will result in an error
path=/dev/dax0.0
size=2147483648
I run my code as follow:
import lib.util.persistent.*;
public class Main {
public static void main(String[] args) {
PersistentArray<PersistentString> string = new PersistentArray<>(100);
ObjectDirectory.put("data",string);
string.set(0,new PersistentString("hello"));
System.out.println(string.get(0));
}
}
then raise error:
Opening heap... Encountered error opening pool! Please check if /home/ziqi/pmemdir exists and accessible.
I can use pmdk in C project with the path "/home/ziqi/pmemdir".
OS:Ubuntu 14.04
memory:16G(8G for emulate persistent memory)
The permission of /home/ziqi/pmemdir is 777
Just starting up with this library and trying to use it. Doing some learning. After I setup the project in IDE got a compilation issue at
https://github.com/pmem/pcj/blob/master/src/main/java/lib/util/persistent/RawString.java#L35
The MemoryRegion is declared final but we do an assignment here. But while making or building there is no such error.
If not, I can submit a PR for this.
It would be good to have a Jigsaw (Java 9) module for this library.
The library has System.exit
sprinkled over the code base causing the shutdown of the entire application on error. This is considered bad practice, instead exceptions should be thrown.
/usr/lib/jvm/jdk1.8.0_231/bin/javac -Xlint:unchecked -XDenableSunApiLintControl -proc:none -d target/test_classes -cp src:target/classes:lib:src:lib/ST-4.0.8.jar: src/test/java/tests/PersistentLinkedQueueTest.java src/test/java/tests/PersistentLinkedListTest.java src/test/java/tests/TestCases.java src/test/java/tests/PersistentSIHashMapTest.java src/test/java/tests/PersistentFPTree2Test.java src/test/java/tests/PersistentArrayTest.java src/test/java/tests/PersistentTestRunner.java src/test/java/tests/ObjectDirectoryTest.java src/test/java/tests/PersistentFPTree1Test.java src/test/java/tests/PersistentHashMapTest.java src/test/java/tests/PersistentTupleTest.java src/test/java/tests/PersistentAtomicReferenceTest.java src/test/java/tests/PersistentSkipListMapTest.java src/test/java/tests/MultithreadTest.java src/test/java/tests/PersistentByteBufferTest.java src/test/java/tests/PersistentArrayListTest.java
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8 -Djava.library.path=/usr/local/lib
/usr/lib/jvm/jdk1.8.0_231/bin/java -ea -cp target/classes:lib:src:lib/ST-4.0.8.jar::target/test_classes:src -Djava.library.path=target/cppbuild tests.PersistentTestRunner
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8 -Djava.library.path=/usr/local/lib
Opening heap... Exception in thread "main" java.lang.ExceptionInInitializerError
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at lib.util.persistent.ClassInfo.initReconstructor(ClassInfo.java:139)
at lib.util.persistent.ClassInfo.<init>(ClassInfo.java:74)
at lib.util.persistent.ClassInfo.init(ClassInfo.java:125)
at lib.xpersistent.XHeap.open(XHeap.java:83)
at tests.PersistentTestRunner.main(PersistentTestRunner.java:32)
Caused by: java.lang.NullPointerException
at lib.util.persistent.ObjectCache.lambda$objectForAddress$2(ObjectCache.java:184)
at lib.util.persistent.Util.synchronizedBlock(Util.java:119)
at lib.util.persistent.ObjectCache.objectForAddress(ObjectCache.java:172)
at lib.util.persistent.ObjectCache.getReference(ObjectCache.java:137)
at lib.util.persistent.ObjectCache.get(ObjectCache.java:120)
at lib.util.persistent.ObjectCache.get(ObjectCache.java:114)
at lib.util.persistent.AbstractPersistentMutableArray.getObject(AbstractPersistentMutableArray.java:85)
at lib.util.persistent.AnyPersistent.getObject(AnyPersistent.java:221)
at lib.util.persistent.AbstractPersistentArray.getObjectElement(AbstractPersistentArray.java:70)
at lib.util.persistent.PersistentArray.get(PersistentArray.java:86)
at lib.util.persistent.PersistentHashMap.getNode(PersistentHashMap.java:427)
at lib.util.persistent.PersistentHashMap.get(PersistentHashMap.java:303)
at lib.util.persistent.ObjectDirectory.get(ObjectDirectory.java:36)
at lib.util.persistent.PersistentArrayList.<clinit>(PersistentArrayList.java:57)
... 7 more
make: *** [Makefile:83: tests] Error 1
relevent code is in ObjectCache.java:
@SuppressWarnings("unchecked")
static <T extends AnyPersistent> Ref<T> objectForAddress(long address, boolean forAdmin) {
final Address addr = new Address(address);
return Util.synchronizedBlock(cacheLock, ()->{
Ref<T> ans = null;
if ((ans = (Ref<T>)cache.get(addr)) != null && ans.get() != null) {
// trace(true, address, "OFA HIT: in OC");
// assert(ans.get() != null);
return ans;
}
else {
T obj = null;
MemoryRegion region = new UncheckedPersistentMemoryRegion(address);
long classInfoAddress = region.getLong(0);
ClassInfo ci = ClassInfo.getClassInfo(classInfoAddress); // ci is Null !!!
ObjectType<T> type = Types.typeForName(ci.className());
obj = AnyPersistent.reconstruct(new ObjectPointer<T>((ObjectType)type, region));
ans = new Ref(obj, forAdmin);
if (!Transaction.addReconstructedObject(address, ans)) cache.put(addr, ans);
}
return ans;
});
}```
On ubuntu 19.
jerry@u19:~/opensources/pcj$ sudo fdisk -l /dev/pmem0
Disk /dev/pmem0: 4 GiB, 4294967296 bytes, 8388608 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
jerry@u19:~/opensources/pcj$ mount | grep pmem0
/dev/pmem0 on /mnt/mem type ext4 (rw,relatime,dax)
What does PCJ decides to use GPL , not just like others PMDK? is it special?
Explicitly set the source and target language level used by javac. The project says the source level is 1.8 but it is not configured by javac.
There seems synchronized
sprinkled over the code base but I could not find any documented synchronization policy that specifies which objects can and can't be shared in which ways.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.