Optimize Strings representation at FastJarHandler
This commit is contained in:
committed by
teamcityserver
parent
4e66fd29e0
commit
bc75a21852
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
package org.jetbrains.kotlin.cli.jvm.compiler.jarfs
|
||||||
|
|
||||||
|
class ByteArrayCharSequence(
|
||||||
|
private val bytes: ByteArray,
|
||||||
|
private val start: Int = 0,
|
||||||
|
private val end: Int = bytes.size
|
||||||
|
) : CharSequence {
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
error("Do not try computing hashCode ByteArrayCharSequence")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
error("Do not try comparing ByteArrayCharSequence")
|
||||||
|
}
|
||||||
|
|
||||||
|
override val length get() = end - start
|
||||||
|
|
||||||
|
override fun get(index: Int): Char = bytes[index + start].toChar()
|
||||||
|
|
||||||
|
override fun subSequence(startIndex: Int, endIndex: Int): CharSequence {
|
||||||
|
if (startIndex == 0 && endIndex == length) return this
|
||||||
|
return ByteArrayCharSequence(bytes, start + startIndex, start + endIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
val chars = CharArray(length)
|
||||||
|
|
||||||
|
for (i in 0 until length) {
|
||||||
|
chars[i] = bytes[i + start].toChar()
|
||||||
|
}
|
||||||
|
|
||||||
|
return String(chars)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.jetbrains.kotlin.cli.jvm.compiler.jarfs
|
package org.jetbrains.kotlin.cli.jvm.compiler.jarfs
|
||||||
|
|
||||||
|
import com.intellij.openapi.util.text.StringUtil
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileNotFoundException
|
import java.io.FileNotFoundException
|
||||||
@@ -22,7 +23,9 @@ class FastJarHandler(val fileSystem: FastJarFileSystem, path: String) {
|
|||||||
val mappedByteBuffer = randomAccessFile.channel.map(FileChannel.MapMode.READ_ONLY, 0, randomAccessFile.length())
|
val mappedByteBuffer = randomAccessFile.channel.map(FileChannel.MapMode.READ_ONLY, 0, randomAccessFile.length())
|
||||||
try {
|
try {
|
||||||
entries = mappedByteBuffer.parseCentralDirectory()
|
entries = mappedByteBuffer.parseCentralDirectory()
|
||||||
cachedManifest = entries.singleOrNull { it.relativePath == MANIFEST_PATH }?.let(mappedByteBuffer::contentsToByteArray)
|
cachedManifest =
|
||||||
|
entries.singleOrNull { StringUtil.equals(MANIFEST_PATH, it.relativePath) }
|
||||||
|
?.let(mappedByteBuffer::contentsToByteArray)
|
||||||
} finally {
|
} finally {
|
||||||
with(fileSystem) {
|
with(fileSystem) {
|
||||||
mappedByteBuffer.unmapBuffer()
|
mappedByteBuffer.unmapBuffer()
|
||||||
@@ -66,8 +69,8 @@ class FastJarHandler(val fileSystem: FastJarFileSystem, path: String) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getOrCreateDirectory(entryName: String, directories: MutableMap<String, FastJarVirtualFile>): FastJarVirtualFile {
|
private fun getOrCreateDirectory(entryName: CharSequence, directories: MutableMap<String, FastJarVirtualFile>): FastJarVirtualFile {
|
||||||
return directories.getOrPut(entryName) {
|
return directories.getOrPut(entryName.toString()) {
|
||||||
val (parentPath, shortName) = entryName.splitPath()
|
val (parentPath, shortName) = entryName.splitPath()
|
||||||
val parentFile = getOrCreateDirectory(parentPath, directories)
|
val parentFile = getOrCreateDirectory(parentPath, directories)
|
||||||
|
|
||||||
@@ -75,7 +78,7 @@ class FastJarHandler(val fileSystem: FastJarFileSystem, path: String) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun String.splitPath(): Pair<String, String> {
|
private fun CharSequence.splitPath(): Pair<CharSequence, CharSequence> {
|
||||||
var slashIndex = this.length - 1
|
var slashIndex = this.length - 1
|
||||||
|
|
||||||
while (slashIndex >= 0 && this[slashIndex] != '/') {
|
while (slashIndex >= 0 && this[slashIndex] != '/') {
|
||||||
@@ -83,7 +86,7 @@ class FastJarHandler(val fileSystem: FastJarFileSystem, path: String) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (slashIndex == -1) return Pair("", this)
|
if (slashIndex == -1) return Pair("", this)
|
||||||
return Pair(substring(0, slashIndex), substring(slashIndex + 1))
|
return Pair(subSequence(0, slashIndex), subSequence(slashIndex + 1, this.length))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun findFileByPath(pathInJar: String): VirtualFile? {
|
fun findFileByPath(pathInJar: String): VirtualFile? {
|
||||||
@@ -92,7 +95,7 @@ class FastJarHandler(val fileSystem: FastJarFileSystem, path: String) {
|
|||||||
|
|
||||||
fun contentsToByteArray(zipEntryDescription: ZipEntryDescription): ByteArray {
|
fun contentsToByteArray(zipEntryDescription: ZipEntryDescription): ByteArray {
|
||||||
val relativePath = zipEntryDescription.relativePath
|
val relativePath = zipEntryDescription.relativePath
|
||||||
if (relativePath == MANIFEST_PATH) return cachedManifest ?: throw FileNotFoundException("$file!/$relativePath")
|
if (StringUtil.equals(relativePath, MANIFEST_PATH)) return cachedManifest ?: throw FileNotFoundException("$file!/$relativePath")
|
||||||
return fileSystem.cachedOpenFileHandles[file].use {
|
return fileSystem.cachedOpenFileHandles[file].use {
|
||||||
synchronized(it) {
|
synchronized(it) {
|
||||||
it.get().second.contentsToByteArray(zipEntryDescription)
|
it.get().second.contentsToByteArray(zipEntryDescription)
|
||||||
|
|||||||
@@ -12,12 +12,12 @@ import java.util.zip.Inflater
|
|||||||
|
|
||||||
|
|
||||||
class ZipEntryDescription(
|
class ZipEntryDescription(
|
||||||
val relativePath: String,
|
val relativePath: CharSequence,
|
||||||
val compressedSize: Int,
|
val compressedSize: Int,
|
||||||
val uncompressedSize: Int,
|
val uncompressedSize: Int,
|
||||||
val offsetInFile: Int,
|
val offsetInFile: Int,
|
||||||
val compressionKind: CompressionKind,
|
val compressionKind: CompressionKind,
|
||||||
val fileNameSize: Int
|
val fileNameSize: Int,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
enum class CompressionKind {
|
enum class CompressionKind {
|
||||||
@@ -101,7 +101,7 @@ fun MappedByteBuffer.parseCentralDirectory(): List<ZipEntryDescription> {
|
|||||||
|
|
||||||
val name =
|
val name =
|
||||||
if (bytesForName.all { it >= 0 })
|
if (bytesForName.all { it >= 0 })
|
||||||
String(bytesForName.asASCICharArray())
|
ByteArrayCharSequence(bytesForName)
|
||||||
else
|
else
|
||||||
String(bytesForName, Charsets.UTF_8)
|
String(bytesForName, Charsets.UTF_8)
|
||||||
|
|
||||||
@@ -126,6 +126,4 @@ fun MappedByteBuffer.parseCentralDirectory(): List<ZipEntryDescription> {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ByteArray.asASCICharArray(): CharArray = CharArray(size) { this@asASCICharArray[it].toChar() }
|
|
||||||
|
|
||||||
private fun ByteBuffer.getUnsignedShort(offset: Int): Int = java.lang.Short.toUnsignedInt(getShort(offset))
|
private fun ByteBuffer.getUnsignedShort(offset: Int): Int = java.lang.Short.toUnsignedInt(getShort(offset))
|
||||||
|
|||||||
Reference in New Issue
Block a user