Skip to content

Commit

Permalink
Merge pull request #33 from h6x0r/tuning-v1.2
Browse files Browse the repository at this point in the history
Small optimizations Cell module
  • Loading branch information
neodix42 authored Aug 15, 2024
2 parents 0e1002f + 9620a80 commit 67fdeac
Show file tree
Hide file tree
Showing 39 changed files with 371 additions and 278 deletions.
22 changes: 5 additions & 17 deletions bitstring/src/main/java/org/ton/java/bitstring/BitString.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public BitString(int[] bytes) {
array = new ArrayDeque<>(0);
initialLength = 0;
} else {
byte[] bits = leftPadBytes(Utils.bytesToBitString(bytes).getBytes(), bytes.length * 8, '0');
byte[] bits = Utils.leftPadBytes(Utils.bytesToBitString(bytes).getBytes(StandardCharsets.UTF_8), bytes.length * 8, '0');

array = new ArrayDeque<>(bits.length);
for (byte bit : bits) { // whole length
Expand All @@ -65,7 +65,7 @@ public BitString(byte[] bytes, int size) {
array = new ArrayDeque<>(0);
initialLength = 0;
} else {
byte[] bits = leftPadBytes(Utils.bytesToBitString(bytes).getBytes(), bytes.length * 8, '0');
byte[] bits = Utils.leftPadBytes(Utils.bytesToBitString(bytes).getBytes(StandardCharsets.UTF_8), bytes.length * 8, '0');
array = new ArrayDeque<>(bits.length);
for (int i = 0; i < size; i++) { // specified length
if (bits[i] == (byte) '1') {
Expand All @@ -80,18 +80,6 @@ public BitString(byte[] bytes, int size) {
}
}

private byte[] leftPadBytes(byte[] bits, int sz, char c) {
if (sz <= bits.length) {
return bits;
}

int diff = sz - bits.length;
byte[] b = new byte[diff + bits.length];
Arrays.fill(b, 0, diff, (byte) c);
System.arraycopy(bits, 0, b, diff, bits.length);

return b;
}

/**
* Create BitString limited by length
Expand Down Expand Up @@ -212,7 +200,7 @@ public void writeUint(BigInteger number, int bitLength) {
throw new Error("bitLength is too small for number, got number=" + number + ", bitLength=" + bitLength);
}

byte[] s = number.toString(2).getBytes();
byte[] s = number.toString(2).getBytes(StandardCharsets.UTF_8);

if (s.length != bitLength) {
s = repeatZerosAndMerge(bitLength - s.length, s);
Expand Down Expand Up @@ -640,7 +628,7 @@ public byte[] toByteArray() {
return new byte[0];
}

byte[] bin = getBitString().getBytes();
byte[] bin = getBitString().getBytes(StandardCharsets.UTF_8);
int sz = bin.length;
byte[] result = new byte[(sz + 7) / 8];

Expand All @@ -660,7 +648,7 @@ public int[] toUintArray() {
return new int[0];
}

byte[] bin = getBitString().getBytes();
byte[] bin = getBitString().getBytes(StandardCharsets.UTF_8);
int sz = bin.length;
int[] result = new int[(sz + 7) / 8];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.logging.Logger;

import static java.util.Objects.isNull;

Expand All @@ -14,7 +15,7 @@
* Interestingly, but this solution loses to Deque<Boolean> array solution from memory footprint allocation.
*/
public class RealBitString {

private static final Logger log = Logger.getLogger(RealBitString.class.getName());
byte[] array;
public int writeCursor;
public int readCursor;
Expand Down Expand Up @@ -625,7 +626,7 @@ public void setTopUppedArray(byte[] arr, boolean fulfilledBytes) {
// writeCursor = saveWriteCursor;

if (!foundEndBit) {
System.err.println(Arrays.toString(arr) + ", " + fulfilledBytes);
log.info((Arrays.toString(arr) + ", " + fulfilledBytes));
throw new Error("Incorrect TopUppedArray");
}
}
Expand Down
7 changes: 3 additions & 4 deletions cell/src/main/java/org/ton/java/cell/BinTree.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,21 @@ public BinTree(Deque<ShardDescr> list) {
}

public Cell toCell() {
if (list.size() == 0) {
if (list.isEmpty()) {
return CellBuilder.beginCell().endCell();
}
return addToBinTree(list, null);
}

private static Cell addToBinTree(Deque<ShardDescr> cells, Cell left) {
CellBuilder c = CellBuilder.beginCell();
if (cells.size() >= 1) {
if (!cells.isEmpty()) {
CellBuilder cb = CellBuilder.beginCell();
cb.storeBit(true);
cb.storeRef(CellBuilder.beginCell()
.storeBit(false)
.storeCell(isNull(left) ? cells.pop().toCell() : left)
.endCell());
if (cells.size() != 0) {
if (!cells.isEmpty()) {
cb.storeRef(addToBinTree(cells, cells.pop().toCell()));
}
return cb.endCell();
Expand Down
57 changes: 25 additions & 32 deletions cell/src/main/java/org/ton/java/cell/Cell.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package org.ton.java.cell;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.ton.java.bitstring.BitString;
import org.ton.java.tlb.types.Boc;
import org.ton.java.utils.Utils;

import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
Expand Down Expand Up @@ -237,7 +237,7 @@ public void calculateHashes() {
depth = refDepth;
}
}
if (refs.size() > 0) {
if (!refs.isEmpty()) {
depth++;
if (depth >= 1024) {
throw new Error("depth is more than max depth (1023)");
Expand Down Expand Up @@ -359,9 +359,6 @@ public static Cell fromHex(String hexBitString) {
BitString bss = new BitString(ba.length);
bss.writeBitArray(ba);

// BitString f = new BitString(bss.getBitString().length());
// f.writeBitString(bss);

return CellBuilder.beginCell().storeBitString(bss).endCell();
} catch (Exception e) {
throw new Error("Cannot convert hex BitString to Cell. Error " + e.getMessage());
Expand Down Expand Up @@ -482,7 +479,7 @@ private static Boc deserializeBocHeader(byte[] data) {
*/
public String print(String indent) {
StringBuilder s = new StringBuilder(indent + "x{" + bits.toHex() + "}\n");
if (nonNull(refs) && refs.size() > 0) {
if (nonNull(refs) && !refs.isEmpty()) {
for (Cell i : refs) {
if (nonNull(i)) {
s.append(i.print(indent + " "));
Expand All @@ -493,12 +490,11 @@ public String print(String indent) {
}

public String print() {
String indent = "";
StringBuilder s = new StringBuilder(indent + "x{" + bits.toHex() + "}\n");
if (nonNull(refs) && refs.size() > 0) {
StringBuilder s = new StringBuilder("x{" + bits.toHex() + "}\n");
if (nonNull(refs) && !refs.isEmpty()) {
for (Cell i : refs) {
if (nonNull(i)) {
s.append(i.print(indent + " "));
s.append(i.print(" "));
}
}
}
Expand All @@ -509,7 +505,6 @@ public String print() {
* Saves BoC to file
*/
public void toFile(String filename, boolean withCrc) {

byte[] boc = toBoc(withCrc);
try {
Files.write(Paths.get(filename), boc);
Expand Down Expand Up @@ -595,7 +590,7 @@ public byte[] getRefsDescriptor(int lvl) {

public byte[] getBitsDescriptor() {
int bitsLength = bits.getLength();
byte d3 = (byte) (Math.floor((double) bitsLength / 8) * 2);
byte d3 = (byte) ((bitsLength / 8) * 2);
if ((bitsLength % 8) != 0) {
d3++;
}
Expand Down Expand Up @@ -636,9 +631,7 @@ public byte[] toBoc(boolean withCRC, boolean withIdx, boolean withCacheBits, boo

// taken from pytoniq - beautiful!
private Map<Cell, Integer> order(Map<Cell, Integer> result) {
if (result.containsKey(this)) {
result.remove(this);
}
result.remove(this);
result.put(this, null);
for (Cell ref : this.refs) {
ref.order(result);
Expand Down Expand Up @@ -667,7 +660,7 @@ public byte[] toBoc(boolean hasCrc32c, boolean hasIdx, boolean hasCacheBits, boo
}

BigInteger cellsNum = BigInteger.valueOf(indexed.size());
int cellsLen = (int) Math.floor((double) (cellsNum.bitLength() + 7) / 8);
int cellsLen = (cellsNum.bitLength() + 7) >> 3;

byte[] payload = new byte[0];
List<BigInteger> serializedCellLen = new ArrayList<>();
Expand All @@ -677,10 +670,9 @@ public byte[] toBoc(boolean hasCrc32c, boolean hasIdx, boolean hasCacheBits, boo
serializedCellLen.add(BigInteger.valueOf(serializeResult.length));
}

// System.out.println(Utils.bytesToHex(payload));
// bytes needed to store len of payload
int sizeBits = Utils.log2(payload.length + 1);
int sizeBytes = (int) Math.ceil((double) sizeBits / 8);
int sizeBits = Utils.log2Ceil(payload.length + 1);
int sizeBytes = (sizeBits + 7) / 8;

int numberOfRoots = 1;
int absent = 0;
Expand All @@ -707,14 +699,12 @@ public byte[] toBoc(boolean hasCrc32c, boolean hasIdx, boolean hasCacheBits, boo
}

private List<Cell> flattenIndex(List<Cell> src, boolean hasTopHash, boolean hasIntHashes) {

List<Cell> pending = src;
Map<String, Cell> allCells = new HashMap<>();
Map<String, Cell> notPermCells = new HashMap<>();

Deque<String> sorted = new ArrayDeque<>();

while (pending.size() > 0) {
while (!pending.isEmpty()) {
List<Cell> cells = new ArrayList<>(pending);
pending = new ArrayList<>();

Expand All @@ -731,15 +721,14 @@ private List<Cell> flattenIndex(List<Cell> src, boolean hasTopHash, boolean hasI
}

Map<String, Boolean> tempMark = new HashMap<>();
while (notPermCells.size() > 0) {
while (!notPermCells.isEmpty()) {
for (String key : notPermCells.keySet()) {
visit(key, allCells, notPermCells, tempMark, sorted);
break;
}
}

Map<String, Integer> indexes = new HashMap<>();

Deque<String> tmpSorted = new ArrayDeque<>(sorted);
int len = tmpSorted.size();
for (int i = 0; i < len; i++) {
Expand Down Expand Up @@ -789,7 +778,6 @@ private void visit(String hash, Map<String, Cell> allCells, Map<String, Cell> no

private byte[] serialize(int refIndexSzBytes) {
byte[] body = Utils.unsignedBytesToSigned(CellSlice.beginParse(this).loadSlice(this.bits.getLength()));
// byte[] body1 = getDataBytes();
byte[] descriptors = getDescriptors(levelMask.getMask());
byte[] data = Utils.concatBytes(descriptors, body);

Expand Down Expand Up @@ -825,12 +813,19 @@ private int getDepth(int lvlMask) {

private byte[] getDataBytes() {
if ((bits.getLength() % 8) > 0) {
String s = bits.toBitString();
s = s + "1";
if ((s.length() % 8) > 0) {
s = s + StringUtils.repeat("0", 8 - (s.length() % 8));
byte[] a = bits.toBitString().getBytes(StandardCharsets.UTF_8);
int sz = a.length;
byte[] b = new byte[sz + 1];

System.arraycopy(a, 0, b, 0, sz);
b[sz] = (byte) '1';

int mod = b.length % 8;
if (mod > 0) {
b = Utils.rightPadBytes(b, b.length + (8 - mod), '0');
}
return Utils.bitStringToByteArray(s);

return Utils.bitStringToByteArray(new String(b));
} else {
return bits.toByteArray();
}
Expand All @@ -851,9 +846,7 @@ public CellType getCellType() {
switch (cellType) {
case ORDINARY: {
if (bits.getLength() >= 288) {
//int msk = clonedBits.readUint(8).intValue();
LevelMask msk = new LevelMask(clonedBits.readUint(8).intValue());
// byte msk = levelMask;
int lvl = msk.getLevel();
if ((lvl > 0) && (lvl <= 3) && (bits.getLength() >= 16 + (256 + 16) * msk.apply(lvl - 1).getHashIndex() + 1)) {
return CellType.PRUNED_BRANCH;
Expand Down
3 changes: 2 additions & 1 deletion cell/src/main/java/org/ton/java/cell/CellBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import org.ton.java.utils.Utils;

import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.util.List;

import static java.util.Objects.isNull;
Expand Down Expand Up @@ -219,7 +220,7 @@ public CellBuilder storeString(String str) {
}

public CellBuilder storeSnakeString(String str) {
byte[] strBytes = str.getBytes();
byte[] strBytes = str.getBytes(StandardCharsets.UTF_8);
Cell c = f(127 - 4, strBytes);
return this.storeSlice(CellSlice.beginParse(c));
}
Expand Down
20 changes: 9 additions & 11 deletions cell/src/main/java/org/ton/java/cell/CellSlice.java
Original file line number Diff line number Diff line change
Expand Up @@ -162,10 +162,10 @@ public TonHashMap loadDict(int n, Function<BitString, Object> keyParser, Functio
TonHashMap x = new TonHashMap(n);
x.deserialize(this, keyParser, valueParser);

if (refs.size() != 0) {
if (!refs.isEmpty()) {
refs.remove(0);
}
if (refs.size() != 0) {
if (!refs.isEmpty()) {
refs.remove(0);
}

Expand All @@ -179,10 +179,10 @@ public TonHashMapAug loadDictAug(int n, Function<BitString, Object> keyParser, F
TonHashMapAug x = new TonHashMapAug(n);
x.deserialize(this, keyParser, valueParser, extraParser);

if (refs.size() != 0) {
if (!refs.isEmpty()) {
refs.remove(0);
}
if (refs.size() != 0) {
if (!refs.isEmpty()) {
refs.remove(0);
}

Expand Down Expand Up @@ -439,20 +439,18 @@ public String loadString(int length) {
* @return String
*/
public String loadSnakeString() {
List<Integer> result = new ArrayList<>();
StringBuilder s = new StringBuilder();
checkBitsOverflow(bits.getLength()); // bitsLeft
CellSlice ref = this.clone();

while (nonNull(ref)) {
try {
BitString bitString = ref.loadBits(ref.bits.getLength());

int[] uintArray = bitString.toUintArray();
List<Integer> resultList = new ArrayList<>(uintArray.length);
for (int value : uintArray) {
resultList.add(value);
byte[] uintArray = bitString.toByteArray();
for (byte value : uintArray) {
s.append((char) value);
}
result.addAll(resultList);

if (ref.refs.size() > 1) {
throw new Error("more than one ref, it is not snake string");
Expand All @@ -468,7 +466,7 @@ public String loadSnakeString() {
ref = null;
}

return result.stream().map(m -> new String(new byte[]{m.byteValue()})).collect(Collectors.joining());
return s.toString();
}

public BitString loadBits(int length) {
Expand Down
2 changes: 1 addition & 1 deletion cell/src/main/java/org/ton/java/cell/LevelMask.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public static int calculateMinimumBits(int number) {
return 0;
}

return (int) Math.ceil(Math.log(number + 1) / Math.log(2));
return Integer.SIZE - Integer.numberOfLeadingZeros(number);
}

public static int calculateOnesBits(int number) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@

public interface BlockCreateStats {

public Cell toCell();
Cell toCell();

public static BlockCreateStats deserialize(CellSlice cs) {
static BlockCreateStats deserialize(CellSlice cs) {
long magic = cs.loadUint(8).longValue();
if (magic == 0x17) {
return BlockCreateStatsOrdinary.deserialize(cs);
Expand Down
Loading

0 comments on commit 67fdeac

Please sign in to comment.