【问题标题】:What is Scala's cheapest type?Scala 最便宜的类型是什么?
【发布时间】:2011-06-21 19:19:38
【问题描述】:

我需要在隐式中使用类型(任何类型)作为类型参数的标记,以将其与另一个隐式区分开来。这很奇怪,但这可能是另一个问题。

因为我可以使用任何类型,所以我考虑使用最便宜的一种,就内存占用初始化时间而言。在这种情况下它可能不会对性能产生太大影响,但问题很有趣:哪个是 Scala 最便宜的类型?

在 Java 中,答案显然是 java.lang.Object。但是 Scala 有一些“有趣”的类型:AnyAnyVal 类型,以及围绕它们可能进行优化的底部类型。 Nothing 类型不能被实例化,所以它被排除在这个比较之外。

【问题讨论】:

  • 有趣,我会说java中最便宜的类型是简单的int。
  • 我不确定这有多“便宜”,但没有什么可以使用:def x(_ : Nothing) = (); x(null.asInstanceOf[Nothing]) 只是不要尝试使用那个 Nothing :-)跨度>
  • 看到一个关于“root”问题的问题也很有趣。
  • @Adrian Fritsch:您需要多少个标记值?只有两个(标记/未标记)?
  • 这听起来像是过早的优化。

标签: scala types


【解决方案1】:

这取决于您的具体问题,但 Scala 或任何语言中最便宜的构造必须是根本不存在的构造......(至少,不是在运行时)

请允许我介绍一下Phantom Types,它允许编译器静态地做正确的事情,但在它们到达 JVM 之前被擦除为虚无。

类似地,您无需任何标记字段即可轻松区分两个不同类型的对象。这是case objects 的一个很好的候选,并且与模式匹配一​​起工作得非常好。

【讨论】:

    【解决方案2】:

    我不确定我理解“最便宜的类型”是什么意思...在 Java 中,内存方面最便宜的数字类型可以是字节,但从性能方面来看,Java 已经过优化以工作与int。事实上,许多(或大多数)语言都经过优化,可以与 int (甚至是数据库引擎)一起使用。 Scala 是 JVM 语言,所以我会说最好使用 int。

    更新:如果问题是关于“标记/未标记”合适的数据类型,我会使用布尔原语。

    如果你在 Scala 中输入 boolean 程序,你实际得到的类型 是scala.Boolean。或者,如果您键入 浮动,你会得到 scala.Float。什么时候 您将 Scala 代码编译为 Java 字节码,然而,Scala 将编译 这些类型转换为 Java 的原始类型 在可能的情况下获得性能 Java 原始类型的好处。

    Nothing 是 Any,它是 Java 中的一种 Object,任何 Object 都比任何原始类型都需要更多的内存

    顺便说一句,使用布尔值作为标记是很自然的,它提高了您的代码可读性(从而支持和理解他人)。就算有别的,更优化我也不会过早优化,会选择boolean。

    【讨论】:

    • byte 在内存中不占用“一个”字节,但它必须对齐,所以是 4/8。例外是字节[]
    • @bestsss:同意,我说的 1 字节大小是错误的(这是根据 javadoc 讲述的 8 位);另一方面,它实际需要多少取决于 JVM 实现(据我所知有开销,也参考stackoverflow.com/questions/229886/…)。一些 JVM 可以将字节类型“处理”为 32 位数字......我根据您的评论更改了答案。谢谢
    【解决方案3】:

    如果您选择AnyAnyVal,那么您传递的任何原语都将被装箱,因此可能会出局。

    AnyRef确实是个不错的选择。

    如果没有进行任何类型参数化,那么“原语”也是不错的选择——例如BooleanInt

    还有Null,这是一个非常有趣的选择,因为它根本不分配任何东西,而且是一个字面量,所以它肯定很快。在不知道你到底在做什么的情况下,我无法判断这是否是有效的选择。

    另一个有趣的选项是java.lang.Integer(使用静态方法valueOf),因为它保证小值的引用相等(您必须检查文档以查看精确范围),这意味着不涉及分配.

    【讨论】:

    • java.lang.Integer 不保证小值的引用相等。表达式new Integer(5) 总是创建一个新的单独实例。您可能正在考虑自动装箱。 Integer i = 5 将始终将相同的对象分配给 i
    【解决方案4】:

    由于 Scala 在 Java 之上运行,我假设相同的答案也适用于 Scala 世界。 Any 类型的 Scala 对象只是某种 Java 对象。

    在 Java 中,我认为像 int、short 或 byte 这样的原始类型会比 Object 便宜,但这些类型可能会在 Scala 中包装/装箱。 (虽然不是 100% 确定这一点。)

    更新

    如果由于某种原因它必须是一个对象而不是原始类型,那么 String 可能是最好的,因为字符串被嵌入在 VM 中。因此,在整个应用程序中通常只有一个对象实例。

    【讨论】:

    • “Scala 编译器在编译代码中尽可能使用 Java 数组、原始类型和本机算术”(来自“Scala 编程”一书)- 似乎它们没有被包装(至少在运行时) )。
    • 不分析代码以避免包装将只是懒惰,懒惰的编码; intern 的字符串容易泄漏,并且不会提高性能
    【解决方案5】:

    Scala 包装原始类型,当您运行包装器的方法调用时,原始类型没有实现。所以即。 1024*512 未包装,但在 1024.toInt*512 中,1024 正在包装。

    【讨论】:

      猜你喜欢
      • 2019-02-28
      • 2011-04-13
      • 2011-04-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-19
      • 2012-02-19
      • 2011-01-21
      相关资源
      最近更新 更多