为什么使用广播增加时间?

时间:2016-08-30 07:28:11

标签: scala apache-spark

这是伪代码:

case class IpDB(startIp: Long, endIp: Long, company: String)
def ipMap(line: Array[String]):
    val Array(startIp, endIp, company) = line
    IpDB(startIp.toLong, endIp.toLong, company)
// The ip-db is just 300M in raw format.
// format of ip-data from s3:
// 100000 200000 GOOGLE
val ipData = sc.broadcast(sc.textFile("s3://....").map(_.split("\t", -1)).map(ipMap).collect().sortWith(_.startIp < _.startIp)).value

val dataA = sc.textFile("s3://...").map((ip, 1)).reduceByKey(_+_)
val dataB = sc.textFile("s3://...").map((ip, 1)).reduceByKey(_+_)

// will do ip company lookup here
dataA.fullOuterJoin(dataB).map(doIpCompanyLookUp(ipData, _)).collect()

代码只是从输入源获取ip数据,然后在加入后找到它的公司。 这是我的问题:

此代码将在生产中运行2-3分钟,但在删除广播数据时(只需加入两个数据),只花费不到1分钟。当我看到火花的ui时,我发现了gc时间可能是问题。

以下是运行此作业的设置:

spark-submit --master yarn --deploy-mode client --driver-memory 4g --num-executors 10 --executor-memory 8800m --executor-cores 4 --class ... XX.jar 

此作业在aws emr spark cluster

上运行
spark version: 1.6.1
10 m3.xlarge.
  1. 如何解决这个问题(减少运行时间)?
  2. 广播数据在spark中占用哪个内存?
  3. 为什么更改执行程序内存时运行时间不会改变?我尝试使用5 * m3.2xlarge和--executor-memory 16g,广播数据的总运行时间没有显着变化。
  4. 更新

    case class IpDB(startIp: Long, endIp: Long, company: String)
    def ipMap(line: Array[String]):
        val Array(startIp, endIp, company) = line
        IpDB(startIp.toLong, endIp.toLong, company)
    // The ip-db is just 300M in raw format.
    // format of ip-data from s3:
    // 100000 200000 GOOGLE
    val dataA = sc.textFile("s3://...").map((ip, 1)).reduceByKey(_+_)
    val dataB = sc.textFile("s3://...").map((ip, 1)).reduceByKey(_+_)
    
    // will do ip company lookup here
    val joinResult = dataA.fullOuterJoin(dataB)
    val ipData = sc.broadcast(sc.textFile("s3://....").map(_.split("\t", -1)).map(ipMap).collect().sortWith(_.startIp < _.startIp)).value
    joinResult.map(doIpCompanyLookUp(ipData, _)).collect()
    

    dataA.fullOuterJoin(dataB)之后移动ip公司数据的生成和广播。运行时间减少了很多。

    UPDATE2。 由于生产代码非常复杂,与上面的伪代码不同,在代码顺序稍有变化后,程序运行得更快,但我不确定问题的关键是初始化数据的位置。

1 个答案:

答案 0 :(得分:0)

没有太多考虑你的代码:

val ipData = sc.broadcast(sc.textFile("s3://....").map(_.split("\t", -1)).map(ipMap).collect().sortWith(_.startIp < _.startIp)).value

让我很担心。

您正在使用sc.textFile构建分布式RDD,只是通过collect()将其设置为本地(驱动程序),然后再次分发,并由sc.broadcast提供给执行程序( !)正如您所看到的,有很多来回发送数据。

你最好cache IP数据,以便它保留在内存中,但这样做:

sc.textFile("s3://....").map(_.split("\t", -1)).map(ipMap).cache