Skip to content

for graalvm native-image: graph.Type needs to implement java.lang.Comparable #48

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

Closed
wants to merge 1 commit into from
Closed

for graalvm native-image: graph.Type needs to implement java.lang.Comparable #48

wants to merge 1 commit into from

Conversation

josh-7t
Copy link

@josh-7t josh-7t commented Sep 16, 2021

After compiling aleph with graal native-image calling manifold.stream.SplicedStream.put appears to pass a byte_stream.graph.Type to byte_streams.utils$fast_memoize

The following stck trace suggests that in the graal environment fast-memoize needs it's arguments to implement java.lang.Coparable interface:

[main] ERROR aleph.netty - cannot coerce clojure.lang.LazySeq into binary representation
java.lang.ClassCastException: byte_streams.graph.Type cannot be cast to java.lang.Comparable
	at clojure.lang.Util.compare(Util.java:153)
	at clojure.lang.APersistentVector.compareTo(APersistentVector.java:439)
	at java.util.concurrent.ConcurrentHashMap.compareComparables(ConcurrentHashMap.java:739)
	at java.util.concurrent.ConcurrentHashMap$TreeBin.<init>(ConcurrentHashMap.java:2819)
	at java.util.concurrent.ConcurrentHashMap.treeifyBin(ConcurrentHashMap.java:2676)
	at java.util.concurrent.ConcurrentHashMap.putVal(ConcurrentHashMap.java:1068)
	at java.util.concurrent.ConcurrentHashMap.putIfAbsent(ConcurrentHashMap.java:1541)
	at byte_streams.utils$fast_memoize$fn__3336.invoke(utils.clj:56)
	at byte_streams.graph$seq_conversion_fn$fn__3709.invoke(graph.clj:293)
	at clojure.core$map$fn__5884.invoke(core.clj:2759)
	at clojure.lang.LazySeq.sval(LazySeq.java:42)
	at clojure.lang.LazySeq.seq(LazySeq.java:51)
	at clojure.lang.RT.seq(RT.java:535)
	at clojure.core$seq__5419.invokeStatic(core.clj:139)
	at clojure.core$filter$fn__5911.invoke(core.clj:2813)
	at clojure.lang.LazySeq.sval(LazySeq.java:42)
	at clojure.lang.LazySeq.seq(LazySeq.java:51)
	at clojure.lang.Cons.next(Cons.java:39)
	at clojure.lang.RT.length(RT.java:1785)
	at clojure.lang.RT.seqToArray(RT.java:1726)
	at clojure.lang.LazySeq.toArray(LazySeq.java:132)
	at clojure.lang.RT.toArray(RT.java:1699)
	at clojure.core$to_array.invokeStatic(core.clj:346)
	at clojure.core$sort.invokeStatic(core.clj:3101)
	at clojure.core$sort_by.invokeStatic(core.clj:3107)
	at clojure.core$sort_by.invokeStatic(core.clj:3107)
	at byte_streams.graph$seq_conversion_fn.invokeStatic(graph.clj:291)
	at byte_streams$fn__4114.invokeStatic(byte_streams.clj:148)
	at byte_streams$fn__4114.invoke(byte_streams.clj:148)
	at byte_streams.utils$fast_memoize$fn__3336$fn__3339.invoke(utils.clj:52)
	at clojure.lang.Delay.deref(Delay.java:42)
	at clojure.core$deref.invokeStatic(core.clj:2324)
	at byte_streams.utils$fast_memoize$fn__3336.invoke(utils.clj:52)
	at byte_streams$convert.invokeStatic(byte_streams.clj:199)
	at byte_streams$convert.invoke(byte_streams.clj:162)
	at byte_streams$convert.invokeStatic(byte_streams.clj:177)
	at aleph.netty$fn__4597$to_byte_buf__4600.invoke(netty.clj:176)
	at aleph.netty.ChannelSink$fn__4632.invoke(netty.clj:382)
	at aleph.netty.ChannelSink.put(netty.clj:381)
	at manifold.stream.SplicedStream.put(stream.clj:403)
	at manifold.stream.graph$async_send.invokeStatic(graph.clj:81)
	at manifold.stream.graph$async_connect$this__2478.invoke(graph.clj:209)
	at manifold.stream.graph$async_connect$this__2478$fn__2479$fn__2480.invoke(graph.clj:191)
	at clojure.core$trampoline.invokeStatic(core.clj:6299)
	at manifold.stream.graph$async_connect$this__2478$fn__2479.invoke(graph.clj:191)
	at manifold.deferred.Listener.onSuccess(deferred.clj:219)
	at manifold.deferred.Deferred$fn__1948.invoke(deferred.clj:400)
	at manifold.deferred.Deferred.success(deferred.clj:400)
	at manifold.deferred$success_BANG_.invokeStatic(deferred.clj:245)
	at manifold.stream.default.Stream$fn__2578.invoke(default.clj:158)
	at manifold.stream.default.Stream.put(default.clj:144)
	at manifold.stream.default.Stream.put(default.clj:180)
	at manifold.stream$map$fn__3044.invoke(stream.clj:620)
	at manifold.stream.Callback.put(stream.clj:454)
	at manifold.stream.graph$async_send.invokeStatic(graph.clj:81)
	at manifold.stream.graph$async_connect$this__2478.invoke(graph.clj:209)
	at manifold.stream.graph$async_connect$this__2478$fn__2479$fn__2480.invoke(graph.clj:191)
	at clojure.core$trampoline.invokeStatic(core.clj:6299)
	at manifold.stream.graph$async_connect$this__2478$fn__2479.invoke(graph.clj:191)
	at manifold.deferred.Listener.onSuccess(deferred.clj:219)
	at manifold.deferred.Deferred$fn__1948.invoke(deferred.clj:400)
	at manifold.deferred.Deferred.success(deferred.clj:400)
	at manifold.deferred$success_BANG_.invokeStatic(deferred.clj:245)
	at manifold.stream.default.Stream$fn__2578.invoke(default.clj:158)
	at manifold.stream.default.Stream.put(default.clj:144)
	at manifold.stream.default.Stream.put(default.clj:180)
	at manifold.stream.SplicedStream.put(stream.clj:403)
	at servo.connection$send.invokeStatic(connection.clj:276)
	at servo.connection$send.invoke(connection.clj:273)
	at servo.connection$run.invokeStatic(connection.clj:148)
	at servo.connection$run.doInvoke(connection.clj:140)
	at clojure.lang.RestFn.invoke(RestFn.java:425)
	at servo.connection$ensure_db.invokeStatic(connection.clj:549)
	at servo.connection$ensure_db.invoke(connection.clj:547)
	at servo.connection$connect.invokeStatic(connection.clj:107)
	at scribe.main$_main$fn__7808.invoke(main.clj:16)
	at scribe.main$_main.invokeStatic(main.clj:16)
	at scribe.main$_main.doInvoke(main.clj:9)
	at clojure.lang.RestFn.invoke(RestFn.java:410)
	at clojure.lang.AFn.applyToHelper(AFn.java:154)
	at clojure.lang.RestFn.applyTo(RestFn.java:132)
	at scribe.main.main(Unknown Source)

@josh-7t josh-7t requested a review from slipset as a code owner September 16, 2021 14:18
@josh-7t josh-7t changed the title graph.Type implements java.lang.Coparable for graalvm native-image: graph.Type needs to implement java.lang.Coparable Sep 17, 2021
@josh-7t josh-7t changed the title for graalvm native-image: graph.Type needs to implement java.lang.Coparable for graalvm native-image: graph.Type needs to implement java.lang.Comparable Sep 17, 2021
@KingMob
Copy link
Collaborator

KingMob commented Sep 24, 2021

@josh-7t Thanks for submitting this PR to improve byte-streams. I appreciate the effort and the interest.

However, there's two issues, one big and one small.

The small issue is the fn as written violates the Comparable contract. If the objects compared aren't equal, it will always return -1, which would mean the objects are always before each other, which is impossible. This is at least fixable by picking an artificial ordering based on type and wrapper. There's no inherent ordering of Types, but as long as it's consistent for TreeBin, it might be ok.

The bigger issue is the ConcurrentHashMap behind fast-memoize is using reflection, which is not exactly friendly to GraalVM. In addition to Java code, Zach's code wasn't shy about doing stuff like this either, so even if we change this here, you're likely to run into it again elsewhere. I suspect supporting Graal is a much bigger endeavor than a few PRs will solve.

That being said, I'm not convinced fast-memoize is worth it over plain memoize, if it's causing issues. If you want to replace it, I'd support that. We'd need a performance comparison between the two. As long as it's not egregious, they should be swappable.

@KingMob KingMob self-requested a review September 25, 2021 16:44
@josh-7t
Copy link
Author

josh-7t commented Sep 28, 2021

Thanks for responding! I think I would be interested in replacing fast-memoize since Implementing Comparable on this type seems very arbitrary.
Would you be amenable to me using https://github.com/clojure/core.memoize instead of the default memoize? It seems like it's implemented to work better for multithreaded apps and it has different cache strategies available so that the cache doesn't just grow forever.

@josh-7t
Copy link
Author

josh-7t commented Oct 5, 2021

superseded by #50

@josh-7t josh-7t closed this Oct 5, 2021
@josh-7t josh-7t deleted the f/implement-Comparable branch October 26, 2021 17:58
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.

2 participants