You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

speedstats.go 3.8 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. package speedstats
  2. import (
  3. "math/rand/v2"
  4. "sync"
  5. "time"
  6. jcstypes "gitlink.org.cn/cloudream/jcs-pub/common/types"
  7. )
  8. const (
  9. LastStatsWeigth = 0.8
  10. MinProb = 0.05
  11. )
  12. type Stats struct {
  13. TotalSize int64
  14. TotalTime time.Duration
  15. LastSpeed float64
  16. HasLastSpeed bool
  17. AvarageSpeed float64
  18. }
  19. func (s *Stats) Record(size int64, time time.Duration) {
  20. s.TotalSize += size
  21. s.TotalTime += time
  22. if s.HasLastSpeed {
  23. s.AvarageSpeed = float64(s.TotalSize)*(1-LastStatsWeigth)/s.TotalTime.Seconds() + s.LastSpeed*LastStatsWeigth
  24. } else {
  25. s.AvarageSpeed = float64(s.TotalSize) / s.TotalTime.Seconds()
  26. }
  27. }
  28. func (s *Stats) Step() {
  29. s.TotalSize = 0
  30. s.TotalTime = 0
  31. s.LastSpeed = s.AvarageSpeed
  32. s.AvarageSpeed = s.LastSpeed * LastStatsWeigth
  33. s.HasLastSpeed = true
  34. }
  35. type SpeedStats struct {
  36. lock sync.RWMutex
  37. stats100M []Stats
  38. stats1G []Stats
  39. statsAbove1G []Stats
  40. }
  41. func New() *SpeedStats {
  42. return &SpeedStats{
  43. stats100M: make([]Stats, 2),
  44. stats1G: make([]Stats, 2),
  45. statsAbove1G: make([]Stats, 2),
  46. }
  47. }
  48. func (p *SpeedStats) Record(size int64, elapsedTime time.Duration, happenedAtClient bool) {
  49. p.lock.Lock()
  50. defer p.lock.Unlock()
  51. if size < 100*1024*1024 {
  52. if happenedAtClient {
  53. p.stats100M[0].Record(size, elapsedTime)
  54. } else {
  55. p.stats100M[1].Record(size, elapsedTime)
  56. }
  57. } else if size < 1024*1024*1024 {
  58. if happenedAtClient {
  59. p.stats1G[0].Record(size, elapsedTime)
  60. } else {
  61. p.stats1G[1].Record(size, elapsedTime)
  62. }
  63. } else {
  64. if happenedAtClient {
  65. p.statsAbove1G[0].Record(size, elapsedTime)
  66. } else {
  67. p.statsAbove1G[1].Record(size, elapsedTime)
  68. }
  69. }
  70. }
  71. func (p *SpeedStats) Step() {
  72. p.lock.Lock()
  73. defer p.lock.Unlock()
  74. p.stats100M[0].Step()
  75. p.stats100M[1].Step()
  76. p.stats1G[0].Step()
  77. p.stats1G[1].Step()
  78. p.statsAbove1G[0].Step()
  79. p.statsAbove1G[1].Step()
  80. }
  81. func (p *SpeedStats) ShouldAtClient(size int64) bool {
  82. p.lock.RLock()
  83. defer p.lock.RUnlock()
  84. var ss []Stats
  85. if size < 100*1024*1024 {
  86. ss = p.stats100M
  87. } else if size < 1024*1024*1024 {
  88. ss = p.stats1G
  89. } else {
  90. ss = p.statsAbove1G
  91. }
  92. prob := 0.0
  93. if ss[0].AvarageSpeed == 0 || ss[1].AvarageSpeed == 0 {
  94. prob = 0.5
  95. } else {
  96. // 保证最小概率为0.05,最大概率为0.95
  97. totalSpeed := ss[0].AvarageSpeed + ss[1].AvarageSpeed
  98. scale := 1 - 2*MinProb
  99. prob = ss[0].AvarageSpeed/totalSpeed*scale + MinProb
  100. }
  101. v := rand.Float64()
  102. return v < prob
  103. }
  104. func (p *SpeedStats) DumpStatus() jcstypes.SpeedStatsStatus {
  105. return jcstypes.SpeedStatsStatus{
  106. Below100M: []jcstypes.SpeedStatsStatusEntry{
  107. {
  108. TotalSize: p.stats100M[0].TotalSize,
  109. TotalTime: p.stats100M[0].TotalTime,
  110. AvarageSpeed: p.stats100M[0].AvarageSpeed,
  111. LastSpeed: p.stats100M[0].LastSpeed,
  112. },
  113. {
  114. TotalSize: p.stats100M[1].TotalSize,
  115. TotalTime: p.stats100M[1].TotalTime,
  116. AvarageSpeed: p.stats100M[1].AvarageSpeed,
  117. LastSpeed: p.stats100M[1].LastSpeed,
  118. },
  119. },
  120. Below1G: []jcstypes.SpeedStatsStatusEntry{
  121. {
  122. TotalSize: p.stats1G[0].TotalSize,
  123. TotalTime: p.stats1G[0].TotalTime,
  124. AvarageSpeed: p.stats1G[0].AvarageSpeed,
  125. LastSpeed: p.stats1G[0].LastSpeed,
  126. },
  127. {
  128. TotalSize: p.stats1G[1].TotalSize,
  129. TotalTime: p.stats1G[1].TotalTime,
  130. AvarageSpeed: p.stats1G[1].AvarageSpeed,
  131. LastSpeed: p.stats1G[1].LastSpeed,
  132. },
  133. },
  134. Above1G: []jcstypes.SpeedStatsStatusEntry{
  135. {
  136. TotalSize: p.statsAbove1G[0].TotalSize,
  137. TotalTime: p.statsAbove1G[0].TotalTime,
  138. AvarageSpeed: p.statsAbove1G[0].AvarageSpeed,
  139. LastSpeed: p.statsAbove1G[0].LastSpeed,
  140. },
  141. {
  142. TotalSize: p.statsAbove1G[1].TotalSize,
  143. TotalTime: p.statsAbove1G[1].TotalTime,
  144. AvarageSpeed: p.statsAbove1G[1].AvarageSpeed,
  145. LastSpeed: p.statsAbove1G[1].LastSpeed,
  146. },
  147. },
  148. }
  149. }

本项目旨在将云际存储公共基础设施化,使个人及企业可低门槛使用高效的云际存储服务(安装开箱即用云际存储客户端即可,无需关注其他组件的部署),同时支持用户灵活便捷定制云际存储的功能细节。