Skip to content

Performance improvement#1

Open
sjcl wants to merge 41 commits intomasterfrom
sjcl
Open

Performance improvement#1
sjcl wants to merge 41 commits intomasterfrom
sjcl

Conversation

@sjcl
Copy link
Member

@sjcl sjcl commented Jan 27, 2026

No description provided.

@sjcl sjcl requested a review from Siro256 January 27, 2026 19:40
@Siro256 Siro256 requested a review from yanorei32 January 28, 2026 11:54
@sjcl
Copy link
Member Author

sjcl commented Jan 28, 2026

やったー

@yanorei32
Copy link
Member

私Java読めませんけど?🫠

Comment on lines 59 to 67
private static int calcBufferLength(String src) {
int srcCodePointCount = src.codePointCount(0, src.length());

int offset = src.offsetByCodePoints(0, srcCodePointCount - 1);
int lastCodePoint = src.codePointAt(offset);
boolean isSevenBitsCode = lastCodePoint <= SEVEN_BITS_CP_FINAL;

return (isSevenBitsCode ? (srcCodePointCount - 1) * 15 + 7 : srcCodePointCount * 15) / 8;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

文字を総舐めしてcp数を数えるより、入力された文字が正しいBase32768エンコーディングであると仮定して文字数からバッファ長を計算したほうが良いかもしれない?

Copy link
Member Author

@sjcl sjcl Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

これで想定通りになってますでしょうか🤔
841e708#diff-ff77f28618ed3ff2b77ee4dbdabcc828feecd35f82de94f55b1d077d79945cdcR53-R58

Comment on lines 128 to 135
final int n = src.length();
if (n == 0) return new byte[0];

int srcCodePointCount = src.codePointCount(0, src.length());
byte[] bytes = new byte[calcBufferLength(src)];

// Multithread-safeではない
final var ref = new Object() {
int srcIndex = 0;
int dstIndex = 0;
int buf = 0;
int bufCount = 0;
};
src.codePoints().forEachOrdered(codePoint -> {
Integer byteBase = TABLE.get(codePoint & ~31);
if (byteBase == null) throw new IllegalBase32768TextException(ref.srcIndex + 1, codePoint);

if (codePoint <= SEVEN_BITS_CP_FINAL) {
if (ref.srcIndex != srcCodePointCount - 1) throw new IllegalBase32768TextException(codePoint);
ref.buf = (ref.buf << 7) + byteBase + codePoint % 32;
ref.bufCount += 7;
} else {
ref.buf = (ref.buf << 15) + byteBase + codePoint % 32;
ref.bufCount += 15;
final char last = src.charAt(n - 1);
final int lastBits = LAST_BITS[last] & 0xFF;
if (lastBits == 0) throw new IllegalBase32768TextException(n - 1, last);

final int outLen = ((n - 1) * 15 + lastBits) >>> 3;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

これをcalcBufferLengthの実装にすると良いかもしれません?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

calcBufferLengthと同じ実装になりましたが、そもそもの実装が意図していないものだったらこちらも同様かもしれません

Comment on lines 22 to 23
private static final char[] DECODE = new char[1 << 16];
private static final byte[] LAST_BITS = new byte[1 << 16];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

15bits範囲と7bits範囲のテーブルを分けると、テーブルサイズが2^17から2^11 + 2^8に削減できそうな気がします

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

とりあえず変更量が少なくて済む方法としてDECODEのサイズを削れるだけ削ってみました。これで分割とほぼ同じ削減量を得られる気がしますがどうでしょうか🤔
LAST_BITSはブロック単位にして、大幅削減しました。シフト演算が1回増えるけどパフォーマンスへの影響は誤差の範囲なはずです

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

なんで最初からこうしなかったのかは不明なんですが、それはそうと破壊してないか不安です
テストは通ってますが...

@sjcl sjcl requested a review from Siro256 January 28, 2026 22:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants