将Scala Map作为参数传递给函数需要花费太多时间

时间:2013-07-23 21:42:45

标签: performance function scala map arguments

我有一个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
    }
}

2 个答案:

答案 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,现在它的工作速度更快