Instantly share code, notes, and snippets.

@rkmathi /list calcStatus Secret
Created Nov 25, 2017

Embed
What would you like to do?
18:28
(pprof) list calcStatus
Total: 1.42mins
ROUTINE ======================== main.calcStatus in /home/isucon/isucon7-final/webapp/go/src/app/game.go
440ms 1.15mins (flat, cum) 81.24% of Total
. . 441:}
. . 442:
. . 443:func calcStatus(currentTime int64, mItems map[int]mItem, addings []Adding, buyings []Buying) (*GameStatus, error) {
. . 444: var (
. . 445: // 1ミリ秒に生産できる椅子の単位をミリ椅子とする
. 20ms 446: totalMilliIsu = big.NewInt(0)
. 10ms 447: totalPower = big.NewInt(0)
. . 448:
. 10ms 449: itemPower = map[int]*big.Int{} // ItemID => Power
. 10ms 450: itemPrice = map[int]*big.Int{} // ItemID => Price
. . 451: itemPrice1000 = map[int]*big.Int{} // ItemID => Price * 1000
. . 452: itemOnSale = map[int]int64{} // ItemID => OnSale
. . 453: itemBuilt = map[int]int{} // ItemID => BuiltCount
. . 454: itemBought = map[int]int{} // ItemID => CountBought
. 20ms 455: itemBuilding = map[int][]Building{} // ItemID => Buildings
. . 456: itemPower0 = map[int]Exponential{} // ItemID => currentTime における Power
. . 457: itemBuilt0 = map[int]int{} // ItemID => currentTime における BuiltCount
. . 458:
. . 459: addingAt = map[int64]Adding{} // Time => currentTime より先の Adding
. . 460: buyingAt = map[int64][]Buying{} // Time => currentTime より先の Buying
. . 461: )
. . 462:
. . 463: for itemID := range mItems {
. 20ms 464: itemPower[itemID] = big.NewInt(0)
. 30ms 465: itemBuilding[itemID] = []Building{}
. . 466: }
. . 467:
20ms 90ms 468: for _, a := range addings {
. . 469: // adding は adding.time に isu を増加させる
20ms 20ms 470: if a.Time <= currentTime {
20ms 4.80s 471: totalMilliIsu.Add(totalMilliIsu, new(big.Int).Mul(str2big(a.Isu), big1000))
. . 472: } else {
. 70ms 473: addingAt[a.Time] = a
. . 474: }
. . 475: }
. . 476:
10ms 20ms 477: for _, b := range buyings {
. . 478: // buying は 即座に isu を消費し buying.time からアイテムの効果を発揮する
. 30ms 479: itemBought[b.ItemID]++
. . 480: m := mItems[b.ItemID]
. 300ms 481: totalMilliIsu.Sub(totalMilliIsu, new(big.Int).Mul(m.GetPrice(b.Ordinal), big1000))
. . 482:
. . 483: if b.Time <= currentTime {
10ms 20ms 484: itemBuilt[b.ItemID]++
. 50ms 485: power := m.GetPower(itemBought[b.ItemID])
10ms 410ms 486: totalMilliIsu.Add(totalMilliIsu, new(big.Int).Mul(power, big.NewInt(currentTime-b.Time)))
. 120ms 487: totalPower.Add(totalPower, power)
10ms 110ms 488: itemPower[b.ItemID].Add(itemPower[b.ItemID], power)
. . 489: } else {
. . 490: buyingAt[b.Time] = append(buyingAt[b.Time], b)
. . 491: }
. . 492: }
. . 493:
. 20ms 494: totalMilliIsuDiv1000 := new(big.Int).Div(totalMilliIsu, big1000)
. 10ms 495: for _, m := range mItems {
. 4.11s 496: itemPower0[m.ItemID] = big2exp(itemPower[m.ItemID])
. 30ms 497: itemBuilt0[m.ItemID] = itemBuilt[m.ItemID]
. 10ms 498: price := m.GetPrice(itemBought[m.ItemID] + 1)
. 10ms 499: itemPrice[m.ItemID] = price
. 120ms 500: itemPrice1000[m.ItemID] = new(big.Int).Mul(price, big1000)
. . 501: if 0 <= totalMilliIsuDiv1000.Cmp(price) {
. . 502: itemOnSale[m.ItemID] = 0 // 0 は 時刻 currentTime で購入可能であることを表す
. . 503: }
. . 504: }
. . 505:
. . 506: schedule := []Schedule{
. . 507: Schedule{
. . 508: Time: currentTime,
. 3.79s 509: MilliIsu: big2exp(totalMilliIsu),
. 3.68s 510: TotalPower: big2exp(totalPower),
. . 511: },
. . 512: }
. . 513:
. . 514: // currentTime から 1000 ミリ秒先までシミュレーションする
40ms 40ms 515: for t := currentTime + 1; t <= currentTime+1000; t++ {
. 1.49s 516: totalMilliIsu.Add(totalMilliIsu, totalPower)
. . 517: updated := false
. . 518:
. . 519: // 時刻 t で発生する adding を計算する
40ms 230ms 520: if a, ok := addingAt[t]; ok {
. . 521: updated = true
. 240ms 522: totalMilliIsu.Add(totalMilliIsu, new(big.Int).Mul(str2big(a.Isu), big1000))
. . 523: }
. . 524:
. . 525: // 時刻 t で発生する buying を計算する
10ms 100ms 526: if _, ok := buyingAt[t]; ok {
. . 527: updated = true
. 20ms 528: updatedID := map[int]bool{}
. . 529: for _, b := range buyingAt[t] {
. . 530: m := mItems[b.ItemID]
. 20ms 531: updatedID[b.ItemID] = true
. . 532: itemBuilt[b.ItemID]++
. . 533: power := m.GetPower(b.Ordinal)
. . 534: itemPower[b.ItemID].Add(itemPower[b.ItemID], power)
. . 535: totalPower.Add(totalPower, power)
. . 536: }
. 20ms 537: for id := range updatedID {
. . 538: itemBuilding[id] = append(itemBuilding[id], Building{
. . 539: Time: t,
. . 540: CountBuilt: itemBuilt[id],
. 1.11s 541: Power: big2exp(itemPower[id]),
. . 542: })
. . 543: }
. . 544: }
. . 545:
. . 546: if updated {
10ms 50ms 547: schedule = append(schedule, Schedule{
. . 548: Time: t,
. 13.10s 549: MilliIsu: big2exp(totalMilliIsu),
. 12.65s 550: TotalPower: big2exp(totalPower),
. . 551: })
. . 552: }
. . 553:
. . 554: // 時刻 t で購入可能になったアイテムを記録する
50ms 1.91s 555: for itemID := range mItems {
120ms 1.83s 556: if _, ok := itemOnSale[itemID]; ok {
. . 557: continue
. . 558: }
60ms 950ms 559: if 0 <= totalMilliIsu.Cmp(itemPrice1000[itemID]) {
. . 560: itemOnSale[itemID] = t
. . 561: }
. . 562: }
. . 563: }
. . 564:
. . 565: gsAdding := []Adding{}
. 10ms 566: for _, a := range addingAt {
. 20ms 567: gsAdding = append(gsAdding, a)
. . 568: }
. . 569:
. . 570: gsItems := []Item{}
. 10ms 571: for itemID, _ := range mItems {
. 20ms 572: gsItems = append(gsItems, Item{
. . 573: ItemID: itemID,
. . 574: CountBought: itemBought[itemID],
. 10ms 575: CountBuilt: itemBuilt0[itemID],
. 17.21s 576: NextPrice: big2exp(itemPrice[itemID]),
. . 577: Power: itemPower0[itemID],
. . 578: Building: itemBuilding[itemID],
. . 579: })
. . 580: }
. . 581:
. . 582: gsOnSale := []OnSale{}
10ms 20ms 583: for itemID, t := range itemOnSale {
. 10ms 584: gsOnSale = append(gsOnSale, OnSale{
. . 585: ItemID: itemID,
. . 586: Time: t,
. . 587: })
. . 588: }
. . 589:
. . 590: return &GameStatus{
. . 591: Adding: gsAdding,
. . 592: Schedule: schedule,
. . 593: Items: gsItems,
. 10ms 594: OnSale: gsOnSale,
. . 595: }, nil
. . 596:}
. . 597:
. . 598:func serveGameConn(ws *websocket.Conn, roomName string) {
. . 599: log.Println(ws.RemoteAddr(), "serveGameConn", roomName)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment