我有一个scala伴侣对象,其方法接受地图作为参数。然后将此映射传递给另一个不同的伴随对象中的另一个函数,而不进行任何更改。当方法执行速度很快时(我测量了一切),实际的方法调用花费了太多时间。如果我没有传递一个map(改为使用null),它的工作速度很快,但是将它作为参数传递,实际的方法调用非常慢。
我是否遗漏了某些内容,并且正在重新创建地图,而不只是传递参考?
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
}
}
答案 0 :(得分:4)
它是通过引用传递的。还有其他事情正在进行 - 你在第一次使用地图时进行测量,这也需要一些类加载(后续调用会快得多),或者当你传递地图时你做了很多工作而不是null
,或者你几乎没有记忆,而是在测量垃圾收集时间。
如果范围内存在隐式转换,则可以复制它,但如果两个地方的类型签名完全相同,那么这不会成为问题,因为“无转换”始终具有优先权。
以下是parse
调用的字节码(content
方法已添加到Asset
,因此会生成Option[ContentElement]
,并添加sub
方法到Node
填写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
请参阅?没有地图复制。 aload_2
是传入的地图。除了通过getAsset
传递给invokevirtual
之外,没有任何其他事情发生。
答案 1 :(得分:1)
所以我试图在一个独立的项目中重现这个并且失败了,它运行正常。但是在一个项目中它很慢,所以显然还有其他事情正在发生。
我最终重构了代码并删除了对象到对象调用。创建了一个通常的类,它接受assetsMap作为构造函数val,现在它的工作速度更快