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

Provide Persistance for Persistance.Reference #9326

Merged
merged 3 commits into from
Mar 8, 2024

Conversation

JaroslavTulach
Copy link
Member

@JaroslavTulach JaroslavTulach commented Mar 7, 2024

Pull Request Description

Provide default Persistance implementation for Persistance.Reference to allow us to persist fields of that type easily. The reference is used to load object lazily. When constructing the objects in memory one uses Reference.of(anObject), stores it in a field and after deserializing one gets an instance of the Reference back (but without the original object being deserialized). Later one calls ref.get(TypeOfTheObject.class) to deserialize also instance of the original object.

Checklist

Please ensure that the following checklist has been satisfied before submitting the PR:

  • All code follows the
    Java,
    style guides.
  • All code has been tested:
    • Unit tests have been written where possible.

@JaroslavTulach JaroslavTulach requested a review from radeusgd March 7, 2024 16:10
@JaroslavTulach JaroslavTulach self-assigned this Mar 7, 2024
@JaroslavTulach JaroslavTulach added CI: No changelog needed Do not require a changelog entry for this PR. CI: Clean build required CI runners will be cleaned before and after this PR is built. CI: Keep up to date Automatically update this PR to the latest develop. labels Mar 7, 2024
@JaroslavTulach JaroslavTulach removed the CI: Keep up to date Automatically update this PR to the latest develop. label Mar 8, 2024
@@ -470,4 +501,11 @@ public record ServiceSupply(Service supply) {}

@Persistable(clazz = IdHolder.class, id = 432876)
public record IdHolder(UUID id) {}

@Persistable(clazz = RefHolder.class, id = 436872)
public record RefHolder(Persistance.Reference<UUID> id) {
Copy link
Member Author

Choose a reason for hiding this comment

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

Have a class with field Persistance.Reference and write/generate Persistance instance for it. In this case we generate the class with @Persistable(clazz = RefHolder.class... annotation.

public void refHolderWithUUID() throws Exception {
var id = UUID.randomUUID();
var il = new RefHolder(id);
var in = serde(RefHolder.class, il, -1, null);
Copy link
Member Author

Choose a reason for hiding this comment

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

This stores an instance of RefHolder and reads another instace of RefHolder back from the array. Only then when one in.id().get(UUID.class) the instance of UUID gets deserialized.

@radeusgd
Copy link
Member

radeusgd commented Mar 8, 2024

As discussed, here's the repro for the problem with cycles in serialization that I'm encountering:

  • Check out the branch: https://github.com/enso-org/enso/tree/wip/radeusgd/cycle-in-serialization
    • I added there the mechanism for detecting the cycles (now it works, when we were chatting I had a missing case where the objects need to be registered). You can revert 47311b0 if you prefer to not have it.
  • Just running buildEngineDistribution triggers the issue.
  • Alternatively, I prefer to buildEngineDistributionNoIndex to build the artefacts, followed by manually running .\built-distribution\enso-engine-0.0.0-dev-windows-amd64\enso-0.0.0-dev\bin\enso --no-global-cache --no-compile-dependencies --compile .\built-distribution\enso-engine-0.0.0-dev-windows-amd64\enso-0.0.0-dev\lib\Standard\AWS\0.0.0-dev\ to trigger compilation of the AWS library (it's a small one so I figured out it will be easier for debugging, but any library incl. Base should work) - this way it is easier for me to attach the debugger.

image

After some digging and relying on the cycle detector, it our initial hypothesis (Name.Literal(Text, ...) being teh culprit) seems to be wrong and after all the object that is really causing the cycle seems to be

Cons(Operation,List(Argument(kind,false,Some(org.enso.persist.PerMemoryReference@2389e02f)), Argument(expressions,false,Some(org.enso.persist.PerMemoryReference@6db609e7)), Argument(metadata,true,Some(org.enso.persist.PerMemoryReference@7e5bfb5a))))

which is quite expected since it is indeed the Cons/Argument pair that I have been modifying - adding the third Option[Reference[Expression]] to it. Indeed removing the expression from there was fixing the issue.

Overall the cycle seems to be Cons -> Argument -> Expression (Application.Prefix) -> Name.Literal -> MetadataStorage(GlobalNames) -> BindingsMap.Resolution -> ResolvedType -> Type -> Cons

@radeusgd
Copy link
Member

radeusgd commented Mar 8, 2024

It seems that I've got a (partial) fix for the issue. It seems that writing is fixed by ensuring that the currently written object is registered before serializing it (so that once we encounter the cycle during serialization, we already see the backreference and avoid the infinite loop).

Seems to be taken care of by this patch:

diff --git a/lib/java/persistance/src/main/java/org/enso/persist/PerGenerator.java b/lib/java/persistance/src/main/java/org/enso/persist/PerGenerator.java
--- a/lib/java/persistance/src/main/java/org/enso/persist/PerGenerator.java	(revision c1fead2ffa276279c28447db7e17118cc92cb2ed)
+++ b/lib/java/persistance/src/main/java/org/enso/persist/PerGenerator.java	(revision 967cffa4b916e42f194e565f4e664fb7d293c1cd)
@@ -59,14 +59,15 @@
     java.lang.Object obj = writeReplace.apply(t);
     java.lang.Integer found = knownObjects.get(obj);
     if (found == null) {
+      found = this.position;
+      knownObjects.put(obj, found);
+
       org.enso.persist.Persistance<?> p = map.forType(obj.getClass());
       java.io.ByteArrayOutputStream os = new ByteArrayOutputStream();
       p.writeInline(obj, new ReferenceOutput(this, os));
-      found = this.position;
       byte[] arr = os.toByteArray();
       main.write(arr);
       this.position += arr.length;
-      knownObjects.put(obj, found);
     }
     return found;
   }
@@ -83,18 +84,18 @@
     }
     java.lang.Integer found = knownObjects.get(obj);
     if (found == null) {
+      found = position;
+      knownObjects.put(obj, found);
 
       var os = new ByteArrayOutputStream();
       var osData = new ReferenceOutput(this, os);
       p.writeInline(obj, osData);
-      found = position;
       if (os.size() == 0) {
         os.write(0);
       }
       byte[] arr = os.toByteArray();
       main.write(arr);
       position += arr.length;
-      knownObjects.put(obj, found);
       if (histogram != null) {
         histogram.register(obj.getClass(), arr.length);
       }

After this patch I was able to rebuild indices.

I'm slightly worried that there may be some issues when reading this back, since I'm getting errors like:

[info] Generating index for built-distribution\enso-engine-0.0.0-dev-windows-amd64\enso-0.0.0-dev\lib\Standard\AWS
[WARN] [2024-03-08T13:30:39+01:00] [enso.org.enso.interpreter.caches.Cache] `Standard.AWS` in built-distribution\enso-engine-0.0.0-dev-windows-amd64\enso-0.0.0-dev\lib\Standard\AWS\0.0.0-dev\.enso\cache\bindings\0.0.0-dev\Standard\AWS.bindings failed to load: No persistance for 1952542308
[info] Generating index for built-distribution\enso-engine-0.0.0-dev-windows-amd64\enso-0.0.0-dev\lib\Standard\Base
[info] Generating index for built-distribution\enso-engine-0.0.0-dev-windows-amd64\enso-0.0.0-dev\lib\Standard\Database
[WARN] [2024-03-08T13:30:56+01:00] [enso.org.enso.interpreter.caches.Cache] `Standard.Base` in X:\NBO\enso\built-distribution\enso-engine-0.0.0-dev-windows-amd64\enso-0.0.0-dev\lib\Standard\Base\0.0.0-dev\.enso\cache\bindings\0.0.0-dev\Standard\Base.bindings failed to load: No persistance for 279137

But I'm not 100% sure if this is it or just unrelated errors?

More problems after clean build:

[info] Generating index for built-distribution\enso-engine-0.0.0-dev-windows-amd64\enso-0.0.0-dev\lib\Standard\AWS
[info] Generating index for built-distribution\enso-engine-0.0.0-dev-windows-amd64\enso-0.0.0-dev\lib\Standard\Base
[WARN] [2024-03-08T13:37:34+01:00] [enso.org.enso.interpreter.caches.Cache] `Standard.Builtins.Main` in C:\Users\DELL\AppData\Local\enso\cache\ir\Standard\Builtins\0.0.0-dev\0.0.0-dev\Standard\Builtins\Main.ir failed to load: No persistance for 541301
[info] Generating index for built-distribution\enso-engine-0.0.0-dev-windows-amd64\enso-0.0.0-dev\lib\Standard\Database
[WARN] [2024-03-08T13:37:44+01:00] [enso.org.enso.interpreter.caches.Cache] `Standard.Builtins.Main` in C:\Users\DELL\AppData\Local\enso\cache\ir\Standard\Builtins\0.0.0-dev\0.0.0-dev\Standard\Builtins\Main.ir failed to load: No persistance for 541301
[WARN] [2024-03-08T13:37:45+01:00] [enso.org.enso.interpreter.caches.Cache] `Standard.Base` in X:\NBO\enso\built-distribution\enso-engine-0.0.0-dev-windows-amd64\enso-0.0.0-dev\lib\Standard\Base\0.0.0-dev\.enso\cache\bindings\0.0.0-dev\Standard\Base.bindings failed to load: No persistance for 279137
[info] Generating index for built-distribution\enso-engine-0.0.0-dev-windows-amd64\enso-0.0.0-dev\lib\Standard\Examples
[WARN] [2024-03-08T13:37:55+01:00] [enso.org.enso.interpreter.caches.Cache] `Standard.Builtins.Main` in C:\Users\DELL\AppData\Local\enso\cache\ir\Standard\Builtins\0.0.0-dev\0.0.0-dev\Standard\Builtins\Main.ir failed to load: No persistance for 541301
[info] Generating index for built-distribution\enso-engine-0.0.0-dev-windows-amd64\enso-0.0.0-dev\lib\Standard\Geo
[WARN] [2024-03-08T13:38:01+01:00] [enso.org.enso.interpreter.caches.Cache] `Standard.Builtins.Main` in C:\Users\DELL\AppData\Local\enso\cache\ir\Standard\Builtins\0.0.0-dev\0.0.0-dev\Standard\Builtins\Main.ir failed to load: No persistance for 541301
[info] Generating index for built-distribution\enso-engine-0.0.0-dev-windows-amd64\enso-0.0.0-dev\lib\Standard\Google_Api
[WARN] [2024-03-08T13:38:07+01:00] [enso.org.enso.interpreter.caches.Cache] `Standard.Builtins.Main` in C:\Users\DELL\AppData\Local\enso\cache\ir\Standard\Builtins\0.0.0-dev\0.0.0-dev\Standard\Builtins\Main.ir failed to load: No persistance for 541301
[info] Generating index for built-distribution\enso-engine-0.0.0-dev-windows-amd64\enso-0.0.0-dev\lib\Standard\Image
[WARN] [2024-03-08T13:38:13+01:00] [enso.org.enso.interpreter.caches.Cache] `Standard.Builtins.Main` in C:\Users\DELL\AppData\Local\enso\cache\ir\Standard\Builtins\0.0.0-dev\0.0.0-dev\Standard\Builtins\Main.ir failed to load: No persistance for 541301
[info] Generating index for built-distribution\enso-engine-0.0.0-dev-windows-amd64\enso-0.0.0-dev\lib\Standard\Searcher
[WARN] [2024-03-08T13:38:18+01:00] [enso.org.enso.interpreter.caches.Cache] `Standard.Builtins.Main` in C:\Users\DELL\AppData\Local\enso\cache\ir\Standard\Builtins\0.0.0-dev\0.0.0-dev\Standard\Builtins\Main.ir failed to load: No persistance for 541301
[info] Generating index for built-distribution\enso-engine-0.0.0-dev-windows-amd64\enso-0.0.0-dev\lib\Standard\Table
[WARN] [2024-03-08T13:38:23+01:00] [enso.org.enso.interpreter.caches.Cache] `Standard.Builtins.Main` in C:\Users\DELL\AppData\Local\enso\cache\ir\Standard\Builtins\0.0.0-dev\0.0.0-dev\Standard\Builtins\Main.ir failed to load: No persistance for 541301
[info] Generating index for built-distribution\enso-engine-0.0.0-dev-windows-amd64\enso-0.0.0-dev\lib\Standard\Test
[WARN] [2024-03-08T13:38:32+01:00] [enso.org.enso.interpreter.caches.Cache] `Standard.Builtins.Main` in C:\Users\DELL\AppData\Local\enso\cache\ir\Standard\Builtins\0.0.0-dev\0.0.0-dev\Standard\Builtins\Main.ir failed to load: No persistance for 541301
[info] Generating index for built-distribution\enso-engine-0.0.0-dev-windows-amd64\enso-0.0.0-dev\lib\Standard\Visualization
[WARN] [2024-03-08T13:38:39+01:00] [enso.org.enso.interpreter.caches.Cache] `Standard.Builtins.Main` in C:\Users\DELL\AppData\Local\enso\cache\ir\Standard\Builtins\0.0.0-dev\0.0.0-dev\Standard\Builtins\Main.ir failed to load: No persistance for 541301
[WARN] [2024-03-08T13:38:39+01:00] [enso.org.enso.interpreter.caches.Cache] `Standard.Table` in X:\NBO\enso\built-distribution\enso-engine-0.0.0-dev-windows-amd64\enso-0.0.0-dev\lib\Standard\Table\0.0.0-dev\.enso\cache\bindings\0.0.0-dev\Standard\Table.bindings failed to load: No persistance for 1634467845
[WARN] [2024-03-08T13:38:40+01:00] [enso.org.enso.interpreter.caches.Cache] `Standard.Database` in X:\NBO\enso\built-distribution\enso-engine-0.0.0-dev-windows-amd64\enso-0.0.0-dev\lib\Standard\Database\0.0.0-dev\.enso\cache\bindings\0.0.0-dev\Standard\Database.bindings failed to load: No persistance for 1953066862
[info] Engine package created at built-distribution\enso-engine-0.0.0-dev-windows-amd64\enso-0.0.0-dev

@JaroslavTulach
Copy link
Member Author

It seems that I've got a (partial) fix for the issue.

I have a feeling it fails a lot of IrPersistanceTests. I'll integrate this PR without further diffs. Please report another issue requesting ability to store cycles in the graph. Extending IrPersistanceTest or some other to demonstrate the problem would be welcomed. Not completely necessary, I guess I understand now where the problem is and how the fix should look like.

@JaroslavTulach JaroslavTulach merged commit 2330fdb into develop Mar 8, 2024
34 of 36 checks passed
@JaroslavTulach JaroslavTulach deleted the wip/jtulach/PersistanceReference branch March 8, 2024 17:23
@enso-bot
Copy link

enso-bot bot commented Mar 9, 2024

Jaroslav Tulach reports a new STANDUP for yesterday (2024-03-08):

Progress: - Persistance.Reference PR merged: #9326

Next Day: Back to work on Monday

@JaroslavTulach
Copy link
Member Author

Request to also support "cycles" in the graph is

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
-compiler CI: Clean build required CI runners will be cleaned before and after this PR is built. CI: No changelog needed Do not require a changelog entry for this PR.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants