On Sun, 12 Mar 2023 14:12:08 GMT, Lance Andersen <lan...@openjdk.org> wrote:
>> Eirik Bjorsnos has updated the pull request incrementally with one >> additional commit since the last revision: >> >> Use Integer.toString instead of Long.toString > >> Here's a wild idea: >> >> We could inject large extra fields on the CEN entries to inflate the size of >> each CEN entry. This means we get away with much fewer CEN entries which >> again means much less memory. Also, writing mostly empty extra data seems to >> be really fast, at least on my Macbook Pro. >> >> For me, the test now run without the `@requires' and completes in less than >> 5 seconds. >> >> The cost is slightly more complicated code. But perhaps still worth the >> added complexity? >> >> ```java >> @BeforeTest >> public void setup() throws IOException { >> hugeZipFile = new File("cen-too-large.zip"); >> hugeZipFile.deleteOnExit(); >> >> // Length of generated entry names >> int nameLength = 10; >> >> // We use a large extra field to get away with fewer CEN headers >> byte[] extra = makeLargeExtra(); >> >> // The size of a single CEN header, including name and extra field >> int cenHeaderSize = ZipFile.CENHDR + nameLength + extra.length; >> >> // Determine the number of entries needed to exceed the MAX_CEN_SIZE >> int numEntries = (MAX_CEN_SIZE / cenHeaderSize) + 1; >> >> ZipEntry[] entries = new ZipEntry[numEntries]; >> try (ZipOutputStream zip = new ZipOutputStream(new >> BufferedOutputStream(new FileOutputStream(hugeZipFile)))) { >> // Creating the LocalDataTime once allows faster processing >> LocalDateTime time = LocalDateTime.now(); >> // Add entries until MAX_CEN_SIZE is reached >> for (int i = 0; i < numEntries; i++) { >> String name = Integer.toString(i); >> name = "0".repeat(nameLength -name.length()) + name; >> ZipEntry entry = entries[i] = new ZipEntry(name); >> // Use STORED for faster processing >> entry.setMethod(ZipEntry.STORED); >> entry.setSize(0); >> entry.setCrc(0); >> entry.setTimeLocal(time); >> zip.putNextEntry(entry); >> } >> zip.closeEntry(); >> for (ZipEntry entry : entries) { >> entry.setExtra(extra); >> } >> } >> } >> >> /** >> * Make an extra field with an 'unknown' tag and the maximum possible data >> size >> * @return >> */ >> private static byte[] makeLargeExtra() { >> byte[] extra = new byte[Short.MAX_VALUE]; >> ByteBuffer buffer = >> ByteBuffer.wrap(extra).order(ByteOrder.LITTLE_ENDIAN); >> buffer.putShort((short) 0x9902); // 'unknown' tag >> buffer.putShort((short) (extra.length - 2 * Short.BYTES)); // Data size >> return e... This PR was reviewed by @LanceAndersen and @Martin-Buchholz back in May, but unfortunately did not get integrated before it was closed for inactivity. I'm reopening it now, with a few changes after the last reviews: - To save disk space required by the test, a SparseOutputStream writes 'holes' until it detects that the last CEN is written, after which it starts writing actual bytes for the END header. This reduces the required disk space from ~2GB to ~4K. - Since the test no longer requires excessive memory or disk space, the 'manual' tag is removed and the test is removed from the `jdk_core_manual_no_input` group in `TEST.groups` With a blessing of these last changes on top of what's already reviewed, I'm hoping to integrate this PR soonish. And sorry for the long-lived PR, I can only blame it on the unusually great summer in the north of Norway this year :-) ------------- PR Comment: https://git.openjdk.org/jdk/pull/12991#issuecomment-1785034602