IResourceScopeCache 用于避免昂贵的范围计算 [英] IResourceScopeCache for Avoid expensive scope calculation

查看:17
本文介绍了IResourceScopeCache 用于避免昂贵的范围计算的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了同样的问题,描述了是这个链接吗

我想在我实现的 getScope 函数中使用 IResourceScopeCache,但我不知道该怎么做.没有找到任何对我有帮助的东西.我有这个文件:MyDslScopeProvider.xtend,我在那里覆盖了 getScope().我如何使用那里的缓存?

override def IScope getScope(EObject context, EReference reference) {如果(参考 == SpectraPackage.Literals.TEMPORAL_PRIMARY_EXPR__POINTER){val contextDecl = EcoreUtil2.getContainerOfType(context, Decl);val root = EcoreUtil2.getContainerOfType(context, Model)val 元素 = root.elementsval ListEObjectsInScope = newArrayListif (contextDecl instanceof Predicate) {val pred = contextDecl 作为谓词EObjectsInScope.addAll(pred.params.params)EObjectsInScope.addAll(consts)EObjectsInScope.addAll(varDecls)返回 Scopes.scopeFor(EObjectsInScope)}else if (contextDecl instanceof Pattern) {val patt = contextDecl 作为模式EObjectsInScope.addAll(patt.varDeclList)EObjectsInScope.addAll(patt.params.params)返回 Scopes.scopeFor(EObjectsInScope)}别的{//获取我需要的所有元素.(这里没有添加,因为代码很多)返回 Scopes.scopeFor(EObjectsInScope)}返回 Scopes.scopeFor(EObjectsInScope)}}返回 super.getScope(context, reference);}

我有 3 个不同的案例.

解决方案

IResourceScopeCache 接口允许使用您选择的键在映射中存储为给定资源计算的值.它有两种方法: T get(Object key, Resource res, Provider provider)void clear(Resource res).get 检查是否已经为给定的键和资源计算了一个值.如果它已经存在,则返回缓存的值,否则使用提供程序计算该值,然后将其存储在缓存中以供后续重用.clear 删除给定键的计算值(如果存在).

您必须注入一个 IResourceScopeCache 类型的字段,并考虑从上下文 EObject 生成缓存键的方案:

您必须确保每当您检索给定缓存键和资源的值时,如果实际执行计算,缓存计算 (provider) 的结果将是相同的,因此重新使用缓存的值是正确的.特别是,您必须确保计算结果仅取决于您传递给 get 方法的资源的内容,因为只有在更改该资源时才会重新计算缓存值.

但是,在执行此操作时,您必须确保没有不必要的不​​同缓存键,而这些键的计算结果必然相同,以最大程度地重复使用并最小化重复计算.

从您论坛帖子中的代码示例中,我看不到非常适合缓存的候选者.但也许我从这个例子中看不到一些东西.

局部变量不是缓存的最佳候选者,至少有两个原因:

  1. 块和语句没有可用于缓存键的名称.
  2. 即使您这样做,局部变量也只能在声明后的表达式/语句中使用,因此每个语句可能有一组不同的可用局部变量.这使得通过合理的努力实现合理的重用量变得更加困难.

如果您无论如何都想这样做,也许您可​​以使用语句在包含层次结构中的位置来计算缓存键,类似于代理 URI 片段(参见 org.eclipse.xtext.linking.lazy.LazyURIEncoder),但不是使用字符串,并重用前面语句的计算值(并包含块的第一个语句的块).

I have the same problem that described is this link

I want to use IResourceScopeCache in my getScope function I implemented, but I don't know how to do it. Didn't found anything that helped me. I have this file: MyDslScopeProvider.xtend that I override getScope() there. How can I use the cache there?

override def IScope getScope(EObject context, EReference reference) {

    if (reference == SpectraPackage.Literals.TEMPORAL_PRIMARY_EXPR__POINTER) {
        val contextDecl = EcoreUtil2.getContainerOfType(context, Decl);
        val root = EcoreUtil2.getContainerOfType(context, Model)
        val elements = root.elements

        val List<EObject> EObjectsInScope = newArrayList

        if (contextDecl instanceof Predicate) {
            val pred = contextDecl as Predicate
            EObjectsInScope.addAll(pred.params.params)
            EObjectsInScope.addAll(consts)
            EObjectsInScope.addAll(varDecls)
            return Scopes.scopeFor(EObjectsInScope)

        }

         else if (contextDecl instanceof Pattern) {
            val patt = contextDecl as Pattern
            EObjectsInScope.addAll(patt.varDeclList)
            EObjectsInScope.addAll(patt.params.params)
            return Scopes.scopeFor(EObjectsInScope)

        }
        else{

            //geting all the elements I need.(didn't added it here because it's a lot of code)
            return Scopes.scopeFor(EObjectsInScope)
    }
    return Scopes.scopeFor(EObjectsInScope)

  }
}

    return super.getScope(context, reference);

}

I have 3 different cases.

解决方案

The interface IResourceScopeCache allows to store values computed for a given resource in a map using keys of your choice. It has two methods: <T> T get(Object key, Resource res, Provider<T> provider) and void clear(Resource res). get checks whether a value was already computed for the given key and resource. If it is already present, the cached value is returned, and otherwise the provider is used to calculate the value, which then is stored in the cache for subsequent re-use. clear removes the computed value for the given key, if present.

You have to inject a field of type IResourceScopeCache and think about a scheme to generate cache keys from the context EObject:

You have to make sure that whenever you retrieve the value for a given cache key and resource, the results of the cache computation (provider) would be identical if the computation was actually performed, so it is correct to re-use the cached values. Especially, you have to make sure that the result of the computation depends only on the contents of the resource you pass to the get method because the cached values are only re-computed when that resource is changed.

However, while doing that, you have to make sure that you don't unnecessarily have different cache keys where the computation results are bound to be identical, in order to maximize re-use and minimize duplicate computations.

From the code example in your forum post I cannot see very good candidates for caching. But maybe there is something I can't see from the example.

Local variables are not the best candidates for caching for at least two reasons:

  1. Blocks and statements don't have names you could use for cache keys.
  2. Even if you do that, local variables are only available for use in expressions/statements after their declaration, so every statement might have a different set of available local variables. This makes it harder to achieve a reasonable amount of reuse with a reasonable amount of effort.

If you want to do it anyway, maybe you could calculate cache keys using the statements' position in the containment hierarchy, similar to proxy URI fragments (cf. org.eclipse.xtext.linking.lazy.LazyURIEncoder), but not using strings, and re-use the computed valued of the preceding statements (and containing blocks for the first statement of a block).

这篇关于IResourceScopeCache 用于避免昂贵的范围计算的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆