Skip to content

Commit

Permalink
⚡ Improve performance of BsonUtils.toJson()
Browse files Browse the repository at this point in the history
  • Loading branch information
ujibang committed Dec 19, 2023
1 parent d57642f commit 1ed0fd8
Show file tree
Hide file tree
Showing 3 changed files with 11,394 additions and 16 deletions.
12 changes: 3 additions & 9 deletions commons/src/main/java/org/restheart/utils/BsonUtils.java
Expand Up @@ -694,16 +694,10 @@ public static String toJson(BsonValue bson, JsonMode mode) {
if (bson.isDocument()) {
return minify(bson.asDocument().toJson(settings));
} else if (bson.isArray()) {
var sb = new StringBuilder();
var wrappedArray = new BsonDocument("w", bson.asArray());
var json = minify(wrappedArray.toJson(settings));

sb.append("[");
bson.asArray().stream().map(e -> toJson(e)).map(e -> minify(e)).forEach(e -> sb.append(e).append(","));
if (sb.length() > 1) {
sb.deleteCharAt(sb.length()-1); // remove last comma
}
sb.append("]");

return sb.toString();
return json.substring(5, json.length()-1); // removes {"w": and } closing }
} else {
var ret = new BsonDocument("x", bson).toJson(settings);

Expand Down
46 changes: 39 additions & 7 deletions commons/src/test/java/org/restheart/utils/BsonUtilsTest.java
Expand Up @@ -20,17 +20,13 @@

package org.restheart.utils;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import static org.restheart.utils.BsonUtils.array;
import static org.restheart.utils.BsonUtils.document;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.LongStream;

import org.bson.BsonArray;
import org.bson.BsonBoolean;
Expand All @@ -43,12 +39,20 @@
import org.bson.types.ObjectId;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.restheart.utils.BsonUtils.array;
import static org.restheart.utils.BsonUtils.document;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.io.Resources;

/**
*
* @author Andrea Di Cesare {@literal <andrea@softinstigate.com>}
Expand Down Expand Up @@ -1010,4 +1014,32 @@ public void testToJsonEmptyArray() {

assertEquals(expected, actual);
}

/**
* used to optimize BsonUtils.toJson()
* @throws IOException
*/
public void testPerformanceOfToJson() throws IOException {
var url = Resources.getResource("large-file.json");
var text = Resources.toString(url, StandardCharsets.UTF_8);

LOG.info("start parsing large file");
var startParse = System.currentTimeMillis();
var bson = BsonUtils.parse(text);
var endParse = System.currentTimeMillis();
LOG.info("end parsing large file. took {} ms", endParse-startParse);

LOG.info("start invoking toJson of large bson 10 times");
var avg = LongStream.range(0, 9).map(i -> toJson(i, bson)).average();

LOG.info("toJson average time {} ms", avg.getAsDouble());
}

private long toJson(long idx, BsonValue bson) {
var start = System.currentTimeMillis();
BsonUtils.toJson(bson);
var end = System.currentTimeMillis();
LOG.info("toJson iteration {} took {} ms", idx, end-start);
return end - start;
}
}

0 comments on commit 1ed0fd8

Please sign in to comment.