Load test of 1000 players on the server: CPU is the ceiling (~135 req/s); player-simulation tools
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
31
tools/loadtest/mkplayers.py
Normal file
31
tools/loadtest/mkplayers.py
Normal file
@@ -0,0 +1,31 @@
|
||||
# manage.py shell -c "exec(open('tools/loadtest/mkplayers.py').read())" env: LT_N, LT_PREFIX
|
||||
# Test players: fake 0900... phones, an active subscription (no paywall, unlimited hearts), a token,
|
||||
# and for each one island of its grade with that island's questions and option ids.
|
||||
import json, os, random
|
||||
from datetime import timedelta
|
||||
from django.utils import timezone
|
||||
from accounts.authentication import issue_access_token
|
||||
from accounts.models import User
|
||||
from content.models import Node, Question
|
||||
from subscription.models import Subscription
|
||||
|
||||
N = int(os.environ['LT_N']); PREFIX = os.environ['LT_PREFIX']
|
||||
rnd = random.Random(11)
|
||||
GRADES = [8, 9, 10, 11, 12, 4, 5, 6, 7, 3]
|
||||
pool = {}
|
||||
for g in GRADES:
|
||||
nodes = []
|
||||
for node in Node.objects.filter(unit__grade_id=g).order_by('?')[:40]:
|
||||
qs = list(Question.objects.filter(lesson__node=node).prefetch_related('choices')[:6])
|
||||
if len(qs) >= 4:
|
||||
nodes.append({'nodeId': node.id, 'lessonId': qs[0].lesson_id,
|
||||
'questions': [{'id': q.id, 'options': [c.id for c in q.choices.all()]} for q in qs]})
|
||||
pool[g] = nodes
|
||||
out = []
|
||||
exp = timezone.now() + timedelta(days=1)
|
||||
for i in range(N):
|
||||
g = GRADES[i % len(GRADES)]
|
||||
u, _ = User.objects.get_or_create(phone=f'{PREFIX}{i:04d}', defaults={'name': f'تست بار {i}', 'grade_id': g})
|
||||
Subscription.objects.update_or_create(user_id=u.id, defaults={'status': 'active', 'expires_at': exp})
|
||||
out.append({'userId': u.id, 'token': issue_access_token(u.id), 'grade': g, **rnd.choice(pool[g])})
|
||||
print('LTJSON' + json.dumps(out))
|
||||
Reference in New Issue
Block a user