内测022:优化消息格式化
#Quiz #Formatter #String #Jvm
@陈宝仪 / 2020-09-01 / CC-BY-SA-3.0
1.问题起源与描述
当使用logback做为slf4j-api的实现端打印日志时,我们通过async-profiler 发现logback做类似
logger.info("{} {}", value1, value2)这样的log解析时的内存分配以及性能存在瓶颈.
具体的解析代码见MessageFormatter.arrayFormat.
我们要实现一个高效的O(n)复杂度的算法替换MessageFormatter.arrayFormat. 需要实现的方法定义如下,
public String format(String str, Object[] args)
2.具体的答题要求
- 当
str为null时, 返回null.format(null, new Object[]{"a"})返回null - 当
args为null或者args.length < pattern length时.format("{} {} {a}", null)返回{null} {null} {a} - 当
str不存在{}等pattern时,直接返回str.format("abc", new Object[]{"a"})返回abc - 可能存在嵌套括号.
format("{{}}", new Object[]{"a"})返回{a} - 使用
\进行{,}的转义.format("\\{\\}", new Object[]{"a"})返回{} - 使用
\转义\自身.format("\\\\", new Object[]{"a"})返回\ - 可能仅存在
{或者}.format("{c", new Object[]{"a"})返回{c
更多测试用例参见MessageFormatterTest,部分示例如下。
format(null, new Object[]{"a"}) return null
format("{} {} {a}", null) return "{null} {null} {a}"
format("{} {} {a}", new Object[]{"b"}) return "{b} {null} {a}"
format("{} {} {a}", new Object[]{"b", "c", "d"}) return "{b} {c} {a}"
format("abc", new Object[]{"a"}) return "abc"
format("{{}}", new Object[]{"a"}) return "{a}"
format("\\{\\}", new Object[]{"a"}) return "{}"
format("\\{}", new Object[]{"a"}) return "{}"
format("\\\\", new Object[]{"a"}) return "\"
format("{c", new Object[]{"a"}) return "{c"
3.答题建议
- clone或fork成自己的repository
- 实现src/main/java/com/moilioncircle/message/formatter/MessageFormatter中的format方法
- 通过src/test/java/com/moilioncircle/message/formatter/MessageFormatterTest进行测试
- 如果clone到本地,可以使用 mvn clean package 进行测试
- 如果fork到github,可以Pull Request,进行测试
4.内存分配对比图
- 优化之前

- 优化之后

5.参考资料
- https://github.com/moilioncircle/message-formatter
- https://github.com/jvm-profiling-tools/async-profiler
- https://github.com/qos-ch/slf4j/blob/master/slf4j-api/src/main/java/org/slf4j/helpers/MessageFormatter.java#L179
–
※ 我们的征途是星辰大海 ※
题图:时代战士——克赛,前来拜访!这是80年代的经典记忆之一。