Skip to content

Instantly share code, notes, and snippets.

@ubourdon
Created July 24, 2015 14:16
Show Gist options
  • Select an option

  • Save ubourdon/f11976e00941d73b32d4 to your computer and use it in GitHub Desktop.

Select an option

Save ubourdon/f11976e00941d73b32d4 to your computer and use it in GitHub Desktop.
extract parts of algo in function produce 5x slower algo
class SpikeTest2 extends FunSuite with Matchers with DurationTestTools {
val boatPrice = Price(1D, false, 20D)
test("classic algo") {
val season = BoatSeason(TODAY.minusDays(150), TODAY.plusDays(150))
val specialPeriod = (0 to 50).map { i => SpecialPricePeriod(TODAY.plusDays(i), TODAY.plusDays(i).plusDays(2), i +1) }.toList
val (time, _) = mesureTimeExecutionOf { ClassicAlgo.buildBookingDaysPrice(boatPrice, season, specialPeriod, TODAY, TODAY.plusDays(5)) }
time shouldBeMinusThan (50 milliseconds)
println(time) // ~43 ms
}
test("with extract function algo") {
val season = BoatSeason(TODAY.minusDays(150), TODAY.plusDays(150))
val specialPeriod = (0 to 50).map { i => SpecialPricePeriod(TODAY.plusDays(i), TODAY.plusDays(i).plusDays(2), i +1) }.toList
val (time, _) = mesureTimeExecutionOf { ExtractAlgo.buildBookingDaysPrice(boatPrice, season, specialPeriod, TODAY, TODAY.plusDays(5)) }
println(time)
time shouldBeMinusThan (50 milliseconds) // ~280 ms
}
}
object ClassicAlgo {
val ZERO = BookingDaysPrice(0D, 0D)
def buildBookingDaysPrice(boatPrice: Price,
season: BoatSeason,
specialPeriods: List[SpecialPricePeriod],
bookingStartDate: DateTime,
bookingEndDate: DateTime): BookingDaysPrice = {
val seasonDays = extractDaysFromPeriod(season.startDate, season.endDate)
val specialPeriodDays = specialPeriods.map { spe => (extractDaysFromPeriod(spe.startDate, spe.endDate), spe.price) }
val availableDaysPrice: Set[(LocalDate, Price)] = seasonDays.map { day =>
val price = specialPeriodDays
.collectFirst { case (speDays, price) if (speDays.contains(day)) => Price(price, boatPrice.inc_vat, boatPrice.vat_value) }
.getOrElse(boatPrice)
(day, price)
}
val bookingDays = extractDaysFromPeriod(bookingStartDate, bookingEndDate)
bookingDays.foldLeft(ZERO) { (acc, day) =>
val price = availableDaysPrice
.collectFirst { case (availableDay, price) if(availableDay === day) => price }
.getOrElse(boatPrice)
addBookingPrice(acc, toBookingDaysPrice(price))
}
}
private def addBookingPrice(p1: BookingDaysPrice, p2: BookingDaysPrice): BookingDaysPrice =
BookingDaysPrice(p1.withVAT + p2.withVAT, p1.withoutVAT + p2.withoutVAT)
private def toBookingDaysPrice(price: Price): BookingDaysPrice = BookingDaysPrice(price.withVAT, price.withoutVAT)
}
object ExtractAlgo {
val ZERO = BookingDaysPrice(0D, 0D)
def buildBookingDaysPrice2(boatPrice: Price,
season: BoatSeason,
specialPeriods: List[SpecialPricePeriod],
bookingStartDate: DateTime,
bookingEndDate: DateTime): BookingDaysPrice =
extractDaysFromPeriod(bookingStartDate, bookingEndDate).foldLeft(ZERO) { (acc, bookingDay) =>
val bookingPrice = bookingDay |> calculBookingPrice(season, specialPeriods, boatPrice) |> toBookingDaysPrice
addBookingPrice(acc, bookingPrice)
}
private def calculBookingPrice(season: BoatSeason, specialPeriods: List[SpecialPricePeriod], boatPrice: Price)
(bookingDay: LocalDate): Price =
availableDaysWithPrice(seasonDays, specialPeriodDays)(season, specialPeriods, boatPrice)
.collectFirst { case (availableDay, price) if(availableDay === bookingDay) => price }
.getOrElse(boatPrice)
private def seasonDays: BoatSeason => Set[LocalDate] = season => extractDaysFromPeriod(season.startDate, season.endDate)
private def specialPeriodDays: List[SpecialPricePeriod] => List[(Set[LocalDate], Double)] = specialPeriods =>
specialPeriods.map { spe => (extractDaysFromPeriod(spe.startDate, spe.endDate), spe.price) }
private def availableDaysWithPrice(f: BoatSeason => Set[LocalDate],
g: List[SpecialPricePeriod] => List[(Set[LocalDate], Double)])
(season: BoatSeason, specialPeriods: List[SpecialPricePeriod], boatPrice: Price): Set[(LocalDate, Price)] =
f(season).map { seasonDay =>
val price = g(specialPeriods)
.collectFirst { case (speDays, price) if(speDays.contains(seasonDay)) => Price(price, boatPrice.inc_vat, boatPrice.vat_value) }
.getOrElse(boatPrice)
(seasonDay, price)
}
private def addBookingPrice(p1: BookingDaysPrice, p2: BookingDaysPrice): BookingDaysPrice =
BookingDaysPrice(p1.withVAT + p2.withVAT, p1.withoutVAT + p2.withoutVAT)
private def toBookingDaysPrice(price: Price): BookingDaysPrice = BookingDaysPrice(price.withVAT, price.withoutVAT)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment