/* estreamdraw.c version 20070120 D. J. Bernstein Public domain. Warning: This code is awful from many perspectives; I'm embarrassed to not be rewriting it before publishing it. */ #include #include #include #include #include #include #include #include #include #include #include #include #define TIMEOUT 20 /* milliseconds until next action */ int viewtype = 1; /* otherwise view machine */ double overhead = 0; #define YCFIXED(z) (750 - 200 * log10(z)) #define YCBAD (-300) #define YC(z) ((z > 0) ? YCFIXED((z) + overhead) : YCBAD) int selecttype = 3; double plustype = 0; #define TYPES 6 #define XT(j) ((590.0 / (TYPES - 1)) * (j) + 105) char *type[TYPES] = { "cipheragility" , "cipherlong" , "cipher1500" , "cipher576" , "cipher40" , "cipher40k" } ; char *typename[TYPES] = { "Encrypt many parallel streams in 256-byte blocks" , "Encrypt one long stream" , "Set up nonce and encrypt 1500-byte packet" , "Set up nonce and encrypt 576-byte packet" , "Set up nonce and encrypt 40-byte packet" , "Set up key, set up nonce, and encrypt 40-byte packet" } ; #define MAXMACHINES 64 char *machine[MAXMACHINES]; char *machinename[MAXMACHINES]; double machinelogcycles[MAXMACHINES]; int machines = 0; int selectmachine = 0; double plusmachine = 0; #define XM(j) ((590.0 / (machines - 1)) * (j) + 105) #define MAXCIPHERS 127 char *cipher[MAXCIPHERS]; char *ciphername[MAXCIPHERS]; char *ciphershortname[MAXCIPHERS]; int ciphers = 0; int selectcipher = 0; int selectsecondcipher = -1; char line[1000]; char word0[1000]; char word1[1000]; char word2[1000]; char word3[1000]; double cycles[TYPES][MAXMACHINES][MAXCIPHERS + 1]; void readdata(void) { int t; int m; int c; double z; while (fgets(line,sizeof line,stdin)) { if (sscanf(line,"%s %s %s %[^\n]",word0,word1,word2,word3) == 4 && !strcmp(word0,"machine")) { if (machines == MAXMACHINES) { fprintf(stderr,"fatal: too many machines\n"); exit(1); } machine[machines] = strdup(word1); if (!machine[machines]) { fprintf(stderr,"fatal: out of memory\n"); exit(1); } machinename[machines] = strdup(word3); if (!machinename[machines]) { fprintf(stderr,"fatal: out of memory\n"); exit(1); } ++machines; continue; } if (sscanf(line,"%s %s %[^\n]",word0,word1,word2) == 3 && !strcmp(word0,"machine")) { if (machines == MAXMACHINES) { fprintf(stderr,"fatal: too many machines\n"); exit(1); } machine[machines] = strdup(word1); if (!machine[machines]) { fprintf(stderr,"fatal: out of memory\n"); exit(1); } machinename[machines] = strdup(word1); if (!machinename[machines]) { fprintf(stderr,"fatal: out of memory\n"); exit(1); } ++machines; continue; } if (sscanf(line,"%s %s %s %[^\n]",word0,word1,word2,word3) == 4 && !strcmp(word0,"cipher")) { if (ciphers == MAXCIPHERS) { fprintf(stderr,"fatal: too many ciphers\n"); exit(1); } cipher[ciphers] = strdup(word1); if (!cipher[ciphers]) { fprintf(stderr,"fatal: out of memory\n"); exit(1); } ciphershortname[ciphers] = strdup(word2); if (!ciphershortname[ciphers]) { fprintf(stderr,"fatal: out of memory\n"); exit(1); } ciphername[ciphers] = strdup(word3); if (!ciphername[ciphers]) { fprintf(stderr,"fatal: out of memory\n"); exit(1); } if (!strcmp(cipher[ciphers],"256.AESCTR")) selectcipher = ciphers; ++ciphers; continue; } if (sscanf(line,"%s %s %s %lf",word0,word1,word2,&z) == 4) { for (t = 0;t < TYPES;++t) if (!strcmp(type[t],word0)) break; if (t < TYPES) { for (m = 0;m < machines;++m) if (!strcmp(machine[m],word1)) break; if (m < machines) { for (c = 0;c < ciphers;++c) if (!strcmp(cipher[c],word2)) break; if (c < ciphers) { if (!cycles[t][m][c]) cycles[t][m][c] = z; continue; } } } } } } void sortdata(void) { int i; int t; int j; int k; double z; double znum; char *s; for (j = 0;j < machines;++j) { z = 0; znum = 0; for (i = 0;i < TYPES;++i) for (k = 0;k < ciphers;++k) if (cycles[i][j][k]) { z += log(cycles[i][j][k]); znum += 1; } if (znum) z /= znum; machinelogcycles[j] = z; } for (j = 0;j < machines;++j) { t = j; for (k = j;k < machines;++k) if (machinelogcycles[k] > machinelogcycles[t]) t = k; if (t != j) { s = machine[j]; machine[j] = machine[t]; machine[t] = s; s = machinename[j]; machinename[j] = machinename[t]; machinename[t] = s; z = machinelogcycles[j]; machinelogcycles[j] = machinelogcycles[t]; machinelogcycles[t] = z; for (i = 0;i < TYPES;++i) for (k = 0;k < ciphers;++k) { z = cycles[i][j][k]; cycles[i][j][k] = cycles[i][t][k]; cycles[i][t][k] = z; } } } } XtAppContext a; Widget top; Widget draw; Display *display; Screen *screen; Window root; XGCValues gcv; GC gc; Pixmap pix; Colormap colormap; XColor color[MAXCIPHERS + 1]; int pos[MAXCIPHERS + 1]; double lastz[MAXCIPHERS + 1]; int lastzpos[MAXCIPHERS + 1]; double oldlastz[MAXCIPHERS + 1]; int oldlastzpos[MAXCIPHERS + 1]; void redraw(void) { int i; int j; int k; int z1; int z2; int t0; int t1; double fraction; int minz; int maxz; XSetForeground(display,gc,WhitePixelOfScreen(screen)); XFillRectangle(display,pix,gc,0,0,1024,768); minz = 768; maxz = 0; for (j = 0;j < machines;++j) for (k = 0;k < TYPES;++k) cycles[k][j][ciphers] = cycles[k][j][selectcipher]; ciphershortname[ciphers] = ciphershortname[selectcipher]; for (i = 0;i <= ciphers;++i) { oldlastz[i] = 0; lastz[i] = 0; if (i == selectcipher) continue; if (i == selectsecondcipher) XSetForeground(display,gc,color[ciphers].pixel); else XSetForeground(display,gc,color[i].pixel); if (viewtype) { if (plustype < 0) { t0 = selecttype + floor(plustype); t1 = selecttype + ceil(plustype); fraction = plustype - floor(plustype); } else { t0 = selecttype + ceil(plustype); t1 = selecttype + floor(plustype); fraction = ceil(plustype) - plustype; } for (j = 0;j < machines;++j) { if (j == selectmachine) { oldlastz[i] = YC(cycles[t0][j][i]); lastz[i] = YC(cycles[t1][j][i]); } if (cycles[t0][j][i] && cycles[t1][j][i]) { z1 = YC(cycles[t1][j][i]) * fraction + YC(cycles[t0][j][i]) * (1 - fraction); if (j == selectmachine) { if (z1 < minz) minz = z1; if (z1 > maxz) maxz = z1; } if (i % 10 < 5) { XFillRectangle(display,pix,gc,XM(j) - 3,z1 - 2,7,5); XFillRectangle(display,pix,gc,XM(j) - 2,z1 - 3,5,7); } else { XDrawRectangle(display,pix,gc,XM(j) - 3,z1 - 3,7,7); } } } for (j = 1;j < machines;++j) { z1 = YC(cycles[t1][j - 1][i]) * fraction + YC(cycles[t0][j - 1][i]) * (1 - fraction); z2 = YC(cycles[t1][j][i]) * fraction + YC(cycles[t0][j][i]) * (1 - fraction); if (cycles[t0][j - 1][i] && cycles[t0][j][i]) if (cycles[t1][j - 1][i] && cycles[t1][j][i]) { XDrawLine(display,pix,gc,XM(j - 1),z1,XM(j),z2); XDrawLine(display,pix,gc,XM(j - 1),z1 + 1,XM(j),z2 + 1); if (i == ciphers || i == selectsecondcipher) { XDrawLine(display,pix,gc,XM(j - 1),z1 - 1,XM(j),z2 - 1); XDrawLine(display,pix,gc,XM(j - 1),z1 + 2,XM(j),z2 + 2); } } } } else { if (plusmachine < 0) { t0 = selectmachine + floor(plusmachine); t1 = selectmachine + ceil(plusmachine); fraction = plusmachine - floor(plusmachine); } else { t0 = selectmachine + ceil(plusmachine); t1 = selectmachine + floor(plusmachine); fraction = ceil(plusmachine) - plusmachine; } for (k = 0;k < TYPES;++k) { if (k == selecttype) { oldlastz[i] = YC(cycles[k][t0][i]); lastz[i] = YC(cycles[k][t1][i]); } if (cycles[k][t0][i] && cycles[k][t1][i]) { z1 = YC(cycles[k][t1][i]) * fraction + YC(cycles[k][t0][i]) * (1 - fraction); if (k == selecttype) { if (z1 < minz) minz = z1; if (z1 > maxz) maxz = z1; } if (i % 10 < 5) { XFillRectangle(display,pix,gc,XT(k) - 3,z1 - 2,7,5); XFillRectangle(display,pix,gc,XT(k) - 2,z1 - 3,5,7); } else { XDrawRectangle(display,pix,gc,XT(k) - 3,z1 - 3,7,7); } } } for (k = 1;k < TYPES;++k) { z1 = YC(cycles[k - 1][t1][i]) * fraction + YC(cycles[k - 1][t0][i]) * (1 - fraction); z2 = YC(cycles[k][t1][i]) * fraction + YC(cycles[k][t0][i]) * (1 - fraction); if (cycles[k - 1][t0][i] && cycles[k][t0][i]) if (cycles[k - 1][t1][i] && cycles[k][t1][i]) { XDrawLine(display,pix,gc,XT(k - 1),z1,XT(k),z2); XDrawLine(display,pix,gc,XT(k - 1),z1 + 1,XT(k),z2 + 1); if (i == ciphers || i == selectsecondcipher) { XDrawLine(display,pix,gc,XT(k - 1),z1 - 1,XT(k),z2 - 1); XDrawLine(display,pix,gc,XT(k - 1),z1 + 2,XT(k),z2 + 2); } } } } } lastz[selectcipher] = lastz[ciphers]; for (i = 0;i < ciphers;++i) pos[i] = i; for (i = 0;i < ciphers;++i) { k = i; for (j = i;j < ciphers;++j) if (lastz[pos[j]] >= lastz[pos[k]]) k = j; if (k != i) { j = pos[k]; pos[k] = pos[i]; pos[i] = j; } } for (i = 0;i < ciphers;++i) lastzpos[pos[i]] = i % 4; lastzpos[ciphers] = lastzpos[selectcipher]; oldlastz[selectcipher] = oldlastz[ciphers]; for (i = 0;i < ciphers;++i) pos[i] = i; for (i = 0;i < ciphers;++i) { k = i; for (j = i;j < ciphers;++j) if (oldlastz[pos[j]] >= oldlastz[pos[k]]) k = j; if (k != i) { j = pos[k]; pos[k] = pos[i]; pos[i] = j; } } for (i = 0;i < ciphers;++i) oldlastzpos[pos[i]] = i % 4; oldlastzpos[ciphers] = oldlastzpos[selectcipher]; for (i = 0;i <= ciphers;++i) if (lastz[i] == YCBAD) lastzpos[i] = 500; for (i = 0;i <= ciphers;++i) if (oldlastz[i] == YCBAD) oldlastzpos[i] = 500; for (i = 0;i <= ciphers;++i) { if (i == selectsecondcipher) XSetForeground(display,gc,color[ciphers].pixel); else XSetForeground(display,gc,color[i].pixel); /* if (lastz[i] && oldlastz[i]) */ XDrawString(display,pix,gc ,XM(machines - 1) + 8 + (fraction * lastzpos[i] + (1 - fraction) * oldlastzpos[i]) * 70 ,fraction * lastz[i] + (1 - fraction) * oldlastz[i] + 12 ,ciphershortname[i],strlen(ciphershortname[i])); } XSetForeground(display,gc,BlackPixelOfScreen(screen)); maxz = YCFIXED(1); if (viewtype) XDrawLine(display,pix,gc,XM(selectmachine),minz,XM(selectmachine),maxz); else XDrawLine(display,pix,gc,XT(selecttype),minz,XT(selecttype),maxz); XDrawLine(display,pix,gc,XM(0),YCFIXED(1),XM(machines - 1),YCFIXED(1)); XDrawLine(display,pix,gc,XM(0),YCFIXED(10),XM(machines - 1),YCFIXED(10)); XDrawLine(display,pix,gc,XM(0),YCFIXED(100),XM(machines - 1),YCFIXED(100)); XDrawLine(display,pix,gc,XM(0),YCFIXED(1000),XM(machines - 1),YCFIXED(1000)); XDrawString(display,pix,gc,80,12 + YCFIXED(1),"1",1); XDrawString(display,pix,gc,80,12 + YCFIXED(3),"3",1); XDrawString(display,pix,gc,60,12 + YCFIXED(10),"10",2); XDrawString(display,pix,gc,60,12 + YCFIXED(30),"30",2); XDrawString(display,pix,gc,40,12 + YCFIXED(100),"100",3); XDrawString(display,pix,gc,40,12 + YCFIXED(300),"300",3); XDrawString(display,pix,gc,20,12 + YCFIXED(1000),"1000",4); XDrawString(display,pix,gc,120,45,typename[selecttype],strlen(typename[selecttype])); XDrawString(display,pix,gc,120,85,machinename[selectmachine],strlen(machinename[selectmachine])); if (cycles[selecttype][selectmachine][selectcipher]) if (overhead) sprintf(line,"%s + %.1f cycles/byte: %.1f cycles/byte",ciphername[selectcipher],overhead,cycles[selecttype][selectmachine][selectcipher] + overhead); else sprintf(line,"%s: %.1f cycles/byte",ciphername[selectcipher],cycles[selecttype][selectmachine][selectcipher]); else sprintf(line,"%s: not timed",ciphername[selectcipher],cycles[selecttype][selectmachine][selectcipher]); XDrawString(display,pix,gc,120,125,line,strlen(line)); XCopyArea(display,pix,XtWindow(draw),gc,0,0,1024,768,0,0); } void timeout(XtPointer client_data,XtIntervalId *id) { XtAppAddTimeOut(a,TIMEOUT,timeout,0); if (plustype > 0) { if (plustype > 1) plustype -= 3 * 0.03125; plustype -= 0.03125; redraw(); } if (plustype < 0) { if (plustype < -1) plustype += 3 * 0.03125; plustype += 0.03125; redraw(); } if (plusmachine > 0) { if (plusmachine > 1) plusmachine -= 3 * 0.03125; plusmachine -= 0.03125; redraw(); } if (plusmachine < 0) { if (plusmachine < -1) plusmachine += 3 * 0.03125; plusmachine += 0.03125; redraw(); } } void selectcipherdown(void) { int i; int k; double *z = cycles[selecttype][selectmachine]; k = selectcipher; for (i = 0;i < ciphers;++i) if (z[i] < z[selectcipher] || (z[i] == z[selectcipher] && i < selectcipher)) { if (k != selectcipher) if (z[i] < z[k] || (z[i] == z[k] && i < k)) continue; k = i; } selectcipher = k; } void selectcipherup(void) { int i; int k; double *z = cycles[selecttype][selectmachine]; k = selectcipher; for (i = 0;i < ciphers;++i) if (z[i] > z[selectcipher] || (z[i] == z[selectcipher] && i > selectcipher)) { if (k != selectcipher) if (z[i] > z[k] || (z[i] == z[k] && i > k)) continue; k = i; } selectcipher = k; } void input(Widget draw,XtPointer client_data,XmDrawingAreaCallbackStruct *cbk) { char buf[1]; KeySym k; if (cbk->event->type == KeyPress) { if (XLookupString((XKeyEvent *) cbk->event,buf,sizeof buf,&k,0) == 1) switch(k) { case 'q': XFlush(display); exit(0); case ']': if (viewtype) { if (selecttype + 1 < TYPES) { plustype -= 1; ++selecttype; } } else { if (selectmachine + 1 < machines) { plusmachine -= 1; ++selectmachine; } } redraw(); XSync(display,False); break; case '[': if (viewtype) { if (selecttype - 1 >= 0) { plustype += 1; --selecttype; } } else { if (selectmachine - 1 >= 0) { plusmachine += 1; --selectmachine; } } redraw(); XSync(display,False); break; case '=': selectsecondcipher = selectcipher; redraw(); XSync(display,False); break; case '-': selectsecondcipher = -1; redraw(); XSync(display,False); break; case 'o': if (overhead < 1000) ++overhead; redraw(); XSync(display,False); break; case 'O': if (overhead > 0) --overhead; redraw(); XSync(display,False); break; case 'j': case XK_KP_Down: selectcipherdown(); redraw(); XSync(display,False); break; case 'k': case XK_KP_Up: selectcipherup(); redraw(); XSync(display,False); break; case 'h': case XK_KP_Left: if (viewtype) { if (selectmachine > 0) --selectmachine; } else { if (selecttype > 0) --selecttype; } redraw(); XSync(display,False); break; case 'l': case XK_KP_Right: if (viewtype) { if (selectmachine < machines - 1) ++selectmachine; } else { if (selecttype < TYPES - 1) ++selecttype; } redraw(); XSync(display,False); break; case ' ': viewtype = !viewtype; redraw(); XSync(display,False); break; } } } void expose(Widget draw,XtPointer client_data,XmDrawingAreaCallbackStruct *cbk) { XCopyArea(cbk->event->xexpose.display,pix,cbk->window,gc,0,0,1024,768,0,0); } int main(int argc,char **argv) { unsigned short x; unsigned short y; int i; readdata(); sortdata(); if (!machines) { fprintf(stderr,"fatal: no machines\n"); exit(100); } if (!ciphers) { fprintf(stderr,"fatal: no ciphers\n"); exit(100); } selectmachine = machines - 1; /* XXX: catch various X errors */ top = XtOpenApplication(&a,"draw",0,0,&argc,argv,0,applicationShellWidgetClass,0,0); XtMakeResizeRequest(top,1024,768,&x,&y); draw = XtVaCreateWidget("draw",xmDrawingAreaWidgetClass,top,NULL); display = XtDisplay(draw); screen = XtScreen(draw); root = RootWindowOfScreen(screen); gcv.foreground = BlackPixelOfScreen(XtScreen(draw)); gc = XCreateGC(display,root,GCForeground,&gcv); pix = XCreatePixmap(display,root,1024,768,DefaultDepthOfScreen(screen)); colormap = DefaultColormap(display,DefaultScreen(display)); for (i = 0;i < ciphers;++i) { color[i].flags = DoRed | DoGreen | DoBlue; if (i % 5 == 0) { color[i].red = 65535; color[i].green = 0; color[i].blue = 0; } else if (i % 5 == 1) { color[i].red = 0; color[i].green = 40000; color[i].blue = 0; } else if (i % 5 == 2) { color[i].red = 0; color[i].green = 0; color[i].blue = 65535; } else if (i % 5 == 3) { color[i].red = 40000; color[i].green = 0; color[i].blue = 40000; } else { color[i].red = 0; color[i].green = 50000; color[i].blue = 50000; } XAllocColor(display,colormap,&color[i]); } color[i].flags = DoRed | DoGreen | DoBlue; color[i].red = 0; color[i].green = 0; color[i].blue = 0; XAllocColor(display,colormap,&color[i]); XSetFont(display,gc,XLoadFont(display,"-adobe-helvetica-bold-r-normal--34-240-100-100-p-182-iso8859-1")); XtAddCallback(draw,XmNexposeCallback,(XtCallbackProc) expose,0); XtAddCallback(draw,XmNinputCallback,(XtCallbackProc) input,0); XtAppAddTimeOut(a,TIMEOUT,(XtTimerCallbackProc) timeout,0); /* XtAppAddInput(a,0,(XtPointer) XtInputReadMask,get,0); */ XtManageChild(draw); XtRealizeWidget(top); redraw(); XtAppMainLoop(a); exit(111); }