Java 当区域设置不同时,Freemarker模板缓存在相同的内容中,这是否会浪费内存?

Java 当区域设置不同时,Freemarker模板缓存在相同的内容中,这是否会浪费内存?,java,templates,caching,duplicates,freemarker,Java,Templates,Caching,Duplicates,Freemarker,调试freemarker模板缓存时,我注意到对于同一FTL源文件,freemarker模板缓存对象具有内容、区域设置和编码属性。当使用TemplateKey将此缓存值推入缓存时,该键包括文件名、区域设置、编码、解析等。问题是:对于相同的FTL文件,如果其具有不同的区域设置,则相同的文件内容将根据不同的区域设置、编码等在内存中多次缓存。对于支持所有区域设置的大型网站,这是对内存的极大浪费 这是一个非常大的内存问题。这里我们讨论的是Freemarker模板缓存中30倍的重复内存缓存 我可能是错的,因

调试freemarker模板缓存时,我注意到对于同一FTL源文件,freemarker模板缓存对象具有内容、区域设置和编码属性。当使用TemplateKey将此缓存值推入缓存时,该键包括文件名、区域设置、编码、解析等。问题是:对于相同的FTL文件,如果其具有不同的区域设置,则相同的文件内容将根据不同的区域设置、编码等在内存中多次缓存。对于支持所有区域设置的大型网站,这是对内存的极大浪费

这是一个非常大的内存问题。这里我们讨论的是Freemarker模板缓存中30倍的重复内存缓存

我可能是错的,因为我可能不会触及其他场景,在相同FTL源文件的情况下,当区域设置/编码不同时,这些场景将被缓存为不同的内容。请让我知道这个案子是否存在

我强烈建议FreeMarker designer考虑这个问题,看看是否有任何方法可以提高内存使用率

谢谢


Rocky

是的,如果您传入不同的区域设置,而实际上这些区域设置(如foo_en.ftl、foo_fr.ftl、foo_de.ftl)没有单独的模板版本,这会浪费资源。无可否认,这是需要改进的,我现在是主要的维护者。请注意,如果您的应用程序实际上不支持30个区域设置,那么不要将访问者区域设置传递给getTemplate或类似的东西,如果是这样的话。这种机制只适用于不同地区有不同模板的情况,当然,这些模板必须单独缓存。如果您没有针对不同区域设置的不同模板,那么您应该在环境中设置区域设置(如果有的话)。还要注意的是,如果缓存大小限制足够低,那么这个问题就意味着缓存效率不如内存使用率高

关于如何解决这个问题。。。这不是一个很好的话题,但不管怎样

因此,在工作时,使用不同地区加载的相同模板文件将导致不同的模板对象,因此它们都被加载!并单独缓存。当然,假设每个区域设置没有不同的文件,这些模板对象的内容将是相同的,只是它们的区域设置不同。遗憾的是,我不能仅仅重用模板的解析内容来创建具有不同语言环境设置的相同内容,因为模板中的元素知道它们指向的模板对象。因此,我相信,解决方案是,模板的区域设置不取决于所请求的区域设置,而是取决于模板文件名称末尾的区域设置代码。此行为可以是向后兼容性的配置级别设置。对于每个请求的区域设置,仍然需要一个新的缓存项,因为如果模板查找通常意味着I/O,则需要缓存其结果。

感谢您的回复

另一点是,我们将lcoalelookup设置为false,因此我们没有使用foo_en.ftl、foo_fr.ft、foo_de.ftl这样的文件。在本例中,无论语言环境是什么,一个模板文件都具有相同的内容。目前我们无法更改设计。顺便说一下,templatesource是缓存的,所以它不应该有IO问题

到目前为止,我看到如果我们想减少模板缓存内存,一个解决方案是接管缓存管理,当get cache.putkey,value时,如果localelookup=false,我们可以转换密钥并删除区域设置。当Cache.getkey时,在返回值之前,生成克隆值并更新新模板对象中的区域设置。需要缓存模板,模板级别。问题在于密钥类TemplateKey、CachedTemplate是私有的,并且Template不扩展clonable。是否有机会制作下一个版本补丁来支持客户缓存密钥转换?freemarker中的所有更改都是公开类,但函数没有受到影响

实际上更好的解决方案是:在freemarker内部,如果它有不同的键,比如TemplateKey,TemplateKeyWithOutLocal。创建键对象时,可以根据localelookup设置使用TemplateKey或TemplateKeyWIthoutLocale。返回缓存模板对象时,请进行模板克隆并正确设置区域设置


谢谢。

在Github Master 2.4分支上,我已开始修复此问题。我引入了freemarker.core.UnboundTemplate,它与模板类似,但不绑定到区域设置或任何东西,只绑定到解析的FTL本身和解析器设置。重构已经完成,所以基本的架构问题已经得到解决。现在我可以继续修复尚未完成的缓存。如何添加新的缓存项?@RichElswick获取模板时会自动添加缓存项。