"""Run owned, offline local Docker qualification containers. Never deploys. Build before/final images from the documented commits first. Keeps Docker config and registry credentials intact. No ports are published. Test clients run inside the same 2-CPU cgroup, identically across versions. """ import argparse import io import json import os from pathlib import Path import subprocess import tarfile import tempfile import time def main(): p=argparse.ArgumentParser();p.add_argument('--before-image',required=True);p.add_argument('--final-image',required=True);p.add_argument('--only-final',action='store_true');p.add_argument('--output',default='benchmarks/results/final');args=p.parse_args() env=dict(os.environ) for key in ['DOCKER_HOST','DOCKER_CONTEXT','DOCKER_TLS','DOCKER_TLS_VERIFY','DOCKER_CERT_PATH']:env.pop(key,None) docker=['docker','--host=unix:///var/run/docker.sock'] def run(argv,**kwargs):return subprocess.run(docker+argv,env=env,check=True,capture_output=True,text=True,**kwargs) out=Path(args.output);out.mkdir(parents=True,exist_ok=True) with tempfile.TemporaryDirectory(prefix='needle-original-') as tmp: archive=subprocess.check_output(['git','archive','f7fbfaabc040e1e765f881c01360e2e091f90a51']) with tarfile.open(fileobj=io.BytesIO(archive)) as tf:tf.extractall(tmp,filter='data') jobs=[] if args.only_final else [('original',args.before_image,tmp,1,1,True),('v2-before',args.before_image,None,1,2,True)] jobs += [('v2-final',args.final_image,None,1,2,True),('v2-final-c2',args.final_image,None,2,1,False),('v2-final-c4',args.final_image,None,4,1,False)] for label,image,source,concurrency,repeat,candidates in jobs: start=time.perf_counter() cid=run(['run','-d','--cpus','2','--memory','16g','--network','none','--entrypoint','uvicorn',image,'gateway:app','--app-dir','/srv','--host','127.0.0.1','--port','7860']).stdout.strip() try: if source: for f in ['gateway.py','models.py','registry.py','laya.py']:run(['cp',str(Path(source)/f),cid+':/srv/'+f]) run(['restart',cid]);start=time.perf_counter() for f in ['scripts','benchmarks']:run(['cp',f,cid+':/srv/'+f]) ready=False for _ in range(50): r=subprocess.run(docker+['exec',cid,'python','-c',"import urllib.request;urllib.request.urlopen('http://127.0.0.1:7860/ready')"],env=env,capture_output=True) if r.returncode==0:ready=True;break time.sleep(.2) if not ready:raise RuntimeError('Owned qualification container did not become ready') ready_ms=(time.perf_counter()-start)*1000 command=['exec',cid,'python','-m','scripts.final_qualification','--label',label,'--concurrency',str(concurrency),'--repeat',str(repeat)] if candidates:command+=['--candidate-check'] data=json.loads(run(command,timeout=1200).stdout) data['server_memory']=json.loads(run(['exec',cid,'python','-c',"import json;print(json.dumps({l.split(':')[0]:l.split(':')[1].strip() for l in open('/proc/1/status') if l.startswith(('VmHWM:','VmRSS:','Threads:'))}))"]).stdout) data['image_id']=run(['image','inspect','--format','{{.Id}}',image]).stdout.strip() data['container_start_to_ready_ms']=ready_ms data['resources']={'cpu_quota':2,'memory_gib':16,'network':'none','published_ports':[],'client_in_same_cgroup':True} (out/(label+'.json')).write_text(json.dumps(data,indent=2)+'\n') print(label,json.dumps(data['summary']),flush=True) finally:run(['rm','-f',cid]) if __name__=='__main__':main()