一些Application的相关的参数配置,我们会放到env那里,通过application:get_env可以获取到,本身底层实现是基于ETS表,如果读取不频繁的话,微秒级别也是够用的了。

优化方案

老早之前,就看过mochiglobal,超级飞侠这个项目也是使用它来访问用得比较频繁一些env。最近写了篇《游戏常量配置Erlang实现》,又想了下第一个项目其中有用dynamic_compile来动态编译存储app env,当初前辈的实现写得并不好,每加一个env,都要去手动那个env的代码,搞得十分不方便,现在想想可以通过application:get_all_env(‘your_app_name’)来获取所有env的,避免手动取值。后面的项目,我就没用这个东西了,用mochiglobal去代替。

mochiglobal是用ast拼出代码,然后去编译的,不过中间有个不太满意的地方,模块名要list和atom互相转化,这部分开销可以省略,如果我们直接用模块名来访问数据的话。

constant:compile(Mod, KVList)之后,Mod:K()就可以访问到数据了。比如constant:compile(app_env, [{port, 8000}]),app_env:port()就可以拿到8000了。

通过测试,访问100W次,constant的做法大概是30毫秒,mochiglobal大概是400毫秒。另外ETS的话,100W次是1s。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
-module(constant).
-export([compile/2]).
compile(Mod, KVList) ->
Bin = makes(Mod, KVList),
code:purge(Mod),
{module, Mod} = code:load_binary(Mod, atom_to_list(Mod) ++ ".erl", Bin),
ok.
makes(Module, KVList) ->
{ok, Module, Bin} = compile:forms(forms(Module, KVList),
[verbose, report_errors]),
Bin.
forms(Module, KVList) ->
[erl_syntax:revert(X) || X <- term_to_abstract(Module, KVList)].
term_to_abstract(Module, KVList) ->
ModuleName = erl_syntax:attribute(
erl_syntax:atom(module),
[erl_syntax:atom(Module)]),
Export = erl_syntax:attribute(
erl_syntax:atom(export),
[erl_syntax:list(
[erl_syntax:arity_qualifier(
erl_syntax:atom(K),
erl_syntax:integer(0)) || {K, _} <- KVList])]),
Functions = [erl_syntax:function(
erl_syntax:atom(K),
[erl_syntax:clause([], none, [erl_syntax:abstract(V)])]) || {K, V} <- KVList],
[ModuleName, Export | Functions].

更多

![][image-1]