6 let font = Glut.BITMAP_HELVETICA_12
7 let draw_string ?
(font=font) x y s
=
8 GlPix.raster_pos ~x ~y
();
9 String.iter
(fun c
-> Glut.bitmapCharacter ~
font ~c
:(Char.code c
)) s
14 ; loads
: int64
* int64
* int64
24 external get_nprocs
: unit -> int = "ml_get_nprocs"
25 external idletimeofday
: Unix.file_descr
-> int -> float array
27 external sysinfo
: unit -> sysinfo
= "ml_sysinfo"
28 external waitalrm
: unit -> unit = "ml_waitalrm"
29 external get_hz
: unit -> int = "ml_get_hz"
30 external setnice
: int -> unit = "ml_nice"
40 let hz = get_hz
() |> float
42 let jiffies_to_sec j
=
46 let ic = open_in
"/proc/uptime" in
47 let vals = Scanf.fscanf
ic "%f %f" (fun u i
-> (u
, i
)) in
51 let nprocs = get_nprocs
()
53 let rec parse_int_cont s pos
=
54 let slen = String.length s
in
60 if String.get s
pos = ' '
61 then succ
pos |> skipws
66 try String.index_from s
pos ' '
67 with Not_found
-> slen
69 let i = endpos - pos |> String.sub s
pos |> int_of_string
in
74 `more
(i, fun () -> succ
endpos |> parse_int_cont s
)
77 let rec tolist accu
= function
78 | `last
i -> i :: accu
79 | `more
(i, f
) -> f
() |> tolist (i :: accu
)
81 let index = String.index s ' '
in
82 let cpuname = String.sub s
0 index in
83 let vals = parse_int_cont s
(succ
index) |> tolist [] in
84 let vals = List.rev
|<
85 if List.length
vals < 7
87 0 :: 0 :: 0 :: 0 :: vals
91 cpuname, Array.of_list
vals
95 let ic = open_in
"/proc/stat" in
99 else (input_line
ic |> parse_cpul) :: accu
|> loop (pred
i)
101 let ret = loop nprocs [] in
107 Filename.dirname
|< Unix.readlink
"/proc/self/exe"
117 let rec furious_cycle i =
118 if not
!stop && i > 0
119 then pred
i |> furious_cycle
120 else (i, Unix.gettimeofday
())
124 let it = { Unix.it_interval
= t; it_value
= t } in
131 let sign = Sys.sigalrm
in
132 let oldh = Sys.signal
sign |< Sys.Signal_handle
handler in
133 let oldi = Unix.setitimer
Unix.ITIMER_REAL
it in
134 let oldbp = Unix.sigprocmask
Unix.SIG_BLOCK
[sign] in
135 let () = NP.waitalrm
() in
136 let () = stop := false in
137 let () = NP.setnice
20 in
138 let oldup = Unix.sigprocmask
Unix.SIG_UNBLOCK
[sign] in
139 let t1 = Unix.gettimeofday
() in
140 let n, t2
= furious_cycle max_int
in
141 let () = refdt := t2
-. t1 in
142 let () = lim := max_int
- n in
143 let () = if verbose
then
145 printf
"completed %d iterations in %f seconds@." !lim !refdt
147 let () = NP.setnice ~
-20 in
148 let _ = Unix.sigprocmask
Unix.SIG_UNBLOCK
oldup in
149 let _ = Unix.setitimer
Unix.ITIMER_REAL
oldi in
150 let _ = Unix.sigprocmask
Unix.SIG_BLOCK
oldbp in
151 let _ = Sys.signal
sign oldh in
160 let _, t2
= furious_cycle !lim in
165 Unix.gettimeofday
() |> loop
167 let _ = Thread.create
thf () in
174 [ "Amazing Piece of Code by insanely gifted programmer, Version 0.93"
175 ; "Motivation by: gzh and afs"
177 ] |> String.concat
"\n"
180 let interval = ref 15.0
181 let devpath = NP.getselfdir () |> Filename.concat
|< "itc" |> ref
186 let verbose = ref false
188 let ksampler = ref true
191 let sigway = ref true
194 let scalebar = ref false
196 let debug = ref false
197 let polys = ref false
198 let uptime = ref false
201 let l = String.length s
in
206 let d = String.make
n ' '
in
207 StringLabels.blit ~src
:s ~dst
:d
212 let dA tos s
{contents
=v
} = s ^
" (" ^ tos v ^
")"
213 let dF = dA |< sprintf
"%4.2f"
214 let dB = dA string_of_bool
215 let dcB = dA (fun b
-> not b
|> string_of_bool
)
216 let dI = dA string_of_int
217 let dS = dA (fun s
-> "`" ^
String.escaped s ^
"'")
220 "-" ^ opt
, Arg.Set_float r
, pad 9 "<float> " ^ doc
|> dF |< r
223 "-" ^ opt
, Arg.Set_int r
, pad 9 "<int> " ^ doc
|> dI |< r
226 "-" ^ opt
, Arg.Set r
, pad 9 "" ^ doc
|> dB |< r
229 "-" ^ opt
, Arg.Clear r
, pad 9 "" ^ doc
|> dcB |< r
232 "-" ^ opt
, Arg.Set_string r
, pad 9 "<string> " ^ doc
|> dS |< r
236 [ sF "f" freq "sampling frequency in seconds"
237 ; sF "D" delay "refresh delay in seconds"
238 ; sF "i" interval "history interval in seconds"
239 ; sI "p" pgrid "percent grid"
240 ; sI "s" sgrid "history grid"
243 ; sI "b" barw "bar width"
244 ; sI "B" bars "number of CPU bars"
245 ; sI "n" niceval "value to renice self on init"
246 ; sI "t" timer "timer frequency in herz"
247 ; sS "d" devpath "path to itc device"
248 ; cB "k" ksampler "do not use `/proc/stat'"
249 ; sB "g" gzh "gzh way (does not quite work yet)"
251 "use `/proc/uptime' instead of `/proc/stat` (UniProcessor only)"
252 ; sB "v" verbose "verbose"
253 ; sB "S" sigway "sigwait delay method"
254 ; sB "c" scalebar "constant bar width"
255 ; sB "P" polys "use polygons"
258 "don't know what to do with " ^ s
|> prerr_endline
;
265 let prev = ref 0.0 in
268 let b = Unix.gettimeofday
() in
276 module Delay
= struct
277 let sighandler signr
= ()
281 Sys.Signal_handle
sighandler |> Sys.set_signal
Sys.sigalrm
;
284 let l = if gzh then [Sys.sigprof
; Sys.sigvtalrm
] else [] in
285 Unix.sigprocmask
Unix.SIG_BLOCK
|< Sys.sigalrm
:: l |> ignore
;
288 let v = 1.0 /. float freq in
289 let t = { Unix.it_interval
= v; it_value
= v } in
290 let _ = Unix.setitimer
Unix.ITIMER_REAL
t in
297 try let _ = Unix.select
[] [] [] ~
-.1.0 in ()
298 with Unix.Unix_error
(Unix.EINTR
, _, _) -> ()
301 module Sampler
(T
: sig val nsamples
: int val freq : float end) =
303 let nsamples = T.nsamples + 1
304 let samples = Array.create
nsamples 0.0
310 let n = min
nsamples n in
315 let i = if i = nsamples then 0 else i in
316 Array.set
samples i v;
317 loop (succ
i) (pred j
)
319 let () = loop !head n in
320 let () = head := (!head + n) mod nsamples in
321 let () = active := min
(!active + n) nsamples in
326 let d = !head - !active in
331 let ry = ref (fun () -> assert false) in
337 ry := succ
i |> yield;
338 Some
((i + tail) mod nsamples |> Array.get
samples)
344 let update t1 t2 i1 i2
=
347 let isamples = d /. T.freq |> truncate
in
348 let l = 1.0 -. (i /. d) in
352 module type ViewSampler
=
354 val getyielder : unit -> unit -> float option
355 val update : float -> float -> float -> float -> unit
360 getyielder : unit -> unit -> float option;
361 update : float -> float -> float -> float -> unit;
374 val samplers
: sampler list
377 module View
(V
: sig val w : int val h : int end) = struct
382 let keyboard ~key ~x ~y
=
383 if key
= 27 || key
= Char.code 'q'
390 GlClear.clear
[`color
];
391 List.iter
(fun (display, _) -> display ()) !funcs;
397 List.iter
(fun (_, reshape) -> reshape w h) !funcs;
398 GlClear.clear
[`color
];
399 GlMat.mode `modelview
;
400 GlMat.load_identity
();
401 GlMat.mode `projection
;
402 GlMat.load_identity
();
403 GlMat.rotate ~y
:1.0 ~angle
:180.0 ();
404 GlMat.translate ~x
:~
-.1.0 ~y
:~
-.1.0 ();
405 GlMat.scale ~x
:2.0 ~y
:2.0 ();
406 Glut.postRedisplay
()
410 Glut.initDisplayMode ~double_buffer
:true ();
411 Glut.initWindowSize
V.w V.h
413 let _ = Glut.createWindow
"APC" in
414 Glut.displayFunc
display;
415 Glut.reshapeFunc
reshape;
416 Glut.keyboardFunc
keyboard;
417 GlDraw.color
(1.0, 1.0, 0.0)
422 let func = Glut.idleFunc
424 let run = Glut.mainLoop
427 module Bar
(T
: sig val barw : int val bars : int end) = struct
433 let sw = float T.barw /. float !Args.w
436 let fw = 3 * Glut.bitmapWidth
font (Char.code 'W'
)
438 let base = GlList.gen_lists ~len
:2 in
439 GlList.nth
base ~
pos:0,
440 GlList.nth
base ~
pos:1
447 let xl, xr
= getlr ki
in
449 let h = !vh - 15 - y in
450 let () = GlDraw.viewport
m y !bw h in
453 GlMat.load_identity
();
454 GlMat.rotate ~
y:1.0 ~angle
:180.0 ();
455 GlMat.translate ~x
:~
-.1.0 ~
y:~
-.1.0 ();
456 GlMat.scale ~x
:2.0 ~
y:(2.0 /. float h) ()
459 let mspace = barm * nbars in
460 let barh = (h + 66 - mspace / 2) / nbars |> float in
461 let barm = float barm in
466 let yt = yb
+. barm in
467 let yn = yt +. barh in
468 GlDraw.vertex2
(xl, yb
);
469 GlDraw.vertex2
(xl, yt);
470 GlDraw.vertex2
(xr
, yt);
471 GlDraw.vertex2
(xr
, yb
);
474 GlDraw.color
(0.0, 0.0, 0.0);
475 GlDraw.begins `quads
;
487 (float w *. sw |> truncate
) - m
492 GlList.begins
ksepsl `compile
;
496 GlList.begins isepsl `compile
;
501 let drawseps = function
502 | `k
-> GlList.call
ksepsl
503 | `
i -> GlList.call isepsl
507 let kload = min
!kload 1.0 |> max
0.0 in
508 let iload = min
!iload 1.0 |> max
0.0 in
509 let () = GlDraw.viewport
m 0 !bw 15 in
511 GlDraw.color
(1.0, 1.0, 1.0);
512 let kload = 100.0 *. kload in
513 let iload = 100.0 *. iload in
516 GlMat.load_identity
();
517 GlMat.scale ~x
:(1.0/.float !bw) ~
y:(1.0/.30.0) ()
519 let ix = !bw / 2 - fw |> float in
520 let kx = - (fw + !bw / 2) |> float in
521 let () = sprintf
"%5.2f" iload |> draw_string ix 0.0 in
522 let () = sprintf
"%5.2f" kload |> draw_string kx 0.0 in
523 let () = GlMat.pop
() in ()
527 let h = !vh - 15 - y in
528 let () = GlDraw.viewport
m y !bw h in
531 GlMat.load_identity
();
532 GlMat.rotate ~
y:1.0 ~angle
:180.0 ();
533 GlMat.translate ~x
:~
-.1.0 ~
y:~
-.1.0 ();
534 GlMat.scale ~x
:2.0 ~
y:(2.0 /. float h) ()
536 let drawbar load ki
=
537 let xl, xr
= getlr ki
in
539 GlDraw.begins `quads
;
540 GlDraw.vertex2
(xl, yb
);
541 GlDraw.vertex2
(xl, yt);
542 GlDraw.vertex2
(xr
, yt);
543 GlDraw.vertex2
(xr
, yb
);
546 let yt = float h *. load
in
548 let () = drawquad yb yt in
549 let () = GlDraw.color
(0.5, 0.5, 0.5) in
552 let () = drawquad yb yt in
555 GlDraw.color
(1.0, 1.0, 0.0);
557 GlDraw.color
(1.0, 0.0, 0.0);
562 let update kload'
iload'
=
563 kload := kload'
/. float NP.nprocs;
564 iload := iload'
/. float NP.nprocs;
568 module Graph
(V
: View
) = struct
569 let ox = if !Args.scalebar then 0 else !Args.barw
570 let sw = float V.w /. float (!Args.w - ox)
571 let sh = float V.h /. float !Args.h
572 let sx = float (V.x
- ox) /. float V.w
573 let sy = float V.y /. float V.h
578 let fw = 3 * Glut.bitmapWidth
font (Char.code '
%'
)
580 let scale = V.freq /. V.interval
582 let base = GlList.gen_lists ~len
:1 in
583 GlList.nth
base ~
pos:0
586 let ox = if !Args.scalebar then 0 else !Args.barw in
589 | `labels
-> (!vx + ox, !vy + 5, fw, !vh - 20)
590 | `graph
-> (!vx + fw + 5 + ox, !vy + 5, !vw - fw - 10, !vh - 20)
592 GlDraw.viewport x y w h
595 let scale = 1.0 /. float V.sgrid in
597 GlDraw.line_width
1.0;
598 GlDraw.color
(0.0, 1.0, 0.0);
599 GlDraw.begins `lines
;
602 let x = float i *. scale in
603 let x = if i = 0 then 0.0009 else x in
604 GlDraw.vertex ~
x ~
y:0.0 ();
605 GlDraw.vertex ~
x ~
y:1.0 ();
607 let lim = 100 / V.pgrid in
611 let y = (i * V.pgrid |> float) /. 100.0 in
612 let y = if i = lim then y -. 0.0009 else y in
613 GlDraw.vertex ~
x:0.0 ~
y ();
614 GlDraw.vertex ~
x:1.0 ~
y ();
620 GlDraw.color
(1.0, 1.0, 1.0);
623 for i = 0 to 100 / V.pgrid
625 let p = i * V.pgrid in
626 let y = float p /. ohp in
627 let s = Printf.sprintf
"%3d%%" p in
633 let wxsw = float (w - ox) *. sw
634 and hxsh
= float h *. sh in
635 vw := wxsw |> truncate
;
636 vh := hxsh
|> truncate
;
637 vx := wxsw *. sx |> truncate
;
638 vy := hxsh
*. sy |> truncate
;
639 GlList.begins
gridlist `compile
;
645 Glut.swapBuffers
|> oohz !Args.delay;
649 GlList.call
gridlist;
650 GlDraw.line_width
1.5;
654 GlDraw.color sampler
.color
;
657 then GlDraw.begins `line_strip
660 GlDraw.begins `polygon
;
661 GlDraw.vertex2
(0.0, 0.0);
664 let yield = sampler
.getyielder () in
665 let rec loop last
i =
668 let x = float i *. scale in
669 GlDraw.vertex ~
x ~
y ();
677 let x = float (pred
i) *. scale in
678 GlDraw.vertex ~
x ~
y:0.0 ()
683 List.iter
sample V.samplers
686 let funcs = display, reshape
689 let getplacements w h n barw =
690 let sr = float n |> sqrt
|> ceil
|> truncate
in
692 let r = if n mod sr = 0 then 0 else 1 in
704 let rec loop accu
i =
710 let xc = xc * vw + barw in
712 (i, xc, yc) :: accu
|> loop |< succ
i
719 let freq = !Args.freq
720 let nsamples = !Args.interval /. freq |> ceil
|> truncate
723 let placements, vw, vh = getplacements w h NP.nprocs !Args.barw in
725 let iget () = NP.idletimeofday fd
NP.nprocs in
729 let gks = NP.parse_stat () in
730 gks () |> Array.of_list
734 let crgraph (kaccu
, iaccu
) (i, x, y) =
735 let module Si
= Sampler
(S
) in
737 { getyielder = Si.getyielder
738 ; color
= (1.0, 1.0, 0.0)
742 let (kcalc
, ksampler) =
743 let module Sc
= Sampler
(S
) in
745 { getyielder = Sc.getyielder
746 ; color
= (1.0, 0.0, 0.0)
754 let f d'
= d := d'
in
755 let () = Gzh.gen f in
756 fun _ _ _ -> (0.0, !d)
760 let (u1
, i1
) = NP.parse_uptime () in
764 let (u2
, i2
) = NP.parse_uptime () in
766 and di
= i2
-. !i1
in
771 let i'
= if i = NP.nprocs then 0 else succ
i in
773 let g ks = Array.get
ks i'
|> snd
|> Array.get
|< n in
774 let i1 = g ks |> ref in
777 let i1'
= NP.jiffies_to_sec !i1
778 and i2'
= NP.jiffies_to_sec i2 in
791 let interval = !Args.interval
792 let pgrid = !Args.pgrid
793 let sgrid = !Args.sgrid
796 then [isampler; ksampler]
800 let module Graph
= Graph
(V
) in
802 let i1 = Array.get
is i |> ref in
804 let i2 = Array.get
is i in
811 then (i, kcalc
, ksampler, Graph.funcs) :: kaccu
814 kaccu, (i, icalc, isampler, Graph.funcs) :: iaccu
816 let kl, il
= List.fold_left
crgraph ([], []) placements in
817 ((if kl == [] then (fun () -> [||]) else kget), kl), (iget, il
)
821 Unix.openfile path
[Unix.O_RDONLY
] 0
823 | Unix.Unix_error
(Unix.ENODEV
, s1
, s2
) ->
824 eprintf
"Could not open ITC device %S:\n%s(%s): %s)\n"
825 path s1 s2
|< Unix.error_message
Unix.ENODEV
;
826 eprintf
"(perhaps the module is not loaded?)@.";
829 | Unix.Unix_error
(Unix.ENOENT
, s1
, s2
) ->
830 eprintf
"Could not open ITC device %S:\n%s(%s): %s\n"
831 path s1 s2
|< Unix.error_message
Unix.ENOENT
;
835 let _ = Glut.init [|""|] in
836 let () = Args.init () in
837 let () = if !Args.gzh then Gzh.init !Args.verbose in
838 let () = Delay.init !Args.timer !Args.gzh in
839 let () = if !Args.niceval != 0 then NP.setnice
!Args.niceval in
842 let fd = opendev !Args.devpath in
843 let module FullV
= View
(struct let w = w let h = h end) in
844 let () = FullV.init () in
845 let (kget, kfuncs
), (iget, ifuncs
) = create fd w h in
847 Bar
(struct let barw = !Args.barw let bars = !Args.bars end)
850 FullV.add (Bar.display, Bar.reshape);
851 List.iter
(fun (_, _, _, gfuncs
) -> FullV.add gfuncs
) kfuncs
;
852 List.iter
(fun (_, _, _, gfuncs
) -> FullV.add gfuncs
) ifuncs
;
855 let t2 = Unix.gettimeofday
() in
861 let rec loop2 load
s = function
863 | (nr
, calc, sampler, _) :: rest
->
864 let i1, i2 = calc s t1 t2 in
865 let thisload = 1.0 -. ((i2 -. i1) /. dt) in
869 ("cpu load(" ^ string_of_int nr ^
"): "
870 ^
(thisload *. 100.0 |> string_of_float
)
873 let load = load +. thisload in
874 sampler.update t1 t2 i1 i2;
877 let iload = loop2 0.0 is ifuncs
in
878 let kload = loop2 0.0 ks kfuncs
in
882 iload |> string_of_float
|> prerr_endline
;
883 kload |> string_of_float
|> prerr_endline
;
886 Bar.update kload iload;
888 FullV.func (Some
(loop t2))
892 FullV.func (Some
(Unix.gettimeofday
() |> loop));
898 | Unix.Unix_error
(e
, s1
, s2
) ->
899 eprintf
"%s(%s): %s@." s1 s2
|< Unix.error_message e
902 Printexc.to_string exn
|> eprintf
"Exception: %s@."