Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JNI bindings for FileStorage #61

Merged
merged 22 commits into from
Jun 23, 2024
Merged

JNI bindings for FileStorage #61

merged 22 commits into from
Jun 23, 2024

Conversation

twitu
Copy link
Collaborator

@twitu twitu commented May 14, 2024

Add JNI bindings for FileStorage to create an instance and for all BaseStorage functions.

Once a FileStorage instance is created, it is boxed and leaked as jlong. This jlong can then be upcasted back to a FileStorage instance. All BaseStorage functions take the jlong as an argument upcast it and then perform the necessary operations.

Note: FileStorage needs to be specialized to use with JNI. After discussion, I've specialized it to FileStorage<String, String>, however it can be easily changed.

TODO:

  • Store the jlong in the class instance itself rather than returning it. It will reduce the amount of Java/Kotlin wrapper code that needs to be written
  • Handle Results better - Should they return a default value or should they thrown an exception? open to discussion
  • Support read_fs? It returns the key value pairs as a BTreeMap, however jni by default does not know how to convert BTreeMap to Java's LinkedHashMap. Do we want to support the read_fs operation for JNI bindings? This means we'll have to implement a custom conversion logic from BTreeMap to LinkedHashMap

@twitu
Copy link
Collaborator Author

twitu commented May 14, 2024

The function Java_FileStorage_read_fs implements the conversion from BTreeMap to LinkedHashMap. Going from non-trivial Rust container types to Java container types requires a lot of conversion logic. It will be good to benchmark and decide if it's worth the complexity.

Copy link

Benchmark for a123167

Click to view benchmark
Test Base PR %
../test-assets/lena.jpg/compute_bytes 13.3±0.12µs 13.3±0.06µs 0.00%
../test-assets/test.pdf/compute_bytes 110.3±2.05µs 108.5±0.76µs -1.63%
compute_bytes_large/compute_bytes 137.0±1.57µs 141.2±1.14µs +3.07%
compute_bytes_medium/compute_bytes 27.8±0.31µs 27.6±0.56µs -0.72%
compute_bytes_small/compute_bytes 129.0±8.07ns 128.4±4.03ns -0.47%
index_build/index_build/../test-assets/ 164.8±2.77µs 164.5±2.45µs -0.18%

@kirillt
Copy link
Member

kirillt commented May 15, 2024

@twitu thanks, looks like a good start!

Note: FileStorage needs to be specialized to use with JNI. After discussion, I've specialized it to FileStorage<String, String>, however it can be easily changed.

Type String for both keys and values sounds good. Probably we'll change it to bytes later, but after benchmarking.

Store the jlong in the class instance itself rather than returning it. It will reduce the amount of Java/Kotlin wrapper code that needs to be written

I think we shouldn't mix JNI code into pure Rust structures. Desktop developers should not be affected by JNI. Building and importing fs-storage alone should not trigger building or importing JNI code. Actually, we need to move all JNI stuff into separate crate fs-storage-jni, or even directly to ark-android.

Handle Results better - Should they return a default value or should they thrown an exception? open to discussion

Is there a way to reconstruct Result/Option type? Or would it be too inefficient?

Support read_fs?

Yes, but converting whole structures really sounds inefficient.. Is it too wild to create JNI bindings for BTreeMap itself? Do we have same problem with Rust HashMap? I guess we'd need to iterate anyway but probably there are some ready-made crates for binding maps. If we can bind HashMap probably we can fork the code and implement same for BTreeMap.

@twitu
Copy link
Collaborator Author

twitu commented May 20, 2024

The JNI bindings can be put behind a feature flag and they will only be compiled when the feature flag is set on. Separating the bindings from the logic may not be very helpful it is closely tied to the logic.

There's no good way to wrap a generic Result type in a way that's accessible to Java. Option is doable but then it will lose out on a lot of useful information. I guess in this case the best approach is to return Java Exceptions and the let the library user figure out how to handle it and it some rare cases return a default value where it makes sense.

I looked in implementation for wrapping container types, especially using jnix. It converts container types to Java in a way that's very similar to the one we've implemented for LinkedHashMap basically initializing the java object and inserting values into it. Very bad from an efficiency standpoint.

A more efficient way will be to keep the BTreeMap on the Rust side and define a specific set of operations on it through the jni bindings. I guess the most basic operation will be to get the value for a key. Perhaps a method to iterate over all the values. Do you think any other operations will be useful to library users?

Copy link

Benchmark for 744c333

Click to view benchmark
Test Base PR %
../test-assets/lena.jpg/compute_bytes 13.9±0.15µs 14.0±0.19µs +0.72%
../test-assets/test.pdf/compute_bytes 116.2±2.12µs 130.4±1.06µs +12.22%
compute_bytes_large/compute_bytes 151.4±1.97µs 177.7±2.29µs +17.37%
compute_bytes_medium/compute_bytes 27.9±0.50µs 27.4±0.29µs -1.79%
compute_bytes_small/compute_bytes 131.2±1.38ns 131.4±3.19ns +0.15%
index_build/index_build/../test-assets/ 158.8±0.54µs 160.5±0.66µs +1.07%

Copy link

Benchmark for 8396b25

Click to view benchmark
Test Base PR %
../test-assets/lena.jpg/compute_bytes 13.9±0.09µs 13.9±0.12µs 0.00%
../test-assets/test.pdf/compute_bytes 171.2±0.80µs 114.2±0.55µs -33.29%
compute_bytes_large/compute_bytes 141.7±1.48µs 144.1±1.48µs +1.69%
compute_bytes_medium/compute_bytes 27.8±0.17µs 27.2±0.28µs -2.16%
compute_bytes_small/compute_bytes 131.4±2.43ns 131.2±1.66ns -0.15%
index_build/index_build/../test-assets/ 159.0±4.48µs 158.3±0.95µs -0.44%

@kirillt
Copy link
Member

kirillt commented May 24, 2024

@twitu putting JNI bindings behind a feature flag is good-enough solution for this moment. But I think, we'll probably separate it in the future, when it's debugged. Especially, when we'll work on Swift bindings. On other hand, I can imagine having both binding flavours in the same place, together with Rust code, if it'll appear to be ergonomic enough.

There's no good way to wrap a generic Result type in a way that's accessible to Java. Option is doable but then it will lose out on a lot of useful information. I guess in this case the best approach is to return Java Exceptions and the let the library user figure out how to handle it and it some rare cases return a default value where it makes sense.

Can't we convert Rust Result into Kotlin Result?

A more efficient way will be to keep the BTreeMap on the Rust side and define a specific set of operations on it through the jni bindings. I guess the most basic operation will be to get the value for a key. Perhaps a method to iterate over all the values. Do you think any other operations will be useful to library users?

I like this approach. Not sure what exactly operations we'd need right now. We could make it a separate repo later, containing useful structures and more-or-less complete API. For now, the methods necessary to demonstrate storages are enough.

Store the jlong in the class instance itself rather than returning it. It will reduce the amount of Java/Kotlin wrapper code that needs to be written

Do you want to do it in this PR or in a follow-up?

Copy link

Benchmark for f21bb89

Click to view benchmark
Test Base PR %
blake3_resource_id_creation/compute_from_bytes:large 248.9±0.82µs 251.2±1.50µs +0.92%
blake3_resource_id_creation/compute_from_bytes:medium 15.6±0.06µs 15.6±0.15µs 0.00%
blake3_resource_id_creation/compute_from_bytes:small 1347.4±1.50ns 1347.9±9.98ns +0.04%
blake3_resource_id_creation/compute_from_path:../test-assets/lena.jpg 195.7±0.40µs 196.6±2.62µs +0.46%
blake3_resource_id_creation/compute_from_path:../test-assets/test.pdf 1728.7±6.44µs 1725.8±12.55µs -0.17%
crc32_resource_id_creation/compute_from_bytes:large 86.6±0.19µs 86.8±0.50µs +0.23%
crc32_resource_id_creation/compute_from_bytes:medium 5.4±0.02µs 5.4±0.04µs 0.00%
crc32_resource_id_creation/compute_from_bytes:small 92.3±0.21ns 92.5±0.62ns +0.22%
crc32_resource_id_creation/compute_from_path:../test-assets/lena.jpg 64.4±0.34µs 64.5±0.31µs +0.16%
crc32_resource_id_creation/compute_from_path:../test-assets/test.pdf 930.5±14.54µs 924.7±3.49µs -0.62%
index_build/index_build/../test-assets/ 1072.2±14.26µs 1066.7±6.05µs -0.51%

Copy link

Benchmark for 437cc53

Click to view benchmark
Test Base PR %
blake3_resource_id_creation/compute_from_bytes:large 249.3±0.96µs 248.7±1.39µs -0.24%
blake3_resource_id_creation/compute_from_bytes:medium 15.6±0.06µs 15.6±0.06µs 0.00%
blake3_resource_id_creation/compute_from_bytes:small 1345.3±9.36ns 1387.7±19.84ns +3.15%
blake3_resource_id_creation/compute_from_path:../test-assets/lena.jpg 195.9±0.56µs 195.1±0.79µs -0.41%
blake3_resource_id_creation/compute_from_path:../test-assets/test.pdf 1726.0±9.55µs 1730.0±16.34µs +0.23%
crc32_resource_id_creation/compute_from_bytes:large 87.0±0.94µs 86.9±0.57µs -0.11%
crc32_resource_id_creation/compute_from_bytes:medium 5.4±0.02µs 5.4±0.04µs 0.00%
crc32_resource_id_creation/compute_from_bytes:small 92.4±0.33ns 92.4±0.68ns 0.00%
crc32_resource_id_creation/compute_from_path:../test-assets/lena.jpg 64.6±0.19µs 64.6±0.29µs 0.00%
crc32_resource_id_creation/compute_from_path:../test-assets/test.pdf 922.2±4.56µs 927.2±5.17µs +0.54%
index_build/index_build/../test-assets/ 1072.7±36.26µs 1064.2±23.18µs -0.79%

Copy link

Benchmark for a0f6bdf

Click to view benchmark
Test Base PR %
blake3_resource_id_creation/compute_from_bytes:large 255.2±3.33µs 251.0±1.29µs -1.65%
blake3_resource_id_creation/compute_from_bytes:medium 15.7±0.18µs 15.7±0.55µs 0.00%
blake3_resource_id_creation/compute_from_bytes:small 1350.6±1.87ns 1351.9±15.36ns +0.10%
blake3_resource_id_creation/compute_from_path:../test-assets/lena.jpg 195.8±2.07µs 196.1±0.67µs +0.15%
blake3_resource_id_creation/compute_from_path:../test-assets/test.pdf 1722.6±17.26µs 1726.6±33.73µs +0.23%
crc32_resource_id_creation/compute_from_bytes:large 86.8±0.93µs 86.8±1.41µs 0.00%
crc32_resource_id_creation/compute_from_bytes:medium 5.4±0.15µs 5.4±0.14µs 0.00%
crc32_resource_id_creation/compute_from_bytes:small 92.7±1.80ns 92.4±0.59ns -0.32%
crc32_resource_id_creation/compute_from_path:../test-assets/lena.jpg 64.8±2.59µs 64.7±1.41µs -0.15%
crc32_resource_id_creation/compute_from_path:../test-assets/test.pdf 923.6±2.28µs 923.2±4.82µs -0.04%
index_build/index_build/../test-assets/ 1073.0±37.34µs 1075.8±23.74µs +0.26%

Copy link

Benchmark for 95b2160

Click to view benchmark
Test Base PR %
blake3_resource_id_creation/compute_from_bytes:large 250.7±1.06µs 249.4±1.09µs -0.52%
blake3_resource_id_creation/compute_from_bytes:medium 15.6±0.06µs 15.6±0.04µs 0.00%
blake3_resource_id_creation/compute_from_bytes:small 1351.9±5.86ns 1350.0±1.51ns -0.14%
blake3_resource_id_creation/compute_from_path:../test-assets/lena.jpg 197.2±0.60µs 195.7±1.04µs -0.76%
blake3_resource_id_creation/compute_from_path:../test-assets/test.pdf 1723.7±3.11µs 1728.3±22.39µs +0.27%
crc32_resource_id_creation/compute_from_bytes:large 86.9±0.41µs 87.0±0.52µs +0.12%
crc32_resource_id_creation/compute_from_bytes:medium 5.4±0.03µs 5.4±0.04µs 0.00%
crc32_resource_id_creation/compute_from_bytes:small 92.6±2.08ns 92.3±0.39ns -0.32%
crc32_resource_id_creation/compute_from_path:../test-assets/lena.jpg 64.8±0.50µs 64.8±0.33µs 0.00%
crc32_resource_id_creation/compute_from_path:../test-assets/test.pdf 927.9±2.90µs 930.5±7.81µs +0.28%
index_build/index_build/../test-assets/ 1068.9±6.42µs 1068.1±5.00µs -0.07%

Copy link

Benchmark for ad27900

Click to view benchmark
Test Base PR %
blake3_resource_id_creation/compute_from_bytes:large 252.0±0.58µs 250.8±8.81µs -0.48%
blake3_resource_id_creation/compute_from_bytes:medium 15.6±0.07µs 15.7±0.07µs +0.64%
blake3_resource_id_creation/compute_from_bytes:small 1351.1±4.62ns 1350.7±1.79ns -0.03%
blake3_resource_id_creation/compute_from_path:../test-assets/lena.jpg 195.9±0.52µs 195.7±1.08µs -0.10%
blake3_resource_id_creation/compute_from_path:../test-assets/test.pdf 1728.7±8.42µs 1724.1±15.18µs -0.27%
crc32_resource_id_creation/compute_from_bytes:large 86.8±0.23µs 87.0±2.78µs +0.23%
crc32_resource_id_creation/compute_from_bytes:medium 5.4±0.10µs 5.4±0.07µs 0.00%
crc32_resource_id_creation/compute_from_bytes:small 92.3±0.21ns 92.4±0.53ns +0.11%
crc32_resource_id_creation/compute_from_path:../test-assets/lena.jpg 64.5±0.60µs 64.4±0.22µs -0.16%
crc32_resource_id_creation/compute_from_path:../test-assets/test.pdf 929.0±9.57µs 926.4±8.99µs -0.28%
index_build/index_build/../test-assets/ 1073.4±56.19µs 1067.4±10.07µs -0.56%

Copy link

Benchmark for 7d98c27

Click to view benchmark
Test Base PR %
blake3_resource_id_creation/compute_from_bytes:large 249.1±0.75µs 248.5±1.52µs -0.24%
blake3_resource_id_creation/compute_from_bytes:medium 15.6±0.03µs 15.6±0.08µs 0.00%
blake3_resource_id_creation/compute_from_bytes:small 1388.4±6.03ns 1387.9±2.54ns -0.04%
blake3_resource_id_creation/compute_from_path:../test-assets/lena.jpg 195.7±1.81µs 196.7±2.44µs +0.51%
blake3_resource_id_creation/compute_from_path:../test-assets/test.pdf 1720.0±5.61µs 1739.4±33.58µs +1.13%
crc32_resource_id_creation/compute_from_bytes:large 86.8±1.49µs 86.9±1.45µs +0.12%
crc32_resource_id_creation/compute_from_bytes:medium 5.4±0.02µs 5.4±0.03µs 0.00%
crc32_resource_id_creation/compute_from_bytes:small 92.4±0.39ns 92.5±1.10ns +0.11%
crc32_resource_id_creation/compute_from_path:../test-assets/lena.jpg 64.4±0.36µs 64.4±0.52µs 0.00%
crc32_resource_id_creation/compute_from_path:../test-assets/test.pdf 924.2±5.87µs 926.2±13.52µs +0.22%
index_build/index_build/../test-assets/ 1069.1±17.10µs 1067.9±4.10µs -0.11%

@Pushkarm029 Pushkarm029 requested review from kirillt and tareknaser June 1, 2024 14:06
Copy link
Collaborator

@tareknaser tareknaser left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks.
I'm not sure I can review the Java part, but I left some general comments.

fs-storage/src/file_storage.rs Outdated Show resolved Hide resolved
fs-storage/tests/Makefile Outdated Show resolved Hide resolved
fs-storage/src/utils.rs Outdated Show resolved Hide resolved
fs-storage/tests/Makefile Outdated Show resolved Hide resolved
fs-storage/src/file_storage.rs Outdated Show resolved Hide resolved
Copy link

github-actions bot commented Jun 2, 2024

Benchmark for 2fccdfa

Click to view benchmark
Test Base PR %
blake3_resource_id_creation/compute_from_bytes:large 248.2±0.58µs 249.4±1.18µs +0.48%
blake3_resource_id_creation/compute_from_bytes:medium 15.6±0.07µs 15.6±0.07µs 0.00%
blake3_resource_id_creation/compute_from_bytes:small 1348.4±3.02ns 1335.6±10.81ns -0.95%
blake3_resource_id_creation/compute_from_path:../test-assets/lena.jpg 195.1±0.54µs 195.6±0.51µs +0.26%
blake3_resource_id_creation/compute_from_path:../test-assets/test.pdf 1709.2±4.56µs 1716.2±9.47µs +0.41%
crc32_resource_id_creation/compute_from_bytes:large 86.9±0.29µs 87.4±2.66µs +0.58%
crc32_resource_id_creation/compute_from_bytes:medium 5.4±0.02µs 5.4±0.07µs 0.00%
crc32_resource_id_creation/compute_from_bytes:small 92.4±0.36ns 92.5±0.81ns +0.11%
crc32_resource_id_creation/compute_from_path:../test-assets/lena.jpg 64.8±0.41µs 64.8±0.47µs 0.00%
crc32_resource_id_creation/compute_from_path:../test-assets/test.pdf 931.9±2.37µs 935.1±4.74µs +0.34%
index_build/index_build/../test-assets/ 1063.7±16.87µs 1059.9±12.15µs -0.36%

Copy link

github-actions bot commented Jun 2, 2024

Benchmark for 792a49f

Click to view benchmark
Test Base PR %
blake3_resource_id_creation/compute_from_bytes:large 249.4±0.51µs 252.2±0.46µs +1.12%
blake3_resource_id_creation/compute_from_bytes:medium 15.5±0.02µs 15.6±0.06µs +0.65%
blake3_resource_id_creation/compute_from_bytes:small 1342.8±9.64ns 1343.2±2.29ns +0.03%
blake3_resource_id_creation/compute_from_path:../test-assets/lena.jpg 195.3±0.87µs 195.3±0.77µs 0.00%
blake3_resource_id_creation/compute_from_path:../test-assets/test.pdf 1710.3±5.65µs 1715.9±38.18µs +0.33%
crc32_resource_id_creation/compute_from_bytes:large 86.9±0.39µs 87.1±0.69µs +0.23%
crc32_resource_id_creation/compute_from_bytes:medium 5.4±0.02µs 5.4±0.03µs 0.00%
crc32_resource_id_creation/compute_from_bytes:small 92.3±0.46ns 92.4±0.34ns +0.11%
crc32_resource_id_creation/compute_from_path:../test-assets/lena.jpg 64.4±0.50µs 64.5±1.15µs +0.16%
crc32_resource_id_creation/compute_from_path:../test-assets/test.pdf 934.1±4.18µs 932.6±5.89µs -0.16%
index_build/index_build/../test-assets/ 1057.6±5.70µs 1062.6±4.06µs +0.47%

Copy link

github-actions bot commented Jun 2, 2024

Benchmark for 5e2dc89

Click to view benchmark
Test Base PR %
blake3_resource_id_creation/compute_from_bytes:large 249.2±0.60µs 249.9±1.89µs +0.28%
blake3_resource_id_creation/compute_from_bytes:medium 15.6±0.08µs 15.5±0.11µs -0.64%
blake3_resource_id_creation/compute_from_bytes:small 1345.6±2.13ns 1344.6±7.95ns -0.07%
blake3_resource_id_creation/compute_from_path:../test-assets/lena.jpg 195.2±0.50µs 195.9±0.52µs +0.36%
blake3_resource_id_creation/compute_from_path:../test-assets/test.pdf 1725.5±3.35µs 1714.3±14.92µs -0.65%
crc32_resource_id_creation/compute_from_bytes:large 86.8±0.38µs 86.7±0.25µs -0.12%
crc32_resource_id_creation/compute_from_bytes:medium 5.4±0.09µs 5.4±0.05µs 0.00%
crc32_resource_id_creation/compute_from_bytes:small 92.4±0.47ns 92.4±0.45ns 0.00%
crc32_resource_id_creation/compute_from_path:../test-assets/lena.jpg 64.3±0.35µs 64.5±0.35µs +0.31%
crc32_resource_id_creation/compute_from_path:../test-assets/test.pdf 930.4±4.87µs 931.1±4.28µs +0.08%
index_build/index_build/../test-assets/ 1059.1±4.81µs 1058.0±8.23µs -0.10%

Copy link

github-actions bot commented Jun 2, 2024

Benchmark for cc2e79b

Click to view benchmark
Test Base PR %
blake3_resource_id_creation/compute_from_bytes:large 247.4±0.57µs 248.3±0.95µs +0.36%
blake3_resource_id_creation/compute_from_bytes:medium 15.6±0.03µs 15.5±0.11µs -0.64%
blake3_resource_id_creation/compute_from_bytes:small 1357.3±2.01ns 1333.6±10.45ns -1.75%
blake3_resource_id_creation/compute_from_path:../test-assets/lena.jpg 195.2±0.58µs 195.2±0.47µs 0.00%
blake3_resource_id_creation/compute_from_path:../test-assets/test.pdf 1706.1±6.42µs 1716.6±32.25µs +0.62%
crc32_resource_id_creation/compute_from_bytes:large 86.7±0.32µs 86.8±0.60µs +0.12%
crc32_resource_id_creation/compute_from_bytes:medium 5.4±0.02µs 5.5±0.35µs +1.85%
crc32_resource_id_creation/compute_from_bytes:small 92.3±0.18ns 92.4±0.43ns +0.11%
crc32_resource_id_creation/compute_from_path:../test-assets/lena.jpg 64.4±0.72µs 64.6±0.66µs +0.31%
crc32_resource_id_creation/compute_from_path:../test-assets/test.pdf 931.8±3.54µs 932.2±3.99µs +0.04%
index_build/index_build/../test-assets/ 1058.7±4.23µs 1059.3±10.60µs +0.06%

Copy link

github-actions bot commented Jun 2, 2024

Benchmark for 8ceb461

Click to view benchmark
Test Base PR %
blake3_resource_id_creation/compute_from_bytes:large 251.4±0.46µs 253.2±14.03µs +0.72%
blake3_resource_id_creation/compute_from_bytes:medium 15.6±0.12µs 15.5±0.04µs -0.64%
blake3_resource_id_creation/compute_from_bytes:small 1343.5±1.66ns 1348.8±1.38ns +0.39%
blake3_resource_id_creation/compute_from_path:../test-assets/lena.jpg 195.0±0.62µs 195.1±0.73µs +0.05%
blake3_resource_id_creation/compute_from_path:../test-assets/test.pdf 1711.7±6.45µs 1714.5±18.05µs +0.16%
crc32_resource_id_creation/compute_from_bytes:large 86.8±0.42µs 86.8±0.25µs 0.00%
crc32_resource_id_creation/compute_from_bytes:medium 5.4±0.31µs 5.4±0.03µs 0.00%
crc32_resource_id_creation/compute_from_bytes:small 92.4±0.44ns 92.4±0.42ns 0.00%
crc32_resource_id_creation/compute_from_path:../test-assets/lena.jpg 64.8±0.35µs 64.5±0.28µs -0.46%
crc32_resource_id_creation/compute_from_path:../test-assets/test.pdf 929.0±3.96µs 928.7±5.01µs -0.03%
index_build/index_build/../test-assets/ 1058.0±18.98µs 1061.8±6.51µs +0.36%

@Pushkarm029
Copy link
Collaborator

CI is failing due to Java warnings. It is running perfectly locally.

@tareknaser
Copy link
Collaborator

The logs from the failing CI show that there is probably an error not just warnings

cd tests && \
if [ ! -f "junit.jar" ]; then \
	curl -o "junit.jar" "https://repo1.maven.org/maven2/org/junit/platform/junit-platform-console-standalone/1.9.3/junit-platform-console-standalone-1.9.3.jar"; \
else \
	echo "junit.jar already exists."; \
fi
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
100 2552k  100 2552k    0     0  9533k      0 --:--:-- --:--:-- --:--:-- 9525k
(cd ../target/debug && \
export LD_LIBRARY_PATH=$PWD && \
cd ../../fs-storage/tests && \
javac -Xlint:none -d out FileStorage.java && \
javac -Xlint:none -d out -cp out:junit.jar FileStorageTest.java && \
java -jar junit.jar --class-path out --scan-class-path)
Note: FileStorageTest.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
thread '<unnamed>' panicked at /home/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/jni-0.21.1/src/wrapper/jnienv.rs:520:9:
NullDeref("*JNIEnv")
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
fatal runtime error: failed to initiate panic, error 5
Aborted (core dumped)
make: *** [Makefile:24: java-test] Error 134

@Pushkarm029
Copy link
Collaborator

locally i am getting this : (im on debian)

pushkarm029@thinkpad:~/ark-rust(jni-bindings○) » cd fs-storage
pushkarm029@thinkpad:~/ark-rust/fs-storage(jni-bindings○) » make test
cargo build --release --features jni-bindings
    Finished `release` profile [optimized] target(s) in 0.24s
cd tests && \
if [ ! -f "junit.jar" ]; then \
	curl -o "junit.jar" "https://repo1.maven.org/maven2/org/junit/platform/junit-platform-console-standalone/1.9.3/junit-platform-console-standalone-1.9.3.jar"; \
else \
	echo "junit.jar already exists."; \
fi
junit.jar already exists.
(cd ../target/debug && \
export LD_LIBRARY_PATH=$PWD && \
cd ../../fs-storage/tests && \
javac -Xlint:none -d out FileStorage.java && \
javac -Xlint:none -d out -cp out:junit.jar FileStorageTest.java && \
java -jar junit.jar --class-path out --scan-class-path)
Note: FileStorageTest.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.

Thanks for using JUnit! Support its development at https://junit.org/sponsoring

╷
├─ JUnit Jupiter ✔
│  └─ FileStorageTest ✔
│     ├─ testFileStorageNeedsSyncing() ✔
│     ├─ testFileStorageMonoidCombine() ✔
│     ├─ testFileStorageAutoDelete() ✔
│     ├─ testFileStorageMainScenario() ✔
│     └─ testFileStorageWriteRead() ✔
├─ JUnit Vintage ✔
└─ JUnit Platform Suite ✔

Test run finished after 186 ms
[         4 containers found      ]
[         0 containers skipped    ]
[         4 containers started    ]
[         0 containers aborted    ]
[         4 containers successful ]
[         0 containers failed     ]
[         5 tests found           ]
[         0 tests skipped         ]
[         5 tests started         ]
[         0 tests aborted         ]
[         5 tests successful      ]
[         0 tests failed          ]

Copy link
Collaborator Author

@twitu twitu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Pushkarm029 in your last commit returning jstring from all functions is not a proper solution to handling errors.

A Rust Result<T> cannot be returned directly across jni bindings because bindings don't allow passing generics. There is no good way to communicate if the Result contains a bool, or integer or string or something else.

There are two possible options to consider -

  • Return exceptions - throw exception using throw function in JNIEnv. Perhaps mplement a conversion from ArkStorageError to jni::error::Exception if it's not ergonomic by default.

  • Implement a conversion to Kotlin Result type1 by creating a native java object similar to how a BTreeMap is transformed into a LinkedHashMap.

Note: that the error message in both cases will be a string version of the ArkStorageError

Footnotes

  1. https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-result/

@twitu
Copy link
Collaborator Author

twitu commented Jun 10, 2024

* [ ]  Store the `jlong` in the class instance itself rather than returning it

The main purpose of this point was to avoid the writing the Java wrapper code like the one implemented in FileStorage.java. This java code wraps around the static methods exposed by the rust jni bindings. I wanted to avoid this by hiding the state of the FileStorage and directly exposing the a FileStorage Java object.

However, that does not seem to be possible based on my exploration. There is no way to create Java class instances with hidden state1 on the Rust side that can then be transferred over through JNI bindings. Even looking through the documentation of jni and jnix there is no way to define a Java "class" on the Rust side. It only provides functionality to convert between Rust and Java data types and export static methods through JNI bindings.

As such, I believe this PR is ready to merge. The syncing logic PR can adopt these changes as it might take more time to identify and fix the timestamp bug in it.

Footnotes

  1. https://stackoverflow.com/questions/25025956/create-anonymous-java-class-in-c-via-jni

Copy link

Benchmark for 70a378a

Click to view benchmark
Test Base PR %
blake3_resource_id_creation/compute_from_bytes:large 250.8±0.66µs 248.9±1.45µs -0.76%
blake3_resource_id_creation/compute_from_bytes:medium 15.6±0.20µs 15.6±0.14µs 0.00%
blake3_resource_id_creation/compute_from_bytes:small 1351.1±7.93ns 1355.8±9.65ns +0.35%
blake3_resource_id_creation/compute_from_path:../test-assets/lena.jpg 196.0±1.23µs 199.0±0.80µs +1.53%
blake3_resource_id_creation/compute_from_path:../test-assets/test.pdf 1741.2±5.12µs 1765.0±25.00µs +1.37%
crc32_resource_id_creation/compute_from_bytes:large 86.6±0.27µs 86.8±1.55µs +0.23%
crc32_resource_id_creation/compute_from_bytes:medium 5.4±0.03µs 5.4±0.05µs 0.00%
crc32_resource_id_creation/compute_from_bytes:small 92.6±0.36ns 92.7±0.75ns +0.11%
crc32_resource_id_creation/compute_from_path:../test-assets/lena.jpg 65.7±0.15µs 65.4±0.50µs -0.46%
crc32_resource_id_creation/compute_from_path:../test-assets/test.pdf 953.1±6.08µs 950.6±3.60µs -0.26%
index_build/index_build/../test-assets/ 1049.5±8.09µs 1046.5±47.55µs -0.29%

Copy link

Benchmark for 24437c5

Click to view benchmark
Test Base PR %
blake3_resource_id_creation/compute_from_bytes:large 248.2±0.86µs 248.7±1.23µs +0.20%
blake3_resource_id_creation/compute_from_bytes:medium 15.6±0.20µs 15.6±0.14µs 0.00%
blake3_resource_id_creation/compute_from_bytes:small 1344.4±6.72ns 1344.5±2.20ns +0.01%
blake3_resource_id_creation/compute_from_path:../test-assets/lena.jpg 197.0±3.71µs 196.8±3.55µs -0.10%
blake3_resource_id_creation/compute_from_path:../test-assets/test.pdf 1744.8±14.52µs 1739.9±15.98µs -0.28%
crc32_resource_id_creation/compute_from_bytes:large 86.7±0.69µs 86.7±0.41µs 0.00%
crc32_resource_id_creation/compute_from_bytes:medium 5.4±0.04µs 5.4±0.02µs 0.00%
crc32_resource_id_creation/compute_from_bytes:small 92.8±1.65ns 92.9±1.54ns +0.11%
crc32_resource_id_creation/compute_from_path:../test-assets/lena.jpg 65.4±1.21µs 65.4±0.66µs 0.00%
crc32_resource_id_creation/compute_from_path:../test-assets/test.pdf 959.3±2.76µs 951.7±6.97µs -0.79%
index_build/index_build/../test-assets/ 1053.5±38.06µs 1049.7±5.06µs -0.36%

Signed-off-by: pushkarm029 <[email protected]>
Copy link

Benchmark for d4baf9c

Click to view benchmark
Test Base PR %
blake3_resource_id_creation/compute_from_bytes:large 248.6±0.62µs 250.4±0.57µs +0.72%
blake3_resource_id_creation/compute_from_bytes:medium 15.7±0.53µs 15.6±0.09µs -0.64%
blake3_resource_id_creation/compute_from_bytes:small 1364.7±1.54ns 1347.3±3.87ns -1.28%
blake3_resource_id_creation/compute_from_path:../test-assets/lena.jpg 195.4±0.24µs 195.5±0.43µs +0.05%
blake3_resource_id_creation/compute_from_path:../test-assets/test.pdf 1739.4±2.69µs 1746.3±38.85µs +0.40%
crc32_resource_id_creation/compute_from_bytes:large 86.7±0.45µs 86.6±0.26µs -0.12%
crc32_resource_id_creation/compute_from_bytes:medium 5.4±0.03µs 5.4±0.05µs 0.00%
crc32_resource_id_creation/compute_from_bytes:small 92.7±0.38ns 92.8±1.34ns +0.11%
crc32_resource_id_creation/compute_from_path:../test-assets/lena.jpg 65.4±0.21µs 66.0±1.56µs +0.92%
crc32_resource_id_creation/compute_from_path:../test-assets/test.pdf 958.4±3.99µs 974.1±6.86µs +1.64%
index_build/index_build/../test-assets/ 1038.0±6.71µs 1047.8±53.12µs +0.94%

Signed-off-by: pushkarm029 <[email protected]>
Copy link

Benchmark for 3b12cca

Click to view benchmark
Test Base PR %
blake3_resource_id_creation/compute_from_bytes:large 252.4±0.78µs 253.7±3.15µs +0.52%
blake3_resource_id_creation/compute_from_bytes:medium 15.7±0.13µs 15.6±0.14µs -0.64%
blake3_resource_id_creation/compute_from_bytes:small 1359.7±24.94ns 1370.5±15.23ns +0.79%
blake3_resource_id_creation/compute_from_path:../test-assets/lena.jpg 196.6±2.64µs 196.0±2.83µs -0.31%
blake3_resource_id_creation/compute_from_path:../test-assets/test.pdf 1756.3±4.07µs 1749.4±32.16µs -0.39%
crc32_resource_id_creation/compute_from_bytes:large 86.8±0.34µs 86.9±1.33µs +0.12%
crc32_resource_id_creation/compute_from_bytes:medium 5.4±0.05µs 5.4±0.14µs 0.00%
crc32_resource_id_creation/compute_from_bytes:small 93.3±1.46ns 93.0±0.37ns -0.32%
crc32_resource_id_creation/compute_from_path:../test-assets/lena.jpg 65.7±2.73µs 65.1±0.89µs -0.91%
crc32_resource_id_creation/compute_from_path:../test-assets/test.pdf 962.7±15.20µs 972.7±13.15µs +1.04%
index_build/index_build/../test-assets/ 1040.1±25.37µs 1034.5±20.29µs -0.54%

Signed-off-by: pushkarm029 <[email protected]>
Copy link

Benchmark for 21d16f0

Click to view benchmark
Test Base PR %
blake3_resource_id_creation/compute_from_bytes:large 248.7±0.90µs 249.1±1.72µs +0.16%
blake3_resource_id_creation/compute_from_bytes:medium 15.6±0.12µs 15.6±0.23µs 0.00%
blake3_resource_id_creation/compute_from_bytes:small 1366.9±11.07ns 1357.4±17.38ns -0.70%
blake3_resource_id_creation/compute_from_path:../test-assets/lena.jpg 195.9±2.57µs 196.7±3.90µs +0.41%
blake3_resource_id_creation/compute_from_path:../test-assets/test.pdf 1749.0±11.41µs 1755.1±35.62µs +0.35%
crc32_resource_id_creation/compute_from_bytes:large 87.3±2.65µs 86.8±0.51µs -0.57%
crc32_resource_id_creation/compute_from_bytes:medium 5.4±0.03µs 5.4±0.09µs 0.00%
crc32_resource_id_creation/compute_from_bytes:small 93.1±0.80ns 93.0±0.45ns -0.11%
crc32_resource_id_creation/compute_from_path:../test-assets/lena.jpg 65.0±0.36µs 65.6±0.47µs +0.92%
crc32_resource_id_creation/compute_from_path:../test-assets/test.pdf 959.2±17.76µs 961.5±9.81µs +0.24%
index_build/index_build/../test-assets/ 1039.7±21.60µs 1048.5±29.73µs +0.85%

@kirillt
Copy link
Member

kirillt commented Jun 15, 2024

@twitu Could you also create tracking issue for functional error handling (Result)?

And we need the sample wired to this branch, that would be the best demo.

Copy link
Collaborator Author

@twitu twitu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Pushkarm029 the new syncing logic has introduced a new struct for SyncStatus that must be exposed through JNI along with a couple of functions added to the BaseStorage trait. Also some of the existing tests and functions need to be updated.

    /// Get [`SyncStatus`] of the storage
    fn sync_status(&self) -> Result<SyncStatus>;

    /// Sync the in-memory storage with the storage on disk
    fn sync(&mut self) -> Result<()>;

One way to expose SyncStatus is using the jnix crate which will automatically derive the conversion logic to and from java objects. Note that jnix should be feature flagged just like jni.

Kotlin style Results is scoped in a separate issue #74

Signed-off-by: pushkarm029 <[email protected]>
@Pushkarm029 Pushkarm029 requested a review from kirillt June 18, 2024 17:41
@Pushkarm029
Copy link
Collaborator

done; pls review @twitu @tareknaser

Copy link

Benchmark for a949330

Click to view benchmark
Test Base PR %
blake3_resource_id_creation/compute_from_bytes:large 248.5±1.60µs 247.7±1.31µs -0.32%
blake3_resource_id_creation/compute_from_bytes:medium 15.5±0.04µs 15.5±0.05µs 0.00%
blake3_resource_id_creation/compute_from_bytes:small 1371.2±12.84ns 1366.6±9.44ns -0.34%
blake3_resource_id_creation/compute_from_path:../test-assets/lena.jpg 197.7±1.03µs 198.0±0.62µs +0.15%
blake3_resource_id_creation/compute_from_path:../test-assets/test.pdf 1729.3±14.55µs 1732.7±17.26µs +0.20%
crc32_resource_id_creation/compute_from_bytes:large 86.8±0.81µs 86.7±0.30µs -0.12%
crc32_resource_id_creation/compute_from_bytes:medium 5.4±0.01µs 5.4±0.02µs 0.00%
crc32_resource_id_creation/compute_from_bytes:small 92.6±1.76ns 92.5±1.13ns -0.11%
crc32_resource_id_creation/compute_from_path:../test-assets/lena.jpg 65.1±0.35µs 65.2±0.92µs +0.15%
crc32_resource_id_creation/compute_from_path:../test-assets/test.pdf 973.8±5.49µs 975.8±4.46µs +0.21%
index_build/index_build/../test-assets/ 1043.5±6.44µs 1043.2±2.82µs -0.03%

Copy link
Collaborator Author

@twitu twitu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A minor nit related to feature flagging.

fs-storage/src/base_storage.rs Show resolved Hide resolved
fs-storage/src/base_storage.rs Outdated Show resolved Hide resolved
@@ -0,0 +1,11 @@
/// Represents the synchronization status of the storage.
public enum SyncStatus {
Copy link
Collaborator Author

@twitu twitu Jun 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's unfortunate that we cannot avoid duplicating the SyncStatus definition. I'd hoped the jnix_macro would create a class definition as part of the exported package.

Signed-off-by: pushkarm029 <[email protected]>
Copy link

Benchmark for 62c6a19

Click to view benchmark
Test Base PR %
blake3_resource_id_creation/compute_from_bytes:large 251.2±0.62µs 250.5±1.03µs -0.28%
blake3_resource_id_creation/compute_from_bytes:medium 15.6±0.06µs 15.6±0.06µs 0.00%
blake3_resource_id_creation/compute_from_bytes:small 1358.6±10.80ns 1353.1±8.90ns -0.40%
blake3_resource_id_creation/compute_from_path:../test-assets/lena.jpg 195.8±0.50µs 196.2±0.65µs +0.20%
blake3_resource_id_creation/compute_from_path:../test-assets/test.pdf 1737.2±6.84µs 1741.9±28.42µs +0.27%
crc32_resource_id_creation/compute_from_bytes:large 86.8±0.39µs 86.8±0.80µs 0.00%
crc32_resource_id_creation/compute_from_bytes:medium 5.4±0.15µs 5.4±0.03µs 0.00%
crc32_resource_id_creation/compute_from_bytes:small 93.0±2.59ns 92.7±0.29ns -0.32%
crc32_resource_id_creation/compute_from_path:../test-assets/lena.jpg 65.2±0.22µs 65.0±0.87µs -0.31%
crc32_resource_id_creation/compute_from_path:../test-assets/test.pdf 958.7±7.59µs 952.9±3.17µs -0.60%
index_build/index_build/../test-assets/ 1045.2±12.51µs 1051.6±10.38µs +0.61%

Copy link
Collaborator Author

@twitu twitu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MERGE! 🚀

Copy link
Collaborator

@tareknaser tareknaser left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have left some comments, but I think we should merge. These comments can be addressed in #75.

@@ -44,3 +44,15 @@ key2: value2
```bash
cargo run --example cli read /tmp/z
```

## Java Wrapper
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These commands should be run inside tests/


## Steps to test Java Wrapper
```bash
cd tests && make test
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no make test
it's os dependant

Comment on lines +6 to +12
test-linux: build-rust download-test-lib java-test-linux

.PHONY: test-mac
test-mac: build-rust download-test-lib java-test-mac

.PHONY: test-windows
test-windows: build-rust download-test-lib java-test-windows
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can detect the OS in the Makefile to have only one make test

For reference: https://gist.github.com/sighingnow/deee806603ec9274fd47
but there may be even an easier way

@@ -15,11 +15,16 @@ name = "cli"
log = { version = "0.4.17", features = ["release_max_level_off"] }
serde_json = "1.0.82"
serde = { version = "1.0.138", features = ["derive"] }

jni = { version = "0.21.1", optional = true }
jnix = { version = "0.5.1", features = ["derive"] }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess jnix should be optional as well

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also git ignore *.h files

```java
javac -h . FileStorage.java
javac FileStorage.java
LD_LIBRARY_PATH=<project-root-path>/target/debug && java FileStorage.java
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The project root path is always ../ if we run from fs-storage/

@@ -0,0 +1,11 @@
/// Represents the synchronization status of the storage.
public enum SyncStatus {
Copy link
Collaborator

@tareknaser tareknaser Jun 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should add a note in the rust code of SyncStatus that any change should be applied here as well


.PHONY: download-test-lib
download-test-lib:
cd tests && \
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
cd tests && \
@cd tests && \

So it doesn't print the command to the terminal each time

@Pushkarm029
Copy link
Collaborator

Thanks @tareknaser for the review, i completed all these suggestions in #76

@twitu twitu merged commit 8d12782 into main Jun 23, 2024
4 checks passed
@twitu twitu deleted the jni-bindings branch June 23, 2024 06:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants