关于 DLR 调用站点缓存的一些问题

发布于 2024-10-10 23:14:34 字数 1082 浏览 5 评论 0原文

如果我对 DLR 操作解析方法的理解是错误的,请纠正我

DLR 有一个称为调用站点缓存的东西。给定“a+b”(其中 a 和 b 都是整数),第一次它将无法理解 +(加)运算符以及操作数。因此,它将解析操作数,然后解析运算符,并在构建适当的规则后缓存在第 1 级。

下次以后,如果找到类似的匹配(其中操作数是整数类型,运算符是 + 类型),它将查找缓存并返回结果,从此性能将得到增强。

如果我的这种理解是正确的(如果您认为我的基本理解不正确,请纠正),我有以下问题正在寻找答案

    a) What kind of operations happen in level 1 , level 2 
    and level 3 call site caching in general
     ( i mean plus, minus..what kind)

    b) DLR caches those results. Where it stores..i mean the cache location

    c) How it makes the rules.. any algorithm.. if so could you please specify(any link or your own answer)

    d) Sometime back i read somewhere that in level 1 caching , DLR has 10 rules,
 level 2 it has 20 or something(may be) while level 3 has 100. 
If a new operation comes, then I makes a new rule. Are these rules(level 1 , 2 ,3) predefined?

    e) Where these rules are kept?

    f) Instead of passing two integers (a and b in the example), 
        if we pass two strings or one string and one integer, 
       whether it will form a new rule?

谢谢

Kindly correct me if my understanding about DLR operation resolving methodology is wrong

DLR has something call as call site caching. Given "a+b" (where a and b are both integers), the first time it will not be able to understand the +(plus) operator as wellas the operand. So it will resolve the operands and then the operators and will cache in level 1 after building a proper rule.

Next time onwards, if a similar kind of match is found (where the operand are of type integers and operator is of type +), it will look into the cache and will return the result and henceforth the performance will be enhanced.

If this understanding of mine is correct(if you fell that I am incorrect in the basic understanding kindly rectify that), I have the below questions for which I am looking answers

    a) What kind of operations happen in level 1 , level 2 
    and level 3 call site caching in general
     ( i mean plus, minus..what kind)

    b) DLR caches those results. Where it stores..i mean the cache location

    c) How it makes the rules.. any algorithm.. if so could you please specify(any link or your own answer)

    d) Sometime back i read somewhere that in level 1 caching , DLR has 10 rules,
 level 2 it has 20 or something(may be) while level 3 has 100. 
If a new operation comes, then I makes a new rule. Are these rules(level 1 , 2 ,3) predefined?

    e) Where these rules are kept?

    f) Instead of passing two integers (a and b in the example), 
        if we pass two strings or one string and one integer, 
       whether it will form a new rule?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

み青杉依旧 2024-10-17 23:14:34

a)如果我正确理解这一点,目前所有级别的工作方式都是相同的 - 他们运行一个委托来测试对规则重要的参数,然后执行操作或记录失败(通过设置一个值来记录失败在调用站点上或对更新方法进行尾调用)。因此,每条规则的工作原理如下:

   public object Rule(object x, object y) {
       if(x is int && y is int) {
             return (int)x + (int)y;
       }
       CallSiteOps.SetNotMatched(site);
       return null;
    }

并且该方法的委托用于 L0、L1 和 L2 缓存。但这里的行为可能会改变(并且在开发过程中确实改变了很多次)。例如,在某个时间点,L2 缓存是一棵基于参数类型的树。

b) L0 缓存和L1 缓存存储在CallSite 对象上。 L0 缓存是一个单一委托,它始终是第一个运行的东西。最初,这被设置为仅第一次更新站点的委托。其他调用尝试执行调用站点看到的最后一个操作。

L1 缓存包含调用站点看到的最后 10 个操作。如果 L0 缓存失败,将尝试 L1 缓存中的所有委托。

L2 缓存位于 CallSiteBinder 上。 CallSiteBinder 应该在多个调用站点之间共享。例如,通常应该有且只有一个附加项(假设所有附加项都相同),用于该语言的调用站点绑定器。如果是L0和L1,则L2缓存中的所有可用规则都会被搜索。目前L2缓存的上限是128。

c) 规则最终可以通过两种方式产生。一般解决方案是创建一个 DynamicMetaObject,其中包括要执行的操作的表达式树以及确定其是否适用的限制(测试)。这类似于:

public DynamicMetaObject FallbackBinaryOperation(DynamicMetaObject target, DynamicMetaObject arg) {
  return new DynamicMetaObject(
       Expression.Add(Expression.Convert(target, typeof(int)), Expression.Convert(arg, typeof(int))),
       BindingRestrictions.GetTypeRestriction(target, typeof(int)).Merge(
           BindingRestrictions.GetTypeRestriction(arg,  typeof(int))
       )
  );
}

这创建了将两个整数相加的规则。这实际上并不正确,因为如果你得到整数以外的东西,它会无限循环 - 所以通常你会做一堆类型检查,为你可以处理的东西生成加法,然后如果你不能处理则产生一个错误处理添加。

另一种制定规则的方法是直接提供委托。这是更先进的,可以进行一些高级优化,以避免一直编译代码。为此,您需要重写 CallSiteBinder 上的 BindDelegate,检查参数,并提供一个类似于我在上面键入的 Rule 方法的委托。

d) 在 b)

e) 中回答,我相信这与 b) f) 是同一个问题,

如果您对其施加适当的限制,那么是的(您被迫对标准活页夹执行此操作)。因为限制将会失败,因为您没有两个整数,DLR 将探测缓存,当它找不到规则时,它将调用绑定器来生成新规则。该新规则将带有一组新的限制返回,将安装在 L0、L1 和 L2 缓存中,然后将从那时起对字符串执行操作。

a) If I understand this correctly currently all of the levels work effectively the same - they run a delegate which tests the arguments which matter for the rule and then either performs an operation or notes the failure (the failure is noted by either setting a value on the call site or doing a tail call to the update method). Therefore every rule works like:

   public object Rule(object x, object y) {
       if(x is int && y is int) {
             return (int)x + (int)y;
       }
       CallSiteOps.SetNotMatched(site);
       return null;
    }

And a delegate to this method is used in the L0, L1, and L2 caches. But the behavior here could change (and did change many times during development). For example at one point in time the L2 cache was a tree based upon the type of the arguments.

b) The L0 cache and the L1 caches are stored on the CallSite object. The L0 cache is a single delegate which is always the 1st thing to run. Initially this is set to a delegate which just updates the site for the 1st time. Additional calls attempt to perform the last operation the call site saw.

The L1 cache includes the last 10 actions the call site saw. If the L0 cache fails all the delegates in the L1 cache will be tried.

The L2 cache lives on the CallSiteBinder. The CallSiteBinder should be shared across multiple call sites. For example there should generally be one and only one additiona call site binder for the language assuming all additions are the same. If the L0 and L1 all of the available rules in the L2 cache will be searched. Currently the upper limit for the L2 cache is 128.

c) Rules can ultimately be produced in 2 ways. The general solution is to create a DynamicMetaObject which includes both the expression tree of the operation to be performed as well as the restrictions (the test) which determines if it's applicable. This is something like:

public DynamicMetaObject FallbackBinaryOperation(DynamicMetaObject target, DynamicMetaObject arg) {
  return new DynamicMetaObject(
       Expression.Add(Expression.Convert(target, typeof(int)), Expression.Convert(arg, typeof(int))),
       BindingRestrictions.GetTypeRestriction(target, typeof(int)).Merge(
           BindingRestrictions.GetTypeRestriction(arg,  typeof(int))
       )
  );
}

This creates the rule which adds two integers. This isn't really correct because if you get something other than integers it'll loop infinitely - so usually you do a bunch of type checks, produce the addition for the things you can handle, and then produce an error if you can't handle the addition.

The other way to make a rule is provide the delegate directly. This is more advanced and enables some advanced optimizations to avoid compiling code all of the time. To do this you override BindDelegate on CallSiteBinder, inspect the arguments, and provide a delegate which looks like the Rule method I typed above.

d) Answered in b)

e) I believe this is the same question as b)

f) If you put the appropriate restrictions on then yes (which you're forced to do for the standard binders). Because the restrictions will fail because you don't have two ints the DLR will probe the caches and when it doesn't find a rule it'll call the binder to produce a new rule. That new rule will come back w/ a new set of restrictions, will be installed in the L0, L1, and L2 caches, and then will perform the operation for strings from then on out.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文