Skip to main content

B6.Frequently Asked Questions

trydoforOriginalMeepoTemplateAbout 3 min

B6.Frequently Asked Questions

01.How to Debug, eg. Parsing

Debugging is mainly focused on Parse and RnaEngine execution, so logger only exists in these 2 places. In the testing of the Meepo project itself, the slf4j logger is at trace level, so when debugging in other projects, you need to set the level of pro.fessional.mepo to trace.

If the debug logs are not detailed enough, you can extend Parser, and then call the protected method.

If you get an error like 'Class path contains multiple SLF4J bindings', you can directly exclude the slf4j dependency from Meepo.

02.Performance and Thread Safety

The template engines are all parsed once, used many times, with some pre-compilation or caching.

When Meepo parsing, the Parse itself is based on string analysis and only uses the RegExp in directive's find. It is usually recommended that the parsing process needs to be done within a single thread and multiple parsing or competition is not necessary.

When merging, if there is no Rng level directive, it just does a static string concat, concat first, then cache. During the concating, just pre-allocate enough buffs to avoid expansion. Performance is better than multiple times of string appends.

Without Rng in directive, it is thread-safe and very few fragments, so it can be used safely. but when Rng is present, the performance and thread safety depend on the execution engine and the context.

Meepo's performance is much better than Freemarker according to benchmark results (for+if+function).

BenchmarkModeCntScoreErrorUnits
Meepo.benchmarkthrpt5024177.507 ±493.546ops/s
Freemarker.benchmarkthrpt5018152.915 ±928.830ops/s
Mustache.benchmarkthrpt5022565.064 ±154.915ops/s
Pebble.benchmarkthrpt5034311.017 ±248.283ops/s
Rocker.benchmarkthrpt5037499.123 ±1275.888ops/s
Thymeleaf.benchmarkthrpt505406.186 ±177.424ops/s
Trimou.benchmarkthrpt5019718.903 ±669.759ops/s
Velocity.benchmarkthrpt5018956.594 ±766.578ops/s

03.How to Tune Performance

Run MeepoAsyncProfile by main, then use async-profileropen in new window

mvn clean
mvn -Dmaven.test.skip=false test
mvn dependency:copy-dependencies -DincludeScope=runtime -DoutputDirectory=target/lib

# Start a long loop, or you can run it directly in the IDE
java -cp target/classes:target/test-classes\
:target/lib/slf4j-api-1.7.30.jar\
:target/lib/annotations-19.0.0.jar \
pro.fessional.meepo.benchmark.MeepoAsyncProfile

# get the pid
jps
# use async-profiler to generate flame graph in svg
#/Users/trydofor/Applications-cli/async-profiler-1.8.2/profiler.sh
profiler.sh -d 30 -f meepo-profile.svg $pid

There are a lot of details related to performance, for the template engine, mainly focusing on string/char handling.

  • zero-copy, Use char[] instead of a full string copy.
  • For array assignment, use System.arraycopy
  • hashCode() and equals(), short-circuit in if
  • toString() of primitive type
  • Avoid expanding buffers, try to reuse them thread-safe

04.Meepo Syntax can Not Lexer

In general, grammar parsing consists of two steps: lexical and grammatical analysis.

  • First, perform lexical analysis to convert text into tokens
  • Then, perform grammatical analysis to combine tokens into statements and AST

Meepo uses a hard-coded finite-state way to handle the dynamic MEEPO head/tail and BKB block.

05.How to Remember Meepo Syntax

The syntax of Meepo is very simple, it is all about dota, vi and COVID-19 in 2020.

  • DNA, static replacement, is designed to translate templates
  • RNA, dynamic execution, support for and if, and engine extensions
  • The directive syntax is similar tos/find/replace/g in vi
  • Meepo says case-sensitive, but in fact its directive is case-insensitve

06.How to Input Empty and Quotes

There is special handling for quotes and blanks in the directive,

  • Two double quotes "", is the empty string
  • And quotes must escape, eg. \"

07.Zebra Stripes Like Other Templates

Meepo's starting point is that the template is only responsible for display, not for calculation, and the logical result should be predefined in the model. Therefore, creating a zebra style cell background in Meepo is complex, but can be achieved as follows,

08.Literal Number and Boolean

In the engine, DNA is all static string replacement and RNA is all fetching data from context. Only the pipeline function chain needs data from the template and data lieral type.

  • Number - see Pipelined Functions
  • Boolean - TRUE,FALSE, see above
  • The string type requires quotes, eg. "TRUE","3.14"
  • Otherwise, they are all RefStr. get value from the environment first, or this string if null