tricu

A lazy functional language based on Tree Calculus
Log | Files | Refs | README | LICENSE

binding_failure_isolate.py (4299B)


      1 #!/usr/bin/env python3
      2 """Bounded prefix isolation of the unpublished compiler's pipelines stall."""
      3 import argparse,json,re,time
      4 from pathlib import Path
      5 from float_multiply import Runner,sha
      6 from binding_substitution import ROOT
      7 from bundle_dag import read,Intern
      8 
      9 
     10 def main():
     11     p=argparse.ArgumentParser(description=__doc__)
     12     p.add_argument('tricu',type=Path);p.add_argument('--directory',type=Path,required=True)
     13     p.add_argument('--candidate',type=Path,default=Path('/tmp/tricu-binding-compiler-first'))
     14     p.add_argument('--failed',type=Path,default=Path('/tmp/tricu-binding-compiler-measure'))
     15     args=p.parse_args();root=args.directory.resolve();root.mkdir(parents=True,exist_ok=False)
     16     workspace=root/'workspace';workspace.mkdir();runner=Runner(args.tricu,root,600,memory_mib=2048)
     17     prior=json.loads((args.candidate/'report.json').read_text());assert prior['complete']
     18     assert sha(args.candidate/'candidate.arboricx')==prior['candidate_sha256']
     19     report=dict(complete=False,harness_sha256=sha(Path(__file__)),candidate_sha256=prior['candidate_sha256'],
     20                 runtime_sha256=sha(args.tricu),dependencies=[],attempts=[])
     21     try:
     22         tools={role:runner.imported(path,role) for role,path in [('accepted',ROOT/'bootstrap/build-stable.arboricx'),('candidate',args.candidate/'candidate.arboricx')]}
     23         for alias in ['native_math','kernels','layouts']:
     24             graphs={};intern=Intern()
     25             for role in tools:
     26                 store=args.failed/f'compile-0-{role}-store'
     27                 manifest=(store/'cache/source-build'/alias).read_text().split('\t')[2]
     28                 bundle=root/(role+'-'+alias+'.arboricx')
     29                 runner.run('export-'+role+alias,['export','--store',store,'--module',manifest,'--output',bundle])
     30                 _,_,nodes,exports,_=read(bundle);ids=intern.graph(nodes)
     31                 graphs[role]={name:ids[i] for name,i in exports.items()}
     32             different=[name for name in graphs['accepted'] if graphs['accepted'][name]!=graphs['candidate'][name]]
     33             report['dependencies'].append(dict(alias=alias,changed_exports=different))
     34             pin=runner.imported(root/('accepted-'+alias+'.arboricx'),'dep-'+alias)
     35             (workspace/(alias+'.tri')).write_text('!export * from '+pin+'\n')
     36         source=(args.failed/'workspace/pipelines.tri').read_text()
     37         positions=[m.start() for m in re.finditer(r'^[A-Za-z][A-Za-z0-9_]*[^\n]*=',source,re.M)]
     38         names=[re.match(r'[A-Za-z][A-Za-z0-9_]*',source[pos:])[0] for pos in positions]
     39         report['definitions']=names
     40         def attempt(count,role):
     41             text=source[:positions[count]] if count<len(positions) else source
     42             (workspace/'probe.tri').write_text(text)
     43             label=f'{role}-{count}';start=time.monotonic()
     44             try:
     45                 runner.run(label,['compile','--file',workspace/'probe.tri','--toolchain',tools[role],
     46                            '--tool-store',runner.store,'--store',runner.store,'--output',root/(label+'.arboricx'),
     47                            '--compile-timeout','45'],55)
     48                 row=dict(role=role,count=count,last=names[count-1],outcome='complete',seconds=time.monotonic()-start,
     49                          rts=runner.records[-1]['rts_process'])
     50             except RuntimeError as error:
     51                 if str(error)!='wall-time guard exceeded':raise
     52                 row=dict(role=role,count=count,last=names[count-1],outcome='timeout',seconds=time.monotonic()-start)
     53             report['attempts'].append(row);print(json.dumps(row),flush=True)
     54             return row['outcome']=='complete'
     55         assert attempt(len(names),'accepted')
     56         if attempt(len(names),'candidate'):
     57             report['complete']=True;report['reproduced']=False;return
     58         lo,hi=0,len(names)
     59         while hi-lo>1:
     60             mid=(lo+hi)//2
     61             if attempt(mid,'candidate'):lo=mid
     62             else:hi=mid
     63         report['boundary']=dict(completed_prefix=lo,first_timeout_prefix=hi,definition=names[hi-1])
     64         # Verify this boundary against accepted lowering too.
     65         assert attempt(hi,'accepted')
     66         report['complete']=True;report['reproduced']=True
     67     finally:(root/'report.json').write_text(json.dumps(report,indent=2)+'\n')
     68 
     69 
     70 if __name__=='__main__':main()