我有一个 scala 伴随对象,其方法接受映射作为参数。然后将此映射传递给不同伴生对象中的另一个函数,而不进行任何更改。当方法执行速度很快时,实际的方法调用会花费太多时间(我测量了所有内容)。如果我不传递映射(使用 null 代替),它会快速运行,但将其作为参数传递时,实际方法调用会非常慢。
我是否遗漏了一些东西,并且正在重新创建 map ,而不仅仅是传递引用?
object ContentElementParser {
def parse(node: Node, assets: Map[String, Asset]): Option[ContentElement] = {
//Some logic here
AssetParser.getAsset(subNode, assets) //this call is too slow because of assets map
}
}
object AssetParser {
def getAsset(node: Node, assetMap: Map[String, Asset]): Asset = {
//logic
}
}
最佳答案
它是通过引用传递的。还发生了其他事情 - 您正在第一次使用 map 时进行测量,这也需要一些类加载(后续调用会更快),或者当您传递 map 时您会做更多的工作,而不是null
,或者您的内存几乎耗尽,而您正在测量垃圾收集时间。
如果范围内存在隐式转换,则可以复制它,但如果两个位置的类型签名完全相同,则这不会成为问题,因为“无转换”始终具有优先权。
这是 parse
调用的字节码(将 content
方法添加到 Asset
中,因此它会生成 Option[ContentElement ]
,并在 Node
中添加一个 sub
方法来填充 subNode
):
def parse(node: Node, assets: Map[String, Asset]): Option[ContentElement] =
AssetParser.getAsset(node.sub, assets).content
public scala.Option parse(Node, scala.collection.immutable.Map);
Code:
0: getstatic #19; //Field AssetParser$.MODULE$:LAssetParser$;
3: aload_1
4: invokevirtual #25; //Method Node.sub:()LNode;
7: aload_2
8: invokevirtual #29; //Method AssetParser$.getAsset:
(LNode;Lscala/collection/immutable/Map;)LAsset;
11: invokevirtual #35; //Method Asset.content:()Lscala/Some;
14: areturn
看到了吗?没有 map 复制。 aload_2
是传入的 map 。除了通过 invokevirtual
传递到 getAsset
之外,它没有发生任何事情。
关于performance - 将 Scala Map 作为参数传递给函数需要太多时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17821576/