我想知道Dalvik中包装的开关和稀疏开关Opcodes之间的区别。如果您可以提供示例,请。 Google提供的解释对我来说尚不清楚。

包装开关 稀疏开关

谢谢。

有帮助吗?

解决方案

听起来好像 packed-switch 等同于爪哇 tableswitch, , 和 sparse-switchlookupswitch.

一个 packed-switch 使用一个简单的跳台,由表单索引 low + n, , 在哪里 low 是最低的测试值 case 标签,和 n 是输入 switch. 。每个索引上的值代表每个intecode偏移 case. 。找到正确的跳跃地址是一个恒定的时间操作。

一个 sparse-switch 使用键值对的排序列表,其中每个键是来自一个的测试值 case 标签,值是跳跃偏移。找到正确的跳跃目标 lookupswitch 需要在密钥上进行二进制搜索,因此它是对数时间操作。

编译器将选择要使用的。如果键倾向于聚集或 包装 紧密合在一起,然后 packed-switch (或者,用爪哇术语 tableswitch)可以有效地发射。但是如果钥匙是 , ,以及值的范围(high - low + 1)很大,然后使用跳台需要大量的字节码,因为该范围内的所有值必须在跳台中都存在,无论是否有相应的 case 标签。在这些情况下,编译器将发出 sparse-switch (lookupswitch).

有趣的是,Dalvik工程师选择以描述应使用的关键分布的方式命名这些Opcodes,而Java工程师选择了描述字节码操作数相似的概念数据结构的名称。

让我们看一些例子。考虑以下Java代码,该代码将产生一个 tableswitch (并且,当转换为Dalvik时 packed-switch):

static String packedSwitch(final int n) {
    switch (n) {
        case 5:
            return "Five";
        case 3:
            return "Three";
        case 1:
            return "One";
        default:
            return "Other";
    }
}

从概念上讲,有效载荷 packed-switch OpCode看起来像这样:

actual packed-switch

如您所见,它相当紧凑。五个插槽中有三个指向实际 case 目标,其余两个跳到 default 目标。但是,如果我们的测试值更加分布怎么办?

static String sparseSwitch(final int n) {
    switch (n) {
        case 500:
            return "Five Hundred";
        case 300:
            return "Three Hundred";
        case 100:
            return "One Hundred";
        default:
            return "Other";
    }
}

如果编译器试图将其作为一个 packed-switch, ,有效载荷看起来像这样:

theoretical packed-switch

请注意,几百个插槽中只有三个指向 case 来自原始代码的标签。其余的只是为了填写跳台。不是很高效,是吗?这就是为什么编译器会发出 sparse-switch, ,在此特定示例中具有更紧凑的字节码足迹:

sparse-switch

现在,这更合理,您不觉得吗?但是,不利的一面是,我们不必确切地知道要根据输入跳到哪个索引,而是必须在表上执行二进制搜索,直到找到匹配的测试值。开关越大,对性能的影响越大,尽管效果具有对数曲线。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top