Skip to content

Commit 1692cb0

Browse files
committed
always use the FileChannel
this is experimental, performance is obliterated for some reason
1 parent 5ef6d84 commit 1692cb0

File tree

12 files changed

+134
-89
lines changed

12 files changed

+134
-89
lines changed

plugin/src/main/java/fish/cichlidmc/cichlid_gradle/cache/task/impl/ClassTransformer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ private static void readTransformersFromMod(Path root, TransformerManager.Builde
108108

109109
private static void readTransformersFromTree(String namespace, Path root, TransformerManager.Builder builder) throws IOException {
110110
FileUtils.walkFiles(root, file -> {
111-
String relative = root.relativize(file).toString();
111+
String relative = FileUtils.safeRelativize(root, file);
112112
if (!relative.endsWith(".sushi"))
113113
return;
114114

plugin/src/main/java/fish/cichlidmc/cichlid_gradle/cache/task/impl/MergeTask.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import java.util.List;
1818
import java.util.Objects;
1919
import java.util.concurrent.CompletableFuture;
20+
import java.util.zip.ZipOutputStream;
2021

2122
public class MergeTask extends CacheTask {
2223
public MergeTask(CacheTaskEnvironment env) {
@@ -46,7 +47,10 @@ protected String run() throws IOException {
4647
.filter(Objects::nonNull)
4748
.toList();
4849

49-
JarMerger.merge(readySources, output);
50+
try (ZipOutputStream outputStream = new ZipOutputStream(file.newOutputStream())) {
51+
JarMerger.merge(readySources, outputStream);
52+
}
53+
5054
return readySources;
5155
}).orElseGet(List::of);
5256

plugin/src/main/java/fish/cichlidmc/cichlid_gradle/cache/task/impl/ReassembleBinaryTask.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import java.io.IOException;
1010
import java.nio.file.Files;
1111
import java.nio.file.Path;
12+
import java.util.zip.ZipOutputStream;
1213

1314
public final class ReassembleBinaryTask extends CacheTask {
1415
public ReassembleBinaryTask(CacheTaskEnvironment env) {
@@ -25,7 +26,11 @@ protected String run() throws IOException {
2526
FileUtils.assertExists(input);
2627
}
2728

28-
WorkFile.doIfEmpty(output, file -> JarProcessor.run(input, file.path, ClassTransformer.create(this.env)));
29+
WorkFile.doIfEmpty(output, file -> {
30+
try (ZipOutputStream outputStream = new ZipOutputStream(file.newOutputStream())) {
31+
JarProcessor.run(input, outputStream, ClassTransformer.create(this.env));
32+
}
33+
});
2934
return null;
3035
}
3136
}

plugin/src/main/java/fish/cichlidmc/cichlid_gradle/cache/task/impl/ReassembleSourcesTask.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import java.io.IOException;
1212
import java.nio.file.Files;
1313
import java.nio.file.Path;
14+
import java.util.zip.ZipOutputStream;
1415

1516
public final class ReassembleSourcesTask extends CacheTask {
1617
private boolean ranDecompile;
@@ -29,7 +30,11 @@ protected String run() throws IOException {
2930
FileUtils.assertExists(binary);
3031
}
3132

32-
WorkFile.doIfEmpty(output, file -> JarProcessor.run(binary, file.path, this::getDecompiled));
33+
WorkFile.doIfEmpty(output, file -> {
34+
try (ZipOutputStream outputStream = new ZipOutputStream(file.newOutputStream())) {
35+
JarProcessor.run(binary, outputStream, this::getDecompiled);
36+
}
37+
});
3338
return null;
3439
}
3540

plugin/src/main/java/fish/cichlidmc/cichlid_gradle/cache/task/processor/ClassEntry.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import fish.cichlidmc.cichlid_gradle.util.io.FileUtils;
44

55
import java.io.IOException;
6+
import java.io.OutputStream;
67
import java.nio.file.Files;
78
import java.nio.file.Path;
89

@@ -34,9 +35,8 @@ public ClassEntry withContent(byte[] bytes) {
3435
public interface Content {
3536
byte[] bytes() throws IOException;
3637

37-
default void write(Path output) throws IOException {
38-
FileUtils.ensureCreated(output);
39-
Files.write(output, this.bytes());
38+
default void write(OutputStream output) throws IOException {
39+
output.write(this.bytes());
4040
}
4141
}
4242

@@ -50,7 +50,7 @@ public byte[] bytes() throws IOException {
5050
}
5151

5252
@Override
53-
public void write(Path output) throws IOException {
53+
public void write(OutputStream output) throws IOException {
5454
FileUtils.copy(this.path, output);
5555
}
5656
}

plugin/src/main/java/fish/cichlidmc/cichlid_gradle/cache/task/processor/JarProcessor.java

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,42 +14,41 @@
1414
import java.util.HashSet;
1515
import java.util.Map;
1616
import java.util.Objects;
17+
import java.util.zip.ZipEntry;
18+
import java.util.zip.ZipOutputStream;
1719

1820
/**
1921
* Applies a function to every class within a jar file, and places the results in a new output jar.
2022
* Non-classes are copied as-is.
2123
*/
2224
public final class JarProcessor {
2325
// 🮲🮳
24-
public static void run(Path inputJar, Path outputJar, ClassProcessor function) throws IOException {
25-
FileUtils.initEmptyZip(outputJar);
26-
27-
try (FileSystem inputFs = FileSystems.newFileSystem(inputJar); FileSystem outputFs = FileSystems.newFileSystem(outputJar)) {
26+
public static void run(Path inputJar, ZipOutputStream output, ClassProcessor function) throws IOException {
27+
try (FileSystem inputFs = FileSystems.newFileSystem(inputJar)) {
2828
// jars should have 1 root
2929
Path inputRoot = FileUtils.getSingleRoot(inputFs);
30-
Path outputRoot = FileUtils.getSingleRoot(outputFs);
3130

3231
Input input = collectInput(inputRoot);
3332
for (ClassGroup group : input.groups.values()) {
3433
ClassGroup processed = function.apply(group);
3534

36-
addEntry(outputRoot, processed.main());
35+
addEntry(output, processed.main());
3736
for (ClassEntry inner : processed.inner()) {
38-
addEntry(outputRoot, inner);
37+
addEntry(output, inner);
3938
}
4039
}
4140

4241
for (Path nonClass : input.nonClasses) {
43-
Path relative = inputRoot.relativize(nonClass);
44-
Path target = outputRoot.resolve(relative);
45-
FileUtils.copy(nonClass, target);
42+
String relative = FileUtils.safeRelativize(inputRoot, nonClass);
43+
output.putNextEntry(new ZipEntry(relative));
44+
FileUtils.copy(nonClass, output);
4645
}
4746
}
4847
}
4948

50-
private static void addEntry(Path outputRoot, ClassEntry entry) throws IOException {
51-
Path target = outputRoot.resolve(entry.fileName());
52-
entry.content().write(target);
49+
private static void addEntry(ZipOutputStream output, ClassEntry entry) throws IOException {
50+
output.putNextEntry(new ZipEntry(entry.fileName()));
51+
entry.content().write(output);
5352
}
5453

5554
public static Input collectInput(Path inputRoot) throws IOException {
@@ -58,7 +57,7 @@ public static Input collectInput(Path inputRoot) throws IOException {
5857

5958
FileUtils.walkFiles(inputRoot, entry -> {
6059
// net/minecraft/ClassName$Inner.(class/java)
61-
String name = inputRoot.relativize(entry).toString();
60+
String name = FileUtils.safeRelativize(inputRoot, entry);
6261

6362
if (!name.endsWith(".java") && !name.endsWith(".class")) {
6463
nonClasses.add(entry);

plugin/src/main/java/fish/cichlidmc/cichlid_gradle/merge/ClassMerger.java

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,29 @@
33
import fish.cichlidmc.cichlid_gradle.merge.element.FieldMerger;
44
import fish.cichlidmc.cichlid_gradle.merge.element.InterfacesMerger;
55
import fish.cichlidmc.cichlid_gradle.merge.element.MethodMerger;
6-
import fish.cichlidmc.cichlid_gradle.util.io.FileUtils;
76
import fish.cichlidmc.distmarker.Dist;
87
import fish.cichlidmc.distmarker.Distribution;
9-
import org.objectweb.asm.*;
8+
import org.objectweb.asm.ClassReader;
9+
import org.objectweb.asm.ClassWriter;
10+
import org.objectweb.asm.Type;
1011
import org.objectweb.asm.tree.AnnotationNode;
1112
import org.objectweb.asm.tree.ClassNode;
1213

1314
import java.io.IOException;
15+
import java.io.OutputStream;
1416
import java.nio.file.Files;
1517
import java.nio.file.Path;
16-
import java.util.*;
18+
import java.util.ArrayList;
19+
import java.util.Arrays;
20+
import java.util.HashMap;
21+
import java.util.List;
22+
import java.util.Map;
1723

1824
public class ClassMerger {
1925
private static final FieldMerger fieldMerger = new FieldMerger();
2026
private static final MethodMerger methodMerger = new MethodMerger();
2127

22-
public static void mergeClass(Map<MergeSource, Path> sources, Path dest) throws IOException {
28+
public static void mergeClass(Map<MergeSource, Path> sources, OutputStream output) throws IOException {
2329
// merge fields, methods, and constructors
2430
Map<MergeSource, ClassNode> classes = new HashMap<>();
2531
for (Map.Entry<MergeSource, Path> entry : sources.entrySet()) {
@@ -39,7 +45,7 @@ public static void mergeClass(Map<MergeSource, Path> sources, Path dest) throws
3945
methodMerger.merge(classes, mergedNode);
4046
InterfacesMerger.merge(classes, mergedNode);
4147

42-
writeClass(mergedNode, dest);
48+
writeClass(mergedNode, output);
4349
}
4450

4551
private static void assertCommonAttributesMatch(Map<MergeSource, ClassNode> classes) {
@@ -66,12 +72,12 @@ private static byte[] toCommonBytes(ClassNode node) {
6672
return writer.toByteArray();
6773
}
6874

69-
public static void copyExclusiveClass(Path path, Path dest, Dist dist) throws IOException {
75+
public static void copyExclusiveClass(Path path, OutputStream output, Dist dist) throws IOException {
7076
ClassNode node = readClass(path);
7177
if (node.visibleAnnotations == null)
7278
node.visibleAnnotations = new ArrayList<>();
7379
node.visibleAnnotations.add(makeDistAnnotation(dist));
74-
writeClass(node, dest);
80+
writeClass(node, output);
7581
}
7682

7783
private static ClassNode readClass(Path path) throws IOException {
@@ -81,12 +87,11 @@ private static ClassNode readClass(Path path) throws IOException {
8187
return node;
8288
}
8389

84-
private static void writeClass(ClassNode node, Path path) throws IOException {
90+
private static void writeClass(ClassNode node, OutputStream output) throws IOException {
8591
ClassWriter writer = new ClassWriter(0);
8692
node.accept(writer);
8793
byte[] bytes = writer.toByteArray();
88-
FileUtils.ensureCreated(path);
89-
Files.write(path, bytes);
94+
output.write(bytes);
9095
}
9196

9297
public static AnnotationNode makeDistAnnotation(Dist dist) {

plugin/src/main/java/fish/cichlidmc/cichlid_gradle/merge/JarMerger.java

Lines changed: 40 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@
44
import fish.cichlidmc.distmarker.Dist;
55

66
import java.io.IOException;
7-
import java.nio.file.FileSystem;
8-
import java.nio.file.FileSystems;
7+
import java.io.OutputStream;
98
import java.nio.file.Files;
109
import java.nio.file.Path;
1110
import java.util.Arrays;
@@ -17,68 +16,66 @@
1716
import java.util.Set;
1817
import java.util.function.BiPredicate;
1918
import java.util.function.Function;
19+
import java.util.zip.ZipEntry;
20+
import java.util.zip.ZipOutputStream;
2021

2122
public class JarMerger {
22-
public static void merge(List<MergeSource> sources, Path output) throws IOException {
23-
FileUtils.initEmptyZip(output);
24-
25-
try (FileSystem merged = FileSystems.newFileSystem(output)) {
26-
Set<String> entries = new HashSet<>();
27-
for (MergeSource mergeSource : sources) {
28-
mergeSource.listEntries(entries);
29-
}
23+
public static void merge(List<MergeSource> sources, ZipOutputStream output) throws IOException {
24+
Set<String> entries = new HashSet<>();
25+
for (MergeSource mergeSource : sources) {
26+
mergeSource.listEntries(entries);
27+
}
3028

31-
for (String entry : entries) {
32-
Path dest = merged.getPath(entry);
29+
for (String entry : entries) {
30+
output.putNextEntry(new ZipEntry(entry));
3331

34-
Map<MergeSource, Path> paths = new HashMap<>();
35-
for (MergeSource source : sources) {
36-
Path path = source.getEntry(entry);
37-
if (Files.exists(path)) {
38-
paths.put(source, path);
39-
}
32+
Map<MergeSource, Path> paths = new HashMap<>();
33+
for (MergeSource source : sources) {
34+
Path path = source.getEntry(entry);
35+
if (Files.exists(path)) {
36+
paths.put(source, path);
4037
}
38+
}
4139

42-
if (paths.isEmpty()) {
43-
throw new IllegalStateException("No paths exist for " + entry);
44-
} else if (paths.size() == 1) {
45-
// exclusive
46-
Map.Entry<MergeSource, Path> mapEntry = paths.entrySet().iterator().next();
47-
Path source = mapEntry.getValue();
48-
Dist dist = mapEntry.getKey().dist;
49-
copyExclusiveEntry(source, dest, dist);
50-
} else {
51-
// present in >1 source
52-
// check for case where not exclusive, but not present everywhere
53-
// this is not representable currently
54-
int missing = sources.size() - paths.size();
55-
if (missing >= 2) {
56-
throw new IllegalStateException("Entry is both non-exclusive and missing from some sources: " + entry);
57-
}
58-
mergeEntry(paths, dest);
40+
if (paths.isEmpty()) {
41+
throw new IllegalStateException("No paths exist for " + entry);
42+
} else if (paths.size() == 1) {
43+
// exclusive
44+
Map.Entry<MergeSource, Path> mapEntry = paths.entrySet().iterator().next();
45+
Path source = mapEntry.getValue();
46+
Dist dist = mapEntry.getKey().dist;
47+
copyExclusiveEntry(source, output, dist);
48+
} else {
49+
// present in >1 source
50+
// check for case where not exclusive, but not present everywhere
51+
// this is not representable currently
52+
int missing = sources.size() - paths.size();
53+
if (missing >= 2) {
54+
throw new IllegalStateException("Entry is both non-exclusive and missing from some sources: " + entry);
5955
}
56+
mergeEntry(paths, entry, output);
6057
}
6158
}
6259
}
6360

64-
private static void copyExclusiveEntry(Path path, Path dest, Dist dist) throws IOException {
61+
private static void copyExclusiveEntry(Path path, OutputStream output, Dist dist) throws IOException {
6562
if (path.toString().endsWith(".class")) {
66-
ClassMerger.copyExclusiveClass(path, dest, dist);
63+
ClassMerger.copyExclusiveClass(path, output, dist);
6764
} else {
68-
FileUtils.copy(path, dest);
65+
FileUtils.copy(path, output);
6966
}
7067
}
7168

72-
private static void mergeEntry(Map<MergeSource, Path> sources, Path dest) throws IOException {
69+
private static void mergeEntry(Map<MergeSource, Path> sources, String entry, OutputStream output) throws IOException {
7370
if (allEqualContent(sources.values())) {
7471
// when file content is the same across all sources, just copy one over
7572
Path source = sources.values().iterator().next();
76-
FileUtils.copy(source, dest);
77-
} else if (dest.toString().endsWith(".class")) {
78-
ClassMerger.mergeClass(sources, dest);
73+
FileUtils.copy(source, output);
74+
} else if (entry.endsWith(".class")) {
75+
ClassMerger.mergeClass(sources, output);
7976
} else {
8077
// uh oh
81-
throw new IllegalStateException("Entry has conflicting content between sources: " + dest);
78+
throw new IllegalStateException("Entry has conflicting content between sources: " + entry);
8279
}
8380
}
8481

0 commit comments

Comments
 (0)