B6.Frequently Asked Questions
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).
Benchmark | Mode | Cnt | Score | Error | Units |
---|---|---|---|---|---|
Meepo.benchmark | thrpt | 50 | 24177.507 ± | 493.546 | ops/s |
Freemarker.benchmark | thrpt | 50 | 18152.915 ± | 928.830 | ops/s |
Mustache.benchmark | thrpt | 50 | 22565.064 ± | 154.915 | ops/s |
Pebble.benchmark | thrpt | 50 | 34311.017 ± | 248.283 | ops/s |
Rocker.benchmark | thrpt | 50 | 37499.123 ± | 1275.888 | ops/s |
Thymeleaf.benchmark | thrpt | 50 | 5406.186 ± | 177.424 | ops/s |
Trimou.benchmark | thrpt | 50 | 19718.903 ± | 669.759 | ops/s |
Velocity.benchmark | thrpt | 50 | 18956.594 ± | 766.578 | ops/s |
03.How to Tune Performance
Run MeepoAsyncProfile by main, then use async-profiler
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
andif
, andengine
extensions - The directive syntax is similar to
s/find/replace/g
invi
- 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,
- Create styles data in the model directly
- Customize engine to compute the style
- By
USE
it._count|mod, eg. each-c7s1f7-i1.htm - By
WHEN
it._count|mod, eg. each-c7s1f7-i2.htm
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