File size: 2,925 Bytes
c751e85
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import grpc
import time
import sys
import wave
from concurrent.futures import ThreadPoolExecutor, as_completed

sys.path.insert(0, 'server/grpc')
import avatar_pb2
import avatar_pb2_grpc

# Carregar audio de teste
audio_path = 'data/audio/orpheus_demo_3_phrases.wav'
with wave.open(audio_path, 'rb') as wf:
    sample_rate = wf.getframerate()
    audio_data = wf.readframes(wf.getnframes())

audio_duration = len(audio_data) / (sample_rate * 2)
print(f'Audio: {audio_duration:.2f}s')
print()

def run_session(session_id, stub):
    def audio_chunks():
        chunk_size = 4800  # 200ms chunks
        for i in range(0, len(audio_data), chunk_size):
            yield avatar_pb2.AudioChunk(
                session_id=f'user_{session_id}',
                audio_data=audio_data[i:i+chunk_size],
                sample_rate=sample_rate,
                is_final=(i + chunk_size >= len(audio_data))
            )
    
    start = time.time()
    first_frame_time = None
    frame_count = 0
    
    try:
        for response in stub.StreamingGenerate(audio_chunks()):
            if first_frame_time is None:
                first_frame_time = time.time() - start
            frame_count += 1
    except Exception as e:
        return {'error': str(e), 'session_id': session_id}
    
    total_time = time.time() - start
    fps = frame_count / total_time if total_time > 0 else 0
    
    return {
        'session_id': session_id,
        'ttff': first_frame_time * 1000 if first_frame_time else 0,
        'frames': frame_count,
        'fps': fps,
        'total_time': total_time
    }

def test_concurrent_users(num_users):
    channel = grpc.insecure_channel('localhost:8080')
    stub = avatar_pb2_grpc.AvatarServiceStub(channel)
    
    results = []
    with ThreadPoolExecutor(max_workers=num_users) as executor:
        futures = [executor.submit(run_session, i, stub) for i in range(num_users)]
        for future in as_completed(futures):
            results.append(future.result())
    
    return results

# Testar de 1 a 8 usuarios
print('=' * 70)
print('TESTE DE CAPACIDADE MULTI-USUARIO (torch.compile ENABLED)')
print('=' * 70)
print(f'Users | Avg TTFF | Avg FPS | Min FPS | Real-time?')
print('-' * 70)

realtime_fps = 25

for num_users in [1, 2, 3, 4, 5, 6, 8]:
    results = test_concurrent_users(num_users)
    valid = [r for r in results if 'error' not in r]
    
    if valid:
        avg_ttff = sum(r['ttff'] for r in valid) / len(valid)
        avg_fps = sum(r['fps'] for r in valid) / len(valid)
        min_fps = min(r['fps'] for r in valid)
        is_realtime = 'YES' if min_fps >= realtime_fps else 'NO'
        
        print(f'{num_users:>5} | {avg_ttff:>8.0f}ms | {avg_fps:>7.1f} | {min_fps:>7.1f} | {is_realtime}')
    else:
        print(f'{num_users:>5} | ERROR')
    
    time.sleep(2)

print('=' * 70)
print(f'Real-time threshold: {realtime_fps} FPS (video is 25 FPS)')
print('=' * 70)