package com.hubspot.jinjava.benchmarks.liquid;
import static org.apache.commons.io.FileUtils.listFiles;
import static org.apache.commons.io.FileUtils.readFileToString;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.infra.Blackhole;
import org.slf4j.LoggerFactory;
import org.yaml.snakeyaml.Yaml;
import com.hubspot.jinjava.Jinjava;
import com.hubspot.jinjava.interpret.JinjavaInterpreter;
import com.hubspot.jinjava.tree.Node;
import ch.qos.logback.classic.Level;
@State(Scope.Benchmark)
public class LiquidBenchmark {
public List<String> templates;
public Map<String, ?> bindings;
public Jinjava jinjava;
@SuppressWarnings("unchecked")
@Setup
public void setup() throws IOException {
ch.qos.logback.classic.Logger logger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME);
logger.setLevel(Level.WARN);
jinjava = new Jinjava();
jinjava.getGlobalContext().registerClasses(
Filters.OverrideDateFilter.class,
Filters.JsonFilter.class,
Filters.LinkToAddTagFilter.class,
Filters.LinkToRemoveTagFilter.class,
Filters.LinkToTagFilter.class,
Filters.HighlightActiveTagFilter.class,
Filters.MoneyFilter.class,
Filters.MoneyWithCurrencyFilter.class,
Filters.ShopAssetUrlFilter.class,
Filters.ShopGlobalAssetUrl.class,
Filters.ShopImgTagFilter.class,
Filters.ShopLinkTo.class,
Filters.ShopScriptTag.class,
Filters.ShopShopifyAssetUrl.class,
Filters.ShopStylesheetTag.class,
Filters.WeightFilter.class,
Filters.WeightWithUnitFilter.class,
Tags.AssignTag.class,
Tags.CommentFormTag.class,
Tags.PaginateTag.class,
Tags.TableRowTag.class);
templates = new ArrayList<>();
Map<String, Object> db = (Map<String, Object>) new Yaml().load(readFileToString(new File("liquid/performance/shopify/vision.database.yml"), StandardCharsets.UTF_8));
bindings = new HashMap<>(initDb(db));
File baseDir = new File("liquid/performance/tests");
for (File tmpl : listFiles(baseDir, new String[] { "liquid" }, true)) {
String template = readFileToString(tmpl, StandardCharsets.UTF_8);
// convert filter syntax from ':' to '()'
template = template.replaceAll("\\| ([\\w_]+): (.*?)(\\||})", "| $1($2)$3");
// jinjava doesn't have the '?' postfix binary operator
template = template.replaceAll("if (.*?)\\?", "if $1");
// no support for offset:n
template = template.replaceAll("offset:\\s*\\d*", "");
// no support for limit:n
template = template.replaceAll("limit:\\s*\\d*", "");
// no support for cols:n
template = template.replaceAll("cols:\\s*\\d*", "");
// no support for for reversal
template = template.replaceAll(" reversed", "");
// System.out.println("Adding template: " + tmpl.getAbsolutePath());
// System.out.println(template);
templates.add(template);
}
}
@SuppressWarnings("unchecked")
private Map<String, Object> initDb(Map<String, Object> db) {
for (Map.Entry<String, ?> entry : db.entrySet()) {
if (entry.getValue() instanceof List) {
List<?> values = (List<?>) entry.getValue();
if (values.size() > 0 && values.get(0) instanceof Map) {
Map<String, Object> byHandle = new HashMap<>();
for (Map<String, Object> val : (List<Map<String, Object>>) values) {
String handle = val.getOrDefault("handle", "").toString();
if (handle.trim().length() > 0) {
byHandle.put(handle, val);
}
}
if (byHandle.size() > 0) {
db.put(entry.getKey(), byHandle);
}
}
}
}
return db;
}
@Benchmark
public void parse(Blackhole blackhole) {
JinjavaInterpreter interpreter = jinjava.newInterpreter();
for (String template : templates) {
Node parsed = interpreter.parse(template);
if (blackhole != null) {
blackhole.consume(parsed);
}
}
}
@Benchmark
public void parseAndRender(Blackhole blackhole) {
for (String template : templates) {
String result = jinjava.render(template, bindings);
if (blackhole != null) {
blackhole.consume(result);
}
}
}
public static void main(String[] args) throws Exception {
LiquidBenchmark b = new LiquidBenchmark();
b.setup();
b.parse(null);
b.parseAndRender(null);
}
}