25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

228 lines
6.7KB

  1. #include <algorithm>
  2. #include <math.h>
  3. #include "Statistic.hpp"
  4. namespace SRT {
  5. PacketRecvRateContext::PacketRecvRateContext(TimePoint start)
  6. : _last_arrive_time(start) {
  7. for (size_t i = 0; i < SIZE; i++) {
  8. _ts_arr[i] = 1000000;
  9. _size_arr[i] = SRT_MAX_PAYLOAD_SIZE;
  10. }
  11. _cur_idx = 0;
  12. };
  13. void PacketRecvRateContext::inputPacket(TimePoint &ts,size_t len) {
  14. auto tmp = DurationCountMicroseconds(ts - _last_arrive_time);
  15. _ts_arr[_cur_idx] = tmp;
  16. _size_arr[_cur_idx] = len;
  17. _cur_idx = (1+_cur_idx)%SIZE;
  18. _last_arrive_time = ts;
  19. }
  20. uint32_t PacketRecvRateContext::getPacketRecvRate(uint32_t &bytesps) {
  21. int64_t tmp_arry[SIZE];
  22. std::copy(_ts_arr, _ts_arr + SIZE, tmp_arry);
  23. std::nth_element(tmp_arry, tmp_arry + (SIZE / 2), tmp_arry + SIZE);
  24. int64_t median = tmp_arry[SIZE / 2];
  25. unsigned count = 0;
  26. int sum = 0;
  27. int64_t upper = median << 3;
  28. int64_t lower = median >> 3;
  29. int64_t min = median;
  30. int64_t min_size = 0;
  31. bytesps = 0;
  32. size_t bytes = 0;
  33. const size_t *bp = _size_arr;
  34. // median filtering
  35. const int64_t *p = _ts_arr;
  36. for (int i = 0, n = SIZE; i < n; ++i) {
  37. if ((*p < upper) && (*p > lower)) {
  38. ++count; // packet counter
  39. sum += *p; // usec counter
  40. bytes += *bp; // byte counter
  41. }
  42. if(*p < min){
  43. min = *p;
  44. min_size = *bp;
  45. }
  46. ++p; // advance packet pointer
  47. ++bp; // advance bytes pointer
  48. }
  49. uint32_t max_ret = (uint32_t)ceil(1e6/min);
  50. uint32_t max_byteps = (uint32_t)ceil(1e6*min_size/min);
  51. if(count>(SIZE>>1)){
  52. bytesps = (uint32_t)ceil(1000000.0 / (double(sum) / double(bytes)));
  53. auto ret = (uint32_t)ceil(1000000.0 / (double(sum) / double(count)));
  54. //bytesps = max_byteps;
  55. return max_ret;
  56. }else{
  57. //TraceL<<max_ret<<" pkt/s "<<max_byteps<<" byte/s";
  58. bytesps = 0;
  59. return 0;
  60. }
  61. bytesps = 0;
  62. return 0;
  63. // claculate speed, or return 0 if not enough valid value
  64. }
  65. std::string PacketRecvRateContext::dump(){
  66. _StrPrinter printer;
  67. printer <<"dur array : ";
  68. for (size_t i = 0; i < SIZE; i++)
  69. {
  70. printer<<_ts_arr[i]<<" ";
  71. }
  72. printer <<"\r\n";
  73. printer <<"size array : ";
  74. for (size_t i = 0; i < SIZE; i++)
  75. {
  76. printer<<_size_arr[i]<<" ";
  77. }
  78. printer <<"\r\n";
  79. return std::move(printer);
  80. }
  81. EstimatedLinkCapacityContext::EstimatedLinkCapacityContext(TimePoint start) : _start(start) {
  82. for (size_t i = 0; i < SIZE; i++) {
  83. _dur_probe_arr[i] = 1000;
  84. }
  85. _cur_idx = 0;
  86. };
  87. void EstimatedLinkCapacityContext::inputPacket(TimePoint &ts,DataPacket::Ptr& pkt) {
  88. uint32_t seq = pkt->packet_seq_number;
  89. auto diff = seqCmp(seq,_last_seq);
  90. const bool retransmitted = pkt->R == 1;
  91. const bool unordered = diff<=0;
  92. uint32_t one = seq&0xf;
  93. if(one == 0){
  94. probe1Arrival(ts,pkt,unordered || retransmitted);
  95. }
  96. if(diff>0){
  97. _last_seq = seq;
  98. }
  99. if(unordered || retransmitted){
  100. return;
  101. }
  102. if(one == 1){
  103. probe2Arrival(ts,pkt);
  104. }
  105. }
  106. /// Record the arrival time of the first probing packet.
  107. void EstimatedLinkCapacityContext::probe1Arrival(TimePoint &ts, const DataPacket::Ptr &pkt, bool unordered) {
  108. if (unordered && pkt->packet_seq_number == _probe1_seq) {
  109. // Reset the starting probe into "undefined", when
  110. // a packet has come as retransmitted before the
  111. // measurement at arrival of 17th could be taken.
  112. _probe1_seq = SEQ_NONE;
  113. return;
  114. }
  115. _ts_probe_time = ts;
  116. _probe1_seq = pkt->packet_seq_number; // Record the sequence where 16th packet probe was taken
  117. }
  118. /// Record the arrival time of the second probing packet and the interval between packet pairs.
  119. void EstimatedLinkCapacityContext::probe2Arrival(TimePoint &ts, const DataPacket::Ptr &pkt) {
  120. // Reject probes that don't refer to the very next packet
  121. // towards the one that was lately notified by probe1Arrival.
  122. // Otherwise the result can be stupid.
  123. // Simply, in case when this wasn't called exactly for the
  124. // expected packet pair, behave as if the 17th packet was lost.
  125. // no start point yet (or was reset) OR not very next packet
  126. if (_probe1_seq == SEQ_NONE || incSeq(_probe1_seq) != pkt->packet_seq_number)
  127. return;
  128. // Reset the starting probe to prevent checking if the
  129. // measurement was already taken.
  130. _probe1_seq = SEQ_NONE;
  131. // record the probing packets interval
  132. // Adjust the time for what a complete packet would have take
  133. const int64_t timediff = DurationCountMicroseconds(ts - _ts_probe_time);
  134. const int64_t timediff_times_pl_size = timediff * SRT_MAX_PAYLOAD_SIZE;
  135. // Let's take it simpler than it is coded here:
  136. // (stating that a packet has never zero size)
  137. //
  138. // probe_case = (now - previous_packet_time) * SRT_MAX_PAYLOAD_SIZE / pktsz;
  139. //
  140. // Meaning: if the packet is fully packed, probe_case = timediff.
  141. // Otherwise the timediff will be "converted" to a time that a fully packed packet "would take",
  142. // provided the arrival time is proportional to the payload size and skipping
  143. // the ETH+IP+UDP+SRT header part elliminates the constant packet delivery time influence.
  144. //
  145. const size_t pktsz = pkt->payloadSize();
  146. _dur_probe_arr[_cur_idx] = pktsz ? int64_t(timediff_times_pl_size / pktsz) : int64_t(timediff);
  147. // the window is logically circular
  148. _cur_idx = (_cur_idx + 1) % SIZE;
  149. }
  150. uint32_t EstimatedLinkCapacityContext::getEstimatedLinkCapacity() {
  151. int64_t tmp[SIZE];
  152. std::copy(_dur_probe_arr, _dur_probe_arr + SIZE , tmp);
  153. std::nth_element(tmp, tmp + (SIZE / 2), tmp + SIZE);
  154. int64_t median = tmp[SIZE / 2];
  155. int64_t count = 1;
  156. int64_t sum = median;
  157. int64_t upper = median << 3; // median*8
  158. int64_t lower = median >> 3; // median/8
  159. // median filtering
  160. const int64_t* p = _dur_probe_arr;
  161. for (int i = 0, n = SIZE; i < n; ++ i)
  162. {
  163. if ((*p < upper) && (*p > lower))
  164. {
  165. ++ count;
  166. sum += *p;
  167. }
  168. ++ p;
  169. }
  170. return (uint32_t)ceil(1000000.0 / (double(sum) / double(count)));
  171. }
  172. /*
  173. void RecvRateContext::inputPacket(TimePoint &ts, size_t size) {
  174. if (_pkt_map.size() > 100) {
  175. _pkt_map.erase(_pkt_map.begin());
  176. }
  177. auto tmp = DurationCountMicroseconds(ts - _start);
  178. _pkt_map.emplace(tmp, size);
  179. }
  180. uint32_t RecvRateContext::getRecvRate() {
  181. if (_pkt_map.size() < 2) {
  182. return 0;
  183. }
  184. auto first = _pkt_map.begin();
  185. auto last = _pkt_map.rbegin();
  186. double dur = (last->first - first->first) / 1000000.0;
  187. size_t bytes = 0;
  188. for (auto it : _pkt_map) {
  189. bytes += it.second;
  190. }
  191. double rate = (double)bytes / dur;
  192. return (uint32_t)rate;
  193. }
  194. */
  195. } // namespace SRT