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

3% speedup with LazyMap and MetadataStorage #8359

Merged
merged 18 commits into from
Nov 27, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
cd5e645
Make java.util.Map lazy. Try to make immutable Scala map lazy.
JaroslavTulach Nov 21, 2023
d7f9af5
Attempt to create immutable map delegate
JaroslavTulach Nov 22, 2023
f9c34a9
Fix the proxy map to be immutable and lazy
hubertp Nov 22, 2023
f428331
Hexadecimal version looks more professional
JaroslavTulach Nov 23, 2023
3ca2d66
Support serialization of singletons
JaroslavTulach Nov 23, 2023
af04b8e
Generate @Override annotation
JaroslavTulach Nov 23, 2023
228a03f
Read MetadataStorage lazily
JaroslavTulach Nov 23, 2023
cac8910
Enough to use constructor
JaroslavTulach Nov 23, 2023
b8d5efd
Drop caches and reparse when deserialization of BindingsMap yields an…
JaroslavTulach Nov 23, 2023
d8148c1
Avoid deprecated method
JaroslavTulach Nov 23, 2023
cd6c0c6
Let getBindingsMap() recover from cache loading errors
JaroslavTulach Nov 23, 2023
826dcee
SerializerTest needs FullyQualifiedNames serialization
JaroslavTulach Nov 23, 2023
ca5c256
Reverting cd6c0c6e4689c374aecacda52e329ce0557a0e51 as it causes failu…
JaroslavTulach Nov 23, 2023
8bd6adc
More robust ImportResolver
JaroslavTulach Nov 24, 2023
68e057f
Display error when the execution isn't Success
JaroslavTulach Nov 24, 2023
1b3db21
Merge remote-tracking branch 'origin/develop' into wip/jtulach/Benchm…
JaroslavTulach Nov 25, 2023
44b37c7
Benchmark on files that are already prepared in the repository
JaroslavTulach Nov 25, 2023
868793a
Merge remote-tracking branch 'origin/wip/jtulach/BenchmarkStartup_832…
JaroslavTulach Nov 25, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package org.enso.compiler.core.ir;

import java.io.IOException;
import java.util.AbstractMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import org.enso.persist.Persistance;
import org.enso.persist.Persistance.Reference;


final class IrLazyMap<K, V> extends AbstractMap<K, V> {
private final Map<K, Entry<K, V>> delegate;

@SuppressWarnings("unchecked")
IrLazyMap(Persistance.Input in) throws IOException {
var map = new LinkedHashMap<K, Entry<K, V>>();
var n = in.readInt();
for (var i = 0; i < n; i++) {
var key = (K) in.readObject();
var ref = (Reference<V>) in.readReference(Object.class);
var en = new En<>(key, ref);
map.put(key, en);
}
this.delegate = map;
}

@Override
public Set<Entry<K, V>> entrySet() {
return new LinkedHashSet<>(this.delegate.values());
}

@Override
public V get(Object key) {
var entry = this.delegate.get(key);
return entry == null ? null : entry.getValue();
}

private static final class En<K, V> implements Entry<K, V> {
private final K key;
private final Reference<V> ref;

En(K key, Reference<V> ref) {
this.key = key;
this.ref = ref;
}

@Override
public K getKey() {
return key;
}

@Override
@SuppressWarnings("unchecked")
public V getValue() {
return (V) ref.get(Object.class);
}

@Override
public V setValue(V value) {
throw new UnsupportedOperationException();
}

@Override
public int hashCode() {
int hash = 7;
hash = 29 * hash + Objects.hashCode(this.key);
return hash;
}

@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof En<?, ?> other) {
return Objects.equals(this.key, other.key);
}
return false;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package org.enso.compiler.core.ir;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import org.enso.compiler.core.ir.expression.Application;
Expand Down Expand Up @@ -230,14 +229,9 @@ protected void writeObject(scala.collection.immutable.Map map, Output out) throw
@SuppressWarnings("unchecked")
protected scala.collection.immutable.Map readObject(Input in)
throws IOException, ClassNotFoundException {
var size = in.readInt();
var map = scala.collection.immutable.Map$.MODULE$.empty();
for (var i = 0; i < size; i++) {
var key = in.readObject();
var value = in.readObject();
map = map.$plus(new Tuple2(key, value));
}
return map;
var map = new IrLazyMap(in);
var immutableMap = IrLazyImMap$.MODULE$.apply(map);
return immutableMap;
}
}

Expand Down Expand Up @@ -309,13 +303,13 @@ protected scala.collection.immutable.Set readObject(Input in)
}

@ServiceProvider(service = Persistance.class)
public static final class PersistMap extends Persistance<HashMap> {
public static final class PersistMap extends Persistance<Map> {
public PersistMap() {
super(HashMap.class, true, 4440);
super(Map.class, true, 4440);
}

@Override
protected void writeObject(HashMap m, Output out) throws IOException {
protected void writeObject(Map m, Output out) throws IOException {
var size = m.size();
out.writeInt(size);
var it = m.entrySet().iterator();
Expand All @@ -328,15 +322,8 @@ protected void writeObject(HashMap m, Output out) throws IOException {

@Override
@SuppressWarnings("unchecked")
protected HashMap readObject(Input in) throws IOException, ClassNotFoundException {
var size = in.readInt();
var map = new HashMap<Object, Object>();
for (var i = 0; i < size; i++) {
var key = in.readObject();
var value = in.readObject();
map.put(key, value);
}
return map;
protected Map readObject(Input in) throws IOException, ClassNotFoundException {
return new IrLazyMap(in);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package org.enso.compiler.core.ir

import scala.collection.immutable.StrictOptimizedMapOps
import scala.collection.immutable.Map
import scala.collection.Iterator

final private class IrLazyImMap[K, V](
val underlying: java.util.Map[K, V]
JaroslavTulach marked this conversation as resolved.
Show resolved Hide resolved
) extends Map[K, V]
with StrictOptimizedMapOps[K, V, Map, Map[K, V]] {
def removed(key: K) =
new scala.jdk.CollectionConverters.MapHasAsScala(underlying).asScala.toMap
.removed(key)

def updated[V1 >: V](key: K, value: V1) =
new scala.jdk.CollectionConverters.MapHasAsScala(underlying).asScala.toMap
.updated(key, value)

def get(key: K) = Option(underlying.get(key))

def iterator = new Iterator[(K, V)]() {
val keys = underlying.entrySet().iterator()
def hasNext: Boolean = keys.hasNext()
def next(): (K, V) = {
val entry = keys.next()
(entry.getKey, entry.getValue)
}
}

override def size = underlying.size

// Has to override the `contains` method because the underlying implementation
// calls `get(key)`
override def contains(key: K): Boolean = {
underlying.containsKey(key)
}

}

object IrLazyImMap {
def apply[K, V](map: java.util.Map[K, V]): Map[K, V] =
new IrLazyImMap[K, V](map)
JaroslavTulach marked this conversation as resolved.
Show resolved Hide resolved
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import org.enso.compiler.core.ir.Module;
import org.enso.persist.Persistable;
import org.enso.persist.Persistance;
import org.junit.Before;
import org.junit.Test;
import org.openide.util.lookup.ServiceProvider;

Expand All @@ -25,6 +26,11 @@
import scala.collection.immutable.Seq;

public class IrPersistanceTest {
@Before
public void resetDebris() {
LazySeq.forbidden = false;
}

@Test
public void locationTest() throws Exception {
var l = new Location(12, 33);
Expand Down Expand Up @@ -61,6 +67,30 @@ public void scalaMap() throws Exception {
assertEquals(in, out);
}

@Test
@SuppressWarnings("unchecked")
public void scalaImmutableMapIsLazy() throws Exception {
var s1 = new LazySeq("Hello");
var s2 = new LazySeq("World");
var in = (scala.collection.immutable.Map) scala.collection.immutable.Map$.MODULE$.empty()
.$plus(new Tuple2("Hello", s1))
.$plus(new Tuple2("World", s2));

LazySeq.forbidden = true;
var out = (scala.collection.immutable.Map)
serde(scala.collection.immutable.Map.class, in, 64);
JaroslavTulach marked this conversation as resolved.
Show resolved Hide resolved

assertEquals("Two pairs element", 2, out.size());
assertEquals("Two keys", 2, out.keySet().size());
assertTrue(out.keySet().contains("Hello"));
assertTrue(out.keySet().contains("World"));
LazySeq.forbidden = false;

assertEquals(s1, out.get("Hello").get());
assertEquals(s2, out.get("World").get());
assertEquals(in, out);
}

@Test
@SuppressWarnings("unchecked")
public void scalaHashMap() throws Exception {
Expand Down Expand Up @@ -184,11 +214,34 @@ public void hashMap() throws Exception {
map.put("two", "duo");
map.put("ten", "tre");

var out = serde(HashMap.class, map, -1);
var out = serde(java.util.Map.class, map, -1);

assertEquals("Same", map, out);
}

@Test
@SuppressWarnings("unchecked")
public void hashMapIsLazy() throws Exception {
var s1 = new LazySeq("Hello");
var s2 = new LazySeq("World");
var in = new HashMap<String, LazySeq>();
in.put("Hello", s1);
in.put("World", s2);

LazySeq.forbidden = true;
var out = serde(java.util.Map.class, in, 64);

assertEquals("Two pairs element", 2, out.size());
assertEquals("Two keys", 2, out.keySet().size());
assertTrue(out.keySet().contains("Hello"));
assertTrue(out.keySet().contains("World"));
LazySeq.forbidden = false;

assertEquals(s1, out.get("Hello"));
assertEquals(s2, out.get("World"));
assertEquals(in, out);
}

@Test
public void readResolve() throws Exception {
var in = new Service(5);
Expand Down
Loading