Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into move-built_front
Browse files Browse the repository at this point in the history
  • Loading branch information
ShotaKitazawa committed Jul 9, 2021
2 parents e9d0e1a + e765848 commit f31315d
Show file tree
Hide file tree
Showing 23 changed files with 649 additions and 143 deletions.
16 changes: 7 additions & 9 deletions .github/workflows/packer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ jobs:
working-directory: provisioning/packer
steps:
- uses: actions/checkout@v2
- name: Get source tag of git
id: get_source_tag
run: echo ::set-output name=SOURCE_TAG::${GITHUB_REF#refs/tags/}

- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
Expand All @@ -95,19 +98,14 @@ jobs:
- run: make clean-output

- name: "make build-contestant"
env:
GIT_TAG: ${{ steps.get_source_tag.outputs.SOURCE_TAG }}
run: |
export PATH=${HOME}/work/_tool/isucon11-qualify:${PATH}
make build-contestant
- name: "make build-bench"
env:
GIT_TAG: ${{ steps.get_source_tag.outputs.SOURCE_TAG }}
run: |
export PATH=${HOME}/work/_tool/isucon11-qualify:${PATH}
make build-bench
- uses: actions/upload-artifact@v2
with:
name: manifest-amd64-contestant.json
path: provisioning/packer/output/manifest-amd64-contestant.json
- uses: actions/upload-artifact@v2
with:
name: manifest-amd64-bench.json
path: provisioning/packer/output/manifest-amd64-bench.json
2 changes: 1 addition & 1 deletion bench/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ func main() {

critical, _, deduction := checkError(err)

if critical || (deduction && atomic.AddInt64(&errorCount, 1) >= FAIL_ERROR_COUNT) {
if critical || (deduction && atomic.AddInt64(&errorCount, 1) > FAIL_ERROR_COUNT) {
step.Cancel()
}

Expand Down
38 changes: 32 additions & 6 deletions bench/model/isu.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package model

import "fmt"
import (
"context"
"fmt"
)

//enum
type IsuStateChange int
Expand All @@ -21,7 +24,7 @@ const (
type StreamsForPoster struct {
ActiveChan chan<- bool
StateChan <-chan IsuStateChange
ConditionChan chan<- *IsuCondition
ConditionChan chan<- []IsuCondition
}

//posterスレッドとシナリオスレッドとの通信に必要な情報
Expand All @@ -30,7 +33,7 @@ type StreamsForPoster struct {
type StreamsForScenario struct {
activeChan <-chan bool
StateChan chan<- IsuStateChange
ConditionChan <-chan *IsuCondition
ConditionChan <-chan []IsuCondition
}

//一つのIsuにつき、一つの送信用スレッドがある
Expand All @@ -45,7 +48,7 @@ type Isu struct {
IsWantDeactivated bool //シナリオ上でDeleteリクエストを送ったかどうか
isDeactivated bool //実際にdeactivateされているか
StreamsForScenario *StreamsForScenario //posterスレッドとの通信
Conditions []IsuCondition //シナリオスレッドからのみ参照
Conditions IsuConditionArray //シナリオスレッドからのみ参照
}

//新しいISUの生成
Expand All @@ -56,7 +59,7 @@ type Isu struct {
func NewRandomIsuRaw(owner *User) (*Isu, *StreamsForPoster, error) {
activeChan := make(chan bool)
stateChan := make(chan IsuStateChange, 1)
conditionChan := make(chan *IsuCondition, 30)
conditionChan := make(chan []IsuCondition, 10)

id := fmt.Sprintf("randomid-%s-%d", owner.UserID, len(owner.IsuListOrderByCreatedAt)) //TODO: ちゃんと生成する
name := fmt.Sprintf("randomname-%s-%d", owner.UserID, len(owner.IsuListOrderByCreatedAt)) //TODO: ちゃんと生成する
Expand All @@ -74,7 +77,7 @@ func NewRandomIsuRaw(owner *User) (*Isu, *StreamsForPoster, error) {
StateChan: stateChan,
ConditionChan: conditionChan,
},
Conditions: []IsuCondition{},
Conditions: NewIsuConditionArray(),
}

streamsForPoster := &StreamsForPoster{
Expand All @@ -94,3 +97,26 @@ func (isu *Isu) IsDeactivated() bool {
}
return isu.isDeactivated
}

func (isu *Isu) getConditionFromChan(ctx context.Context, userConditionBuffer *IsuConditionArray) {
for {
select {
case <-ctx.Done():
return
case conditions, ok := <-isu.StreamsForScenario.ConditionChan:
if !ok {
return
}
for _, c := range conditions {
isu.Conditions.Add(&c)
}
if userConditionBuffer != nil {
for _, c := range conditions {
userConditionBuffer.Add(&c)
}
}
default:
return
}
}
}
217 changes: 214 additions & 3 deletions bench/model/isuCondition.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ package model
type ConditionLevel int

const (
ConditionLevelInfo ConditionLevel = iota
ConditionLevelWarning
ConditionLevelCritical
ConditionLevelNone ConditionLevel = 0
ConditionLevelInfo ConditionLevel = 1
ConditionLevelWarning ConditionLevel = 2
ConditionLevelCritical ConditionLevel = 4
)

//TODO: メモリ節約の必要があるなら考える
Expand All @@ -20,5 +21,215 @@ type IsuCondition struct {
IsBroken bool
ConditionLevel ConditionLevel `json:"-"`
Message string `json:"message"`
OwnerID string
// Owner *Isu
}

//left < right
func (left *IsuCondition) Less(right *IsuCondition) bool {
return left.TimestampUnix < right.TimestampUnix ||
(left.TimestampUnix == right.TimestampUnix && left.OwnerID < right.OwnerID)
}

type IsuConditionCursor struct {
TimestampUnix int64
OwnerID string
}

//left < right
func (left *IsuConditionCursor) Less(right *IsuConditionCursor) bool {
return left.TimestampUnix < right.TimestampUnix ||
(left.TimestampUnix == right.TimestampUnix && left.OwnerID < right.OwnerID)
}

//left < right
func (left *IsuCondition) Less2(right *IsuConditionCursor) bool {
return left.TimestampUnix < right.TimestampUnix ||
(left.TimestampUnix == right.TimestampUnix && left.OwnerID < right.OwnerID)
}

//left < right
func (left *IsuConditionCursor) Less2(right *IsuCondition) bool {
return left.TimestampUnix < right.TimestampUnix ||
(left.TimestampUnix == right.TimestampUnix && left.OwnerID < right.OwnerID)
}

//conditionをcreated at順で見る
type IsuConditionArray struct {
Info []IsuCondition
Warning []IsuCondition
Critical []IsuCondition
}

//conditionをcreated atの大きい順で見る
type IsuConditionIterator struct {
filter ConditionLevel
indexInfo int
indexWarning int
indexCritical int
parent *IsuConditionArray
}

func NewIsuConditionArray() IsuConditionArray {
return IsuConditionArray{
Info: []IsuCondition{},
Warning: []IsuCondition{},
Critical: []IsuCondition{},
}
}

func (ia *IsuConditionArray) Add(cond *IsuCondition) {
switch cond.ConditionLevel {
case ConditionLevelInfo:
ia.Info = append(ia.Info, *cond)
case ConditionLevelWarning:
ia.Warning = append(ia.Warning, *cond)
case ConditionLevelCritical:
ia.Critical = append(ia.Critical, *cond)
}
}

func (ia *IsuConditionArray) End(filter ConditionLevel) IsuConditionIterator {
return IsuConditionIterator{
filter: filter,
indexInfo: len(ia.Info),
indexWarning: len(ia.Warning),
indexCritical: len(ia.Critical),
parent: ia,
}
}

func (ia *IsuConditionArray) Back() *IsuCondition {
iter := ia.End(ConditionLevelInfo | ConditionLevelWarning | ConditionLevelCritical)
return iter.Prev()
}

func (iter *IsuConditionIterator) UpperBoundIsuConditionIndex(targetTimestamp int64, targetIsuUUID string) {
if (iter.filter & ConditionLevelInfo) != 0 {
iter.indexInfo = upperBoundIsuConditionIndex(iter.parent.Info, len(iter.parent.Info), targetTimestamp, targetIsuUUID)
}
if (iter.filter & ConditionLevelWarning) != 0 {
iter.indexWarning = upperBoundIsuConditionIndex(iter.parent.Warning, len(iter.parent.Warning), targetTimestamp, targetIsuUUID)
}
if (iter.filter & ConditionLevelCritical) != 0 {
iter.indexCritical = upperBoundIsuConditionIndex(iter.parent.Critical, len(iter.parent.Critical), targetTimestamp, targetIsuUUID)
}
}

func (iter *IsuConditionIterator) LowerBoundIsuConditionIndex(targetTimestamp int64, targetIsuUUID string) {
if (iter.filter & ConditionLevelInfo) != 0 {
iter.indexInfo = lowerBoundIsuConditionIndex(iter.parent.Info, len(iter.parent.Info), targetTimestamp, targetIsuUUID)
}
if (iter.filter & ConditionLevelWarning) != 0 {
iter.indexWarning = lowerBoundIsuConditionIndex(iter.parent.Warning, len(iter.parent.Warning), targetTimestamp, targetIsuUUID)
}
if (iter.filter & ConditionLevelCritical) != 0 {
iter.indexCritical = lowerBoundIsuConditionIndex(iter.parent.Critical, len(iter.parent.Critical), targetTimestamp, targetIsuUUID)
}
}

//return: nil:もう要素がない
func (iter *IsuConditionIterator) Prev() *IsuCondition {
maxType := ConditionLevelNone
var max *IsuCondition
if (iter.filter&ConditionLevelInfo) != 0 && iter.indexInfo != 0 {
if max == nil || max.Less(&iter.parent.Info[iter.indexInfo-1]) {
maxType = ConditionLevelInfo
max = &iter.parent.Info[iter.indexInfo-1]
}
}
if (iter.filter&ConditionLevelWarning) != 0 && iter.indexWarning != 0 {
if max == nil || max.Less(&iter.parent.Warning[iter.indexWarning-1]) {
maxType = ConditionLevelWarning
max = &iter.parent.Warning[iter.indexWarning-1]
}
}
if (iter.filter&ConditionLevelCritical) != 0 && iter.indexCritical != 0 {
if max == nil || max.Less(&iter.parent.Critical[iter.indexCritical-1]) {
maxType = ConditionLevelCritical
max = &iter.parent.Critical[iter.indexCritical-1]
}
}

switch maxType {
case ConditionLevelInfo:
iter.indexInfo--
case ConditionLevelWarning:
iter.indexWarning--
case ConditionLevelCritical:
iter.indexCritical--
}
return max
}

//baseはlessの昇順
func upperBoundIsuConditionIndex(base []IsuCondition, end int, targetTimestamp int64, targetIsuUUID string) int {
//末尾の方にあることが分かっているので、末尾を固定要素ずつ線形探索 + 二分探索
//assert end <= len(base)
target := IsuConditionCursor{TimestampUnix: targetTimestamp, OwnerID: targetIsuUUID}
if end <= 0 {
return end //要素が見つからない
}
//[0]が番兵になるかチェック
if target.Less2(&base[0]) {
return 0 //0がupperBound
}

//線形探索 ngがbase[ng] <= targetになるまで探索
const defaultRange = 64
ok := end
ng := end - defaultRange
ng = (ng / defaultRange) * defaultRange //0未満になるのが嫌なので、defaultRangeの倍数にする
for target.Less2(&base[ng]) { //Timestampはunique仮定なので、<で良い(等価が見つかればそれで良し)
ok = ng
ng -= defaultRange
}

//答えは(ng, ok]内にあるはずなので、二分探索
for ok-ng > 1 {
mid := (ok + ng) / 2
if target.Less2(&base[mid]) {
ok = mid
} else {
ng = mid
}
}

return ok
}

//baseはlessの昇順
func lowerBoundIsuConditionIndex(base []IsuCondition, end int, targetTimestamp int64, targetIsuUUID string) int {
//末尾の方にあることが分かっているので、末尾を固定要素ずつ線形探索 + 二分探索
//assert end <= len(base)
target := IsuConditionCursor{TimestampUnix: targetTimestamp, OwnerID: targetIsuUUID}
if end <= 0 {
return end //要素が見つからない
}
//[0]が番兵になるかチェック
if !base[0].Less2(&target) {
return 0 //0がupperBound
}

//線形探索 ngがbase[ng] <= targetになるまで探索
const defaultRange = 64
ok := end
ng := end - defaultRange
ng = (ng / defaultRange) * defaultRange //0未満になるのが嫌なので、defaultRangeの倍数にする
for !base[ng].Less2(&target) { //Timestampはunique仮定なので、<で良い(等価が見つかればそれで良し)
ok = ng
ng -= defaultRange
}

//答えは(ng, ok]内にあるはずなので、二分探索
for ok-ng > 1 {
mid := (ok + ng) / 2
if !base[mid].Less2(&target) {
ok = mid
} else {
ng = mid
}
}

return ok
}
9 changes: 8 additions & 1 deletion bench/model/user.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package model

import (
"context"
"math/rand"

"github.com/isucon/isucandar/agent"
Expand All @@ -23,7 +24,7 @@ type User struct {
Type UserType
IsuListOrderByCreatedAt []*Isu //CreatedAtは厳密にはわからないので、postした後にgetをした順番を正とする
IsuListByID map[string]*Isu //IDをkeyにアクセス
//ここで[]IsuLogを持つと更新にmutexが必要で嫌なので持たない
Conditions IsuConditionArray

Agent *agent.Agent
}
Expand All @@ -48,6 +49,12 @@ func (u *User) AddIsu(isu *Isu) {
u.IsuListByID[isu.JIAIsuUUID] = isu
}

func (user *User) GetConditionFromChan(ctx context.Context) {
for _, isu := range user.IsuListOrderByCreatedAt {
isu.getConditionFromChan(ctx, &user.Conditions)
}
}

// utility

//TODO: 差し替える
Expand Down
Loading

0 comments on commit f31315d

Please sign in to comment.