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

166 lines
7.4 KiB

2 years ago
  1. import logging
  2. import uuid
  3. import random
  4. import threading
  5. from fe.access import book
  6. from fe.access.new_seller import register_new_seller
  7. from fe.access.new_buyer import register_new_buyer
  8. from fe.access.buyer import Buyer
  9. from fe import conf
  10. class NewOrder:
  11. def __init__(self, buyer: Buyer, store_id, book_id_and_count):
  12. self.buyer = buyer
  13. self.store_id = store_id
  14. self.book_id_and_count = book_id_and_count
  15. def run(self) -> (bool, str):
  16. code, order_id = self.buyer.new_order(self.store_id, self.book_id_and_count)
  17. return code == 200, order_id
  18. class Payment:
  19. def __init__(self, buyer:Buyer, order_id):
  20. self.buyer = buyer
  21. self.order_id = order_id
  22. def run(self) -> bool:
  23. code = self.buyer.payment(self.order_id)
  24. return code == 200
  25. class Workload:
  26. def __init__(self):
  27. self.uuid = str(uuid.uuid1())
  28. self.book_ids = []
  29. self.buyer_ids = []
  30. self.store_ids = []
  31. self.book_db = book.BookDB(conf.Use_Large_DB)
  32. self.row_count = self.book_db.get_book_count()
  33. self.book_num_per_store = conf.Book_Num_Per_Store
  34. if self.row_count < self.book_num_per_store:
  35. self.book_num_per_store = self.row_count
  36. self.store_num_per_user = conf.Store_Num_Per_User
  37. self.seller_num = conf.Seller_Num
  38. self.buyer_num = conf.Buyer_Num
  39. self.session = conf.Session
  40. self.stock_level = conf.Default_Stock_Level
  41. self.user_funds = conf.Default_User_Funds
  42. self.batch_size = conf.Data_Batch_Size
  43. self.procedure_per_session = conf.Request_Per_Session
  44. self.n_new_order = 0
  45. self.n_payment = 0
  46. self.n_new_order_ok = 0
  47. self.n_payment_ok = 0
  48. self.time_new_order = 0
  49. self.time_payment = 0
  50. self.lock = threading.Lock()
  51. # 存储上一次的值,用于两次做差
  52. self.n_new_order_past = 0
  53. self.n_payment_past = 0
  54. self.n_new_order_ok_past = 0
  55. self.n_payment_ok_past = 0
  56. def to_seller_id_and_password(self, no: int) -> (str, str):
  57. return "seller_{}_{}".format(no, self.uuid), "password_seller_{}_{}".format(no, self.uuid)
  58. def to_buyer_id_and_password(self, no: int) -> (str, str):
  59. return "buyer_{}_{}".format(no, self.uuid), "buyer_seller_{}_{}".format(no, self.uuid)
  60. def to_store_id(self, seller_no: int, i):
  61. return "store_s_{}_{}_{}".format(seller_no, i, self.uuid)
  62. def gen_database(self):
  63. logging.info("load data")
  64. for i in range(1, self.seller_num + 1):
  65. user_id, password = self.to_seller_id_and_password(i)
  66. seller = register_new_seller(user_id, password)
  67. for j in range(1, self.store_num_per_user + 1):
  68. store_id = self.to_store_id(i, j)
  69. code = seller.create_store(store_id)
  70. assert code == 200
  71. self.store_ids.append(store_id)
  72. row_no = 0
  73. while row_no < self.book_num_per_store:
  74. books = self.book_db.get_book_info(row_no, self.batch_size)
  75. if len(books) == 0:
  76. break
  77. for bk in books:
  78. code = seller.add_book(store_id, self.stock_level, bk)
  79. assert code == 200
  80. if i == 1 and j == 1:
  81. self.book_ids.append(bk.id)
  82. row_no = row_no + len(books)
  83. logging.info("seller data loaded.")
  84. for k in range(1, self.buyer_num + 1):
  85. user_id, password = self.to_buyer_id_and_password(k)
  86. buyer = register_new_buyer(user_id, password)
  87. buyer.add_funds(self.user_funds)
  88. self.buyer_ids.append(user_id)
  89. logging.info("buyer data loaded.")
  90. def get_new_order(self) -> NewOrder:
  91. n = random.randint(1, self.buyer_num)
  92. buyer_id, buyer_password = self.to_buyer_id_and_password(n)
  93. store_no = int(random.uniform(0, len(self.store_ids) - 1))
  94. store_id = self.store_ids[store_no]
  95. books = random.randint(1, 10)
  96. book_id_and_count = []
  97. book_temp = []
  98. for i in range(0, books):
  99. book_no = int(random.uniform(0, len(self.book_ids) - 1))
  100. book_id = self.book_ids[book_no]
  101. if book_id in book_temp:
  102. continue
  103. else:
  104. book_temp.append(book_id)
  105. count = random.randint(1, 10)
  106. book_id_and_count.append((book_id, count))
  107. b = Buyer(url_prefix=conf.URL, user_id=buyer_id, password=buyer_password)
  108. new_ord = NewOrder(b, store_id, book_id_and_count)
  109. return new_ord
  110. def update_stat(self, n_new_order, n_payment,
  111. n_new_order_ok, n_payment_ok,
  112. time_new_order, time_payment):
  113. # 获取当前并发数
  114. thread_num = len(threading.enumerate())
  115. # 加索
  116. self.lock.acquire()
  117. self.n_new_order = self.n_new_order + n_new_order
  118. self.n_payment = self.n_payment + n_payment
  119. self.n_new_order_ok = self.n_new_order_ok + n_new_order_ok
  120. self.n_payment_ok = self.n_payment_ok + n_payment_ok
  121. self.time_new_order = self.time_new_order + time_new_order
  122. self.time_payment = self.time_payment + time_payment
  123. # 计算这段时间内新创建订单的总数目
  124. n_new_order_diff = self.n_new_order - self.n_new_order_past
  125. # 计算这段时间内新付款订单的总数目
  126. n_payment_diff = self.n_payment - self.n_payment_past
  127. if self.n_payment != 0 and self. n_new_order != 0 \
  128. and (self.time_payment + self.time_new_order):
  129. # TPS_C(吞吐量):成功创建订单数量/(提交订单时间/提交订单并发数 + 提交付款订单时间/提交付款订单并发数)
  130. # NO=OK:新创建订单数量
  131. # Thread_num:以新提交订单的数量作为并发数(这一次的TOTAL-上一次的TOTAL)
  132. # TOTAL:总提交订单数量
  133. # LATENCY:提交订单时间/处理订单笔数(只考虑该线程延迟,未考虑并发)
  134. # P=OK:新创建付款订单数量
  135. # Thread_num:以新提交付款订单的数量作为并发数(这一次的TOTAL-上一次的TOTAL)
  136. # TOTAL:总付款提交订单数量
  137. # LATENCY:提交付款订单时间/处理付款订单笔数(只考虑该线程延迟,未考虑并发)
  138. logging.info("TPS_C={}, NO=OK:{} Thread_num:{} TOTAL:{} LATENCY:{} , P=OK:{} Thread_num:{} TOTAL:{} LATENCY:{}".format(
  139. int(self.n_new_order_ok / (self.time_payment / n_payment_diff + self.time_new_order / n_new_order_diff)), # 吞吐量:完成订单数/((付款所用时间+订单所用时间)/并发数)
  140. self.n_new_order_ok, n_new_order_diff, self.n_new_order, self.time_new_order / self.n_new_order, # 订单延迟:(创建订单所用时间/并发数)/新创建订单数
  141. self.n_payment_ok, n_payment_diff, self.n_payment, self.time_payment / self.n_payment # 付款延迟:(付款所用时间/并发数)/付款订单数
  142. ))
  143. self.lock.release()
  144. # 旧值更新为新值,便于下一轮计算
  145. self.n_new_order_past = self.n_new_order
  146. self.n_payment_past = self.n_payment
  147. self.n_new_order_ok_past = self.n_new_order_ok
  148. self.n_payment_ok_past = self.n_payment_ok