2

我有一个带有接受地图作为参数的方法的 scala 伴随对象。然后 in 将此映射传递给不同伴生对象中的另一个函数,而无需更改。当方法执行速度很快(我测量了一切)时,实际的方法调用会花费太多时间。如果我不传递一个映射(使用 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
    }
}
4

2 回答 2

4

它是通过引用传递的。其他事情正在发生-您在第一次使用地图时进行测量,这也需要一些类加载(后续调用会快得多),或者当您传递地图时您正在做更多的工作而不是null,或者您几乎没有内存并且您正在测量垃圾收集时间。

如果范围内存在隐式转换,则可以复制它,但是如果两个地方的类型签名完全相同,那将不是问题,因为“无转换”始终具有优先权。

这是parse调用的字节码(content添加了一个方法,Asset因此它产生一个Option[ContentElement],并sub添加了一个方法Node来填充 for 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是传入的地图。除了传递给getAssetvia之外,它没有任何反应invokevirtual

于 2013-07-23T21:47:54.707 回答
1

所以我试图在一个独立的项目中重现它并失败了,它工作正常。但是在一个项目中它很慢,所以显然发生了其他事情。

我最终重构了代码并摆脱了对象对对象的调用。创建了一个接受 assetsMap 作为构造函数 val 的常用类,现在它的工作速度更快

于 2013-07-24T18:46:43.930 回答