首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Scala如何缩短执行时间

Scala如何缩短执行时间
EN

Stack Overflow用户
提问于 2018-04-09 17:38:21
回答 3查看 250关注 0票数 0

我有一个生成UUID和代码的方法,如下所示:

代码语言:javascript
复制
def generate(number : Int): List[String] = {
List.fill(number)(Generators.randomBasedGenerator().generate().toString.replaceAll("-",""))
}

我称之为:

代码语言:javascript
复制
for(i <-0 to 100) {
  val a = generate(1000000)
  println(a)
}

但是对于运行上面的for循环,执行几乎需要8-9分钟,还有其他方法来最小化执行时间吗?

注意:为了理解我添加了for循环,这里的,但是在实际情况下,generate方法将从其他请求同时调用上千次。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-04-10 06:41:21

基本上,您使用的不是最快的实现。当您将随机传递给构造函数Generators.randomBasedGenerator(new Random(System.currentTimeMillis()))时,应该使用该方法。我做了接下来的事:

  • 使用数组而不是列表(Array更快)
  • 删除字符串替换,让我们来测量生成的纯性能

依赖关系:"com.fasterxml.uuid" % "java-uuid-generator" % "3.1.5"

结果:

代码语言:javascript
复制
Generators.randomBasedGenerator(). Per iteration: 1579.6 ms
Generators.randomBasedGenerator() with passing Random Per iteration: 59.2 ms

代码:

代码语言:javascript
复制
import java.util.{Random, UUID}
import com.fasterxml.uuid.impl.RandomBasedGenerator
import com.fasterxml.uuid.{Generators, NoArgGenerator}
import org.scalatest.{FunSuiteLike, Matchers}

import scala.concurrent.duration.Deadline

class GeneratorTest extends FunSuiteLike
  with Matchers {

  val nTimes = 10

  // Let use Array instead of List - Array is faster!
  // and use pure UUID generators
  def generate(uuidGen: NoArgGenerator, number: Int): Seq[UUID] = {
    Array.fill(number)(uuidGen.generate())
  }

  test("Generators.randomBasedGenerator() without passed Random (secure one)") {
    // Slow generator
    val uuidGen = Generators.randomBasedGenerator()
    // Warm up JVM
    benchGeneration(uuidGen, 3)

    val startTime = Deadline.now
    benchGeneration(uuidGen, nTimes)
    val endTime = Deadline.now
    val perItermTimeMs = (endTime - startTime).toMillis / nTimes.toDouble
    println(s"Generators.randomBasedGenerator(). Per iteration: $perItermTimeMs ms")
  }

  test("Generators.randomBasedGenerator() with passing Random (not secure)") {
    // Fast generator
    val uuidGen = Generators.randomBasedGenerator(new Random(System.currentTimeMillis()))
    // Warm up JVM
    benchGeneration(uuidGen, 3)    

    val startTime = Deadline.now
    benchGeneration(uuidGen, nTimes)
    val endTime = Deadline.now
    val perItermTimeMs = (endTime - startTime).toMillis / nTimes.toDouble
    println(s"Generators.randomBasedGenerator() with passing Random Per iteration: $perItermTimeMs ms")
  }

  private def benchGeneration(uuidGen: RandomBasedGenerator, nTimes: Int) = {
    var r: Long = 0
    for (i <- 1 to nTimes) {
      val a = generate(uuidGen, 1000000)
      r += a.length
    }
    println(r)
  }
}
票数 1
EN

Stack Overflow用户

发布于 2018-04-09 19:41:01

问题是List。用1,000,000个生成和处理的元素填充List需要时间(和内存),因为这些元素中的每一个都必须物化。

如果您不必在实际需要之前实现UUID字符串,则可以立即生成无限数量的处理UUID字符串。

代码语言:javascript
复制
def genUUID :Stream[String] = Stream.continually {
  Generators.randomBasedGenerator().generate().toString.filterNot(_ == '-')
}

val next5 = genUUID.take(5) //only the 1st (head) is materialized
next5.length                //now all 5 are materialized

您可以对无限集合使用StreamIterator,无论您认为对工作流程最有利(或最不烦人)。

票数 2
EN

Stack Overflow用户

发布于 2018-04-09 18:48:40

您可以使用scala的并行集合在多个核心/线程上拆分负载。

您还可以避免每次创建一个新生成器:

代码语言:javascript
复制
class Generator {
  val gen = Generators.randomBasedGenerator()
  def generate(number : Int): List[String] = {
    List.fill(number)(gen.generate().toString.replaceAll("-",""))
  }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49738619

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档