mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 07:14:30 +02:00
8300493: Use ArraysSupport.vectorizedHashCode in j.u.zip.ZipCoder
Reviewed-by: alanb, lancea
This commit is contained in:
parent
06394ee8b1
commit
bb42e61a61
4 changed files with 112 additions and 17 deletions
|
@ -2461,6 +2461,9 @@ public final class System {
|
||||||
return ModuleLayer.layers(loader);
|
return ModuleLayer.layers(loader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int countPositives(byte[] bytes, int offset, int length) {
|
||||||
|
return StringCoding.countPositives(bytes, offset, length);
|
||||||
|
}
|
||||||
public String newStringNoRepl(byte[] bytes, Charset cs) throws CharacterCodingException {
|
public String newStringNoRepl(byte[] bytes, Charset cs) throws CharacterCodingException {
|
||||||
return String.newStringNoRepl(bytes, cs);
|
return String.newStringNoRepl(bytes, cs);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ import java.nio.charset.CharacterCodingException;
|
||||||
import java.nio.charset.CodingErrorAction;
|
import java.nio.charset.CodingErrorAction;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import jdk.internal.util.ArraysSupport;
|
||||||
import sun.nio.cs.UTF_8;
|
import sun.nio.cs.UTF_8;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -209,25 +210,18 @@ class ZipCoder {
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int end = off + len;
|
int end = off + len;
|
||||||
int h = 0;
|
int asciiLen = JLA.countPositives(a, off, len);
|
||||||
while (off < end) {
|
if (asciiLen != len) {
|
||||||
byte b = a[off];
|
|
||||||
if (b >= 0) {
|
|
||||||
// ASCII, keep going
|
|
||||||
h = 31 * h + b;
|
|
||||||
off++;
|
|
||||||
} else {
|
|
||||||
// Non-ASCII, fall back to decoding a String
|
// Non-ASCII, fall back to decoding a String
|
||||||
// We avoid using decoder() here since the UTF8ZipCoder is
|
// We avoid using decoder() here since the UTF8ZipCoder is
|
||||||
// shared and that decoder is not thread safe.
|
// shared and that decoder is not thread safe.
|
||||||
// We use the JLA.newStringUTF8NoRepl variant to throw
|
// We use the JLA.newStringUTF8NoRepl variant to throw
|
||||||
// exceptions eagerly when opening ZipFiles
|
// exceptions eagerly when opening ZipFiles
|
||||||
return hash(JLA.newStringUTF8NoRepl(a, end - len, len));
|
return hash(JLA.newStringUTF8NoRepl(a, off, len));
|
||||||
}
|
}
|
||||||
}
|
// T_BOOLEAN to treat the array as unsigned bytes, in line with StringLatin1.hashCode
|
||||||
|
int h = ArraysSupport.vectorizedHashCode(a, off, len, 0, ArraysSupport.T_BOOLEAN);
|
||||||
if (a[end - 1] != '/') {
|
if (a[end - 1] != '/') {
|
||||||
h = 31 * h + '/';
|
h = 31 * h + '/';
|
||||||
}
|
}
|
||||||
|
|
|
@ -302,6 +302,11 @@ public interface JavaLangAccess {
|
||||||
*/
|
*/
|
||||||
Stream<ModuleLayer> layers(ClassLoader loader);
|
Stream<ModuleLayer> layers(ClassLoader loader);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count the number of leading positive bytes in the range.
|
||||||
|
*/
|
||||||
|
int countPositives(byte[] ba, int off, int len);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new {@code String} by decoding the specified subarray of
|
* Constructs a new {@code String} by decoding the specified subarray of
|
||||||
* bytes using the specified {@linkplain java.nio.charset.Charset charset}.
|
* bytes using the specified {@linkplain java.nio.charset.Charset charset}.
|
||||||
|
|
93
test/micro/org/openjdk/bench/java/util/zip/ZipFileOpen.java
Normal file
93
test/micro/org/openjdk/bench/java/util/zip/ZipFileOpen.java
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.openjdk.bench.java.util.zip;
|
||||||
|
|
||||||
|
import org.openjdk.jmh.annotations.*;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.zip.ZipEntry;
|
||||||
|
import java.util.zip.ZipFile;
|
||||||
|
import java.util.zip.ZipOutputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple benchmark measuring cost of opening zip files, parsing CEN
|
||||||
|
* entries.
|
||||||
|
*/
|
||||||
|
@BenchmarkMode(Mode.AverageTime)
|
||||||
|
@OutputTimeUnit(TimeUnit.NANOSECONDS)
|
||||||
|
@State(Scope.Thread)
|
||||||
|
@Warmup(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
|
||||||
|
@Measurement(iterations = 5, time = 1000, timeUnit = TimeUnit.MILLISECONDS)
|
||||||
|
@Fork(3)
|
||||||
|
public class ZipFileOpen {
|
||||||
|
|
||||||
|
@Param({"512", "1024"})
|
||||||
|
private int size;
|
||||||
|
|
||||||
|
public File zipFile;
|
||||||
|
|
||||||
|
@Setup(Level.Trial)
|
||||||
|
public void beforeRun() throws IOException {
|
||||||
|
// Create a test Zip file with the number of entries.
|
||||||
|
File tempFile = Files.createTempFile("zip-micro", ".zip").toFile();
|
||||||
|
tempFile.deleteOnExit();
|
||||||
|
try (FileOutputStream fos = new FileOutputStream(tempFile);
|
||||||
|
ZipOutputStream zos = new ZipOutputStream(fos)) {
|
||||||
|
|
||||||
|
// Vary dir and entry sizes, with a bias towards shorter entries.
|
||||||
|
String[] dirPrefixes = new String[] { "dir1", "dir2", "dir3",
|
||||||
|
"longer-directory-name-", "ridiculously-long-pathname-to-help-exercize-vectorized-subroutines-"};
|
||||||
|
String[] entryPrefixes = new String[] { "e", "long-entry-name-",
|
||||||
|
"ridiculously-long-entry-name-to-help-exercize-vectorized-subroutines-"};
|
||||||
|
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
String ename = dirPrefixes[i % dirPrefixes.length] + i + "/";
|
||||||
|
zos.putNextEntry(new ZipEntry(ename));
|
||||||
|
|
||||||
|
ename += entryPrefixes[i % entryPrefixes.length] + "-" + i;
|
||||||
|
zos.putNextEntry(new ZipEntry(ename));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
zipFile = tempFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
public ZipFile openCloseZipFile() throws Exception {
|
||||||
|
// Some shared resources in ZipFile are cached in a shared structure
|
||||||
|
// and needs to be cleaned up to properly capture overhead of creating
|
||||||
|
// a ZipFile - otherwise opening the same zip file again will reuse the
|
||||||
|
// cached data and look artificially fast. By including the ZipFile.close()
|
||||||
|
// we aggressively clear those resources pre-emptively. The operations
|
||||||
|
// appears to be complex enough to not be subject to DCE but care needs
|
||||||
|
// to be taken to check that things like initCEN is properly accounted
|
||||||
|
// for if/when the ZipFile setup improves.
|
||||||
|
ZipFile zf = new ZipFile(zipFile);
|
||||||
|
zf.close();
|
||||||
|
return zf;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue