queue.go 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. package stats
  2. import (
  3. "sync"
  4. "time"
  5. )
  6. const (
  7. queueCapacity = 200
  8. )
  9. // RequestStats represent the stats for a request.
  10. // It encapsulates the sending time and the size of the request.
  11. type RequestStats struct {
  12. SendingTime time.Time
  13. Size int
  14. }
  15. type statsQueue struct {
  16. items [queueCapacity]*RequestStats
  17. size int
  18. front int
  19. back int
  20. totalReqSize int
  21. rwl sync.RWMutex
  22. }
  23. func (q *statsQueue) Len() int {
  24. return q.size
  25. }
  26. func (q *statsQueue) ReqSize() int {
  27. return q.totalReqSize
  28. }
  29. // FrontAndBack gets the front and back elements in the queue
  30. // We must grab front and back together with the protection of the lock
  31. func (q *statsQueue) frontAndBack() (*RequestStats, *RequestStats) {
  32. q.rwl.RLock()
  33. defer q.rwl.RUnlock()
  34. if q.size != 0 {
  35. return q.items[q.front], q.items[q.back]
  36. }
  37. return nil, nil
  38. }
  39. // Insert function insert a RequestStats into the queue and update the records
  40. func (q *statsQueue) Insert(p *RequestStats) {
  41. q.rwl.Lock()
  42. defer q.rwl.Unlock()
  43. q.back = (q.back + 1) % queueCapacity
  44. if q.size == queueCapacity { //dequeue
  45. q.totalReqSize -= q.items[q.front].Size
  46. q.front = (q.back + 1) % queueCapacity
  47. } else {
  48. q.size++
  49. }
  50. q.items[q.back] = p
  51. q.totalReqSize += q.items[q.back].Size
  52. }
  53. // Rate function returns the package rate and byte rate
  54. func (q *statsQueue) Rate() (float64, float64) {
  55. front, back := q.frontAndBack()
  56. if front == nil || back == nil {
  57. return 0, 0
  58. }
  59. if time.Now().Sub(back.SendingTime) > time.Second {
  60. q.Clear()
  61. return 0, 0
  62. }
  63. sampleDuration := back.SendingTime.Sub(front.SendingTime)
  64. pr := float64(q.Len()) / float64(sampleDuration) * float64(time.Second)
  65. br := float64(q.ReqSize()) / float64(sampleDuration) * float64(time.Second)
  66. return pr, br
  67. }
  68. // Clear function clear up the statsQueue
  69. func (q *statsQueue) Clear() {
  70. q.rwl.Lock()
  71. defer q.rwl.Unlock()
  72. q.back = -1
  73. q.front = 0
  74. q.size = 0
  75. q.totalReqSize = 0
  76. }