queue.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. // Copyright 2015 CoreOS, Inc.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package stats
  15. import (
  16. "sync"
  17. "time"
  18. )
  19. const (
  20. queueCapacity = 200
  21. )
  22. // RequestStats represent the stats for a request.
  23. // It encapsulates the sending time and the size of the request.
  24. type RequestStats struct {
  25. SendingTime time.Time
  26. Size int
  27. }
  28. type statsQueue struct {
  29. items [queueCapacity]*RequestStats
  30. size int
  31. front int
  32. back int
  33. totalReqSize int
  34. rwl sync.RWMutex
  35. }
  36. func (q *statsQueue) Len() int {
  37. return q.size
  38. }
  39. func (q *statsQueue) ReqSize() int {
  40. return q.totalReqSize
  41. }
  42. // FrontAndBack gets the front and back elements in the queue
  43. // We must grab front and back together with the protection of the lock
  44. func (q *statsQueue) frontAndBack() (*RequestStats, *RequestStats) {
  45. q.rwl.RLock()
  46. defer q.rwl.RUnlock()
  47. if q.size != 0 {
  48. return q.items[q.front], q.items[q.back]
  49. }
  50. return nil, nil
  51. }
  52. // Insert function insert a RequestStats into the queue and update the records
  53. func (q *statsQueue) Insert(p *RequestStats) {
  54. q.rwl.Lock()
  55. defer q.rwl.Unlock()
  56. q.back = (q.back + 1) % queueCapacity
  57. if q.size == queueCapacity { //dequeue
  58. q.totalReqSize -= q.items[q.front].Size
  59. q.front = (q.back + 1) % queueCapacity
  60. } else {
  61. q.size++
  62. }
  63. q.items[q.back] = p
  64. q.totalReqSize += q.items[q.back].Size
  65. }
  66. // Rate function returns the package rate and byte rate
  67. func (q *statsQueue) Rate() (float64, float64) {
  68. front, back := q.frontAndBack()
  69. if front == nil || back == nil {
  70. return 0, 0
  71. }
  72. if time.Now().Sub(back.SendingTime) > time.Second {
  73. q.Clear()
  74. return 0, 0
  75. }
  76. sampleDuration := back.SendingTime.Sub(front.SendingTime)
  77. pr := float64(q.Len()) / float64(sampleDuration) * float64(time.Second)
  78. br := float64(q.ReqSize()) / float64(sampleDuration) * float64(time.Second)
  79. return pr, br
  80. }
  81. // Clear function clear up the statsQueue
  82. func (q *statsQueue) Clear() {
  83. q.rwl.Lock()
  84. defer q.rwl.Unlock()
  85. q.back = -1
  86. q.front = 0
  87. q.size = 0
  88. q.totalReqSize = 0
  89. }