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"
31 external delay
: float -> unit = "ml_delay"
32 external is_winnt
: unit -> bool = "ml_is_winnt"
34 let winnt = is_winnt
()
44 let hz = get_hz
() |> float
46 let jiffies_to_sec j
=
50 let ic = open_in
"/proc/uptime" in
51 let vals = Scanf.fscanf
ic "%f %f" (fun u i
-> (u
, i
)) in
55 let nprocs = get_nprocs
()
57 let rec parse_int_cont s pos
=
58 let slen = String.length s
in
64 if String.get s
pos = ' '
65 then succ
pos |> skipws
70 try String.index_from s
pos ' '
71 with Not_found
-> slen
73 let i = endpos - pos |> String.sub s
pos |> int_of_string
in
78 `more
(i, fun () -> succ
endpos |> parse_int_cont s
)
81 let rec tolist accu
= function
82 | `last
i -> i :: accu
83 | `more
(i, f
) -> f
() |> tolist (i :: accu
)
85 let index = String.index s ' '
in
86 let cpuname = String.sub s
0 index in
87 let vals = parse_int_cont s
(succ
index) |> tolist [] in
88 let vals = List.rev
|<
89 if List.length
vals < 7
91 0 :: 0 :: 0 :: 0 :: vals
95 cpuname, Array.of_list
vals
101 let ia = idletimeofday
Unix.stdin
nprocs in
102 let rec convert accu total n
=
105 let t = total
*. hz |> truncate
in
106 let a = "cpu", Array.make
7 t in
109 let i = Array.get
ia n
in
110 let total = total +. i in
111 let t = i *. hz |> truncate
in
112 let v = "cpu" ^ string_of_int n
, Array.make
7 t in
113 convert |< v :: accu
|< total |< succ n
118 let ic = open_in
"/proc/stat" in
119 let rec loop i accu
=
122 else (input_line
ic |> parse_cpul) :: accu
|> loop (pred
i)
124 let ret = loop nprocs [] in
130 Filename.dirname
|< Unix.readlink
"/proc/self/exe"
137 [ "Amazing Piece of Code by insanely gifted programmer, Version 0.95"
138 ; "Motivation by: gzh and afs"
140 ] |> String.concat
"\n"
143 let interval = ref 15.0
144 let devpath = NP.getselfdir () |> Filename.concat
|< "itc" |> ref
149 let verbose = ref false
151 let ksampler = ref true
154 let sigway = ref true
157 let scalebar = ref false
159 let debug = ref false
161 let uptime = ref false
163 let labels = ref true
164 let mgrid = ref false
167 let l = String.length s
in
172 let d = String.make n ' '
in
173 StringLabels.blit ~src
:s ~dst
:d
178 let dA tos s
{contents
=v} = s ^
" (" ^ tos
v ^
")"
179 let dF = dA |< sprintf
"%4.2f"
180 let dB = dA string_of_bool
181 let dcB = dA (fun b
-> not b
|> string_of_bool
)
182 let dI = dA string_of_int
183 let dS = dA (fun s
-> "`" ^
String.escaped s ^
"'")
186 "-" ^ opt
, Arg.Set_float r
, pad 9 "<float> " ^ doc
|> dF |< r
189 "-" ^ opt
, Arg.Set_int r
, pad 9 "<int> " ^ doc
|> dI |< r
192 "-" ^ opt
, Arg.Set r
, pad 9 "" ^ doc
|> dB |< r
195 "-" ^ opt
, Arg.Clear r
, pad 9 "" ^ doc
|> dcB |< r
198 "-" ^ opt
, Arg.Set_string r
, pad 9 "<string> " ^ doc
|> dS |< r
202 [ sF "f" freq "sampling frequency in seconds"
203 ; sF "D" delay "refresh delay in seconds"
204 ; sF "i" interval "history interval in seconds"
205 ; sI "p" pgrid "percent grid"
206 ; sI "s" sgrid "history grid"
209 ; sI "b" barw "bar width"
210 ; sI "B" bars "number of CPU bars"
211 ; sI "n" niceval "value to renice self on init"
212 ; sI "t" timer "timer frequency in herz"
213 ; sS "d" devpath "path to itc device"
214 ; cB "k" ksampler |< "do not use kernel sampler"
215 ^
(if NP.winnt then "" else " (`/proc/[stat|uptime]')")
216 ; sB "g" gzh "gzh way (does not quite work yet)"
218 "use `uptime' instead of `stat' as kernel sampler (UP only)"
219 ; sB "v" verbose "verbose"
220 ; sB "S" sigway "sigwait delay method"
221 ; sB "c" scalebar "constant bar width"
222 ; sB "P" poly "use filled area instead of lines"
223 ; sB "I" icon "use icon (hack)"
224 ; cB "l" labels "do not draw labels"
225 ; sB "m" mgrid "moving grid"
232 let nixopts = ["-n"; "-u"; "-d"; "-I"; "-S"; "-g"] in
233 prerr_endline
"Only kernel sampler is available on Windows";
234 List.filter
(fun (s
, _
, _
) -> List.mem s
nixopts |> not
) opts
241 "don't know what to do with " ^ s
|> prerr_endline
;
252 let rec furious_cycle i =
253 if not
!stop && i > 0
254 then pred
i |> furious_cycle
255 else (i, Unix.gettimeofday
())
259 let it = { Unix.it_interval
= t; it_value
= t } in
267 let sign = Sys.sigalrm
in
268 let oldh = Sys.signal
sign |< Sys.Signal_handle
handler in
269 let oldi = Unix.setitimer
Unix.ITIMER_REAL
it in
270 let oldbp = Unix.sigprocmask
Unix.SIG_BLOCK
[sign] in
271 let () = NP.waitalrm
() in
272 let () = stop := false in
273 let oldup = Unix.sigprocmask
Unix.SIG_UNBLOCK
[sign] in
274 let t1 = Unix.gettimeofday
() in
275 let n, t2
= furious_cycle max_int
in
276 let () = refdt := t2
-. t1 in
277 let () = lim := tries * (max_int
- n) in
278 let () = if verbose then
280 printf
"Completed %d iterations in %f seconds@." !lim !refdt
282 let _ = Unix.sigprocmask
Unix.SIG_UNBLOCK
oldup in
283 let _ = Unix.setitimer
Unix.ITIMER_REAL
oldi in
284 let _ = Unix.sigprocmask
Unix.SIG_BLOCK
oldbp in
285 let _ = Sys.signal
sign oldh in
295 let _, t2
= furious_cycle !lim in
298 if !Args.debug && !l > 10
301 printf
"Completed %d iterations in %f seconds load %f@."
302 !lim dt |< !refdt /. dt;
309 Unix.gettimeofday
() |> loop
311 let _ = Thread.create
thf () in
317 let prev = ref 0.0 in
320 let b = Unix.gettimeofday
() in
328 module Delay
= struct
329 let sighandler signr
= ()
331 let winfreq = ref 0.0
336 winfreq := 1.0 /. float freq
339 Sys.Signal_handle
sighandler |> Sys.set_signal
Sys.sigalrm
;
342 let l = if gzh then [Sys.sigprof
; Sys.sigvtalrm
] else [] in
343 Unix.sigprocmask
Unix.SIG_BLOCK
|< Sys.sigalrm
:: l |> ignore
;
346 let v = 1.0 /. float freq in
347 let t = { Unix.it_interval
= v; it_value
= v } in
348 let _ = Unix.setitimer
Unix.ITIMER_REAL
t in
362 try let _ = Unix.select
[] [] [] ~
-.1.0 in ()
363 with Unix.Unix_error
(Unix.EINTR
, _, _) -> ()
370 getyielder
: unit -> unit -> float option;
371 update
: float -> float -> float -> float -> unit;
374 module Sampler
(T
: sig val nsamples
: int val freq : float end) =
376 let nsamples = T.nsamples + 1
377 let samples = Array.create
nsamples 0.0
383 let n = min
nsamples n in
388 let i = if i = nsamples then 0 else i in
389 Array.set
samples i v;
390 loop (succ
i) (pred j
)
392 let () = loop !head n in
393 let () = head := (!head + n) mod nsamples in
394 let () = active := min
(!active + n) nsamples in
400 let d = !head - !active in
405 let ry = ref (fun () -> assert false) in
411 ry := succ
i |> yield;
412 Some
((i + tail) mod nsamples |> Array.get
samples)
419 let update t1 t2 i1 i2
=
422 let isamples = d /. T.freq |> truncate
in
423 let l = 1.0 -. (i /. d) in
428 module type ViewSampler
=
430 val getyielder : unit -> unit -> float option
431 val update : float -> float -> float -> float -> unit
444 val samplers
: sampler list
447 module View
(V
: sig val w : int val h : int end) = struct
452 let keyboard ~key ~x ~y
=
453 if key
= 27 || key
= Char.code 'q'
457 funcs := dri
:: !funcs
460 GlClear.clear
[`color
];
461 List.iter
(fun (display, _, _) -> display ()) !funcs;
467 List.iter
(fun (_, reshape, _) -> reshape w h) !funcs;
468 GlClear.clear
[`color
];
469 GlMat.mode `modelview
;
470 GlMat.load_identity
();
471 GlMat.mode `projection
;
472 GlMat.load_identity
();
473 GlMat.rotate ~y
:1.0 ~angle
:180.0 ();
474 GlMat.translate ~x
:~
-.1.0 ~y
:~
-.1.0 ();
475 GlMat.scale ~x
:2.0 ~y
:2.0 ();
476 Glut.postRedisplay
()
480 Glut.initDisplayMode ~double_buffer
:true ();
481 Glut.initWindowSize
V.w V.h
483 let winid = Glut.createWindow
"APC" in
484 Glut.displayFunc
display;
485 Glut.reshapeFunc
reshape;
486 Glut.keyboardFunc
keyboard;
487 GlDraw.color
(1.0, 1.0, 0.0);
491 let inc () = List.iter
(fun (_, _, inc) -> inc ()) !funcs
492 let update = Glut.postRedisplay
493 let func = Glut.idleFunc
494 let run = Glut.mainLoop
497 module Bar
(T
: sig val barw : int val bars : int end) = struct
503 let sw = float T.barw /. float !Args.w
506 let fw = 3 * Glut.bitmapWidth
font (Char.code 'W'
)
508 let base = GlList.gen_lists ~len
:2 in
509 GlList.nth
base ~
pos:0,
510 GlList.nth
base ~
pos:1
517 let xl, xr
= getlr ki
in
519 let h = !vh - 15 - y in
520 let () = GlDraw.viewport
m y !bw h in
523 GlMat.load_identity
();
524 GlMat.rotate ~
y:1.0 ~angle
:180.0 ();
525 GlMat.translate ~x
:~
-.1.0 ~
y:~
-.1.0 ();
526 GlMat.scale ~x
:2.0 ~
y:(2.0 /. float h) ()
529 let mspace = barm * nbars in
530 let barh = (h + 66 - mspace / 2) / nbars |> float in
531 let barm = float barm in
536 let yt = yb
+. barm in
537 let yn = yt +. barh in
538 GlDraw.vertex2
(xl, yb
);
539 GlDraw.vertex2
(xl, yt);
540 GlDraw.vertex2
(xr
, yt);
541 GlDraw.vertex2
(xr
, yb
);
544 GlDraw.color
(0.0, 0.0, 0.0);
545 GlDraw.begins `quads
;
557 (float w *. sw |> truncate
) - m
562 GlList.begins
ksepsl `compile
;
566 GlList.begins isepsl `compile
;
571 let drawseps = function
572 | `k
-> GlList.call
ksepsl
573 | `
i -> GlList.call isepsl
577 let kload = min
!kload 1.0 |> max
0.0 in
578 let iload = min
!iload 1.0 |> max
0.0 in
579 let () = GlDraw.viewport
m 0 !bw 15 in
581 GlDraw.color
(1.0, 1.0, 1.0);
582 let kload = 100.0 *. kload in
583 let iload = 100.0 *. iload in
586 GlMat.load_identity
();
587 GlMat.scale ~x
:(1.0/.float !bw) ~
y:(1.0/.30.0) ()
589 let ix = !bw / 2 - fw |> float in
590 let kx = - (fw + !bw / 2) |> float in
591 let () = sprintf
"%5.2f" iload |> draw_string ix 0.0 in
592 let () = sprintf
"%5.2f" kload |> draw_string kx 0.0 in
593 let () = GlMat.pop
() in ()
597 let h = !vh - 15 - y in
598 let () = GlDraw.viewport
m y !bw h in
601 GlMat.load_identity
();
602 GlMat.rotate ~
y:1.0 ~angle
:180.0 ();
603 GlMat.translate ~x
:~
-.1.0 ~
y:~
-.1.0 ();
604 GlMat.scale ~x
:2.0 ~
y:(2.0 /. float h) ()
606 let drawbar load ki
=
607 let xl, xr
= getlr ki
in
609 GlDraw.begins `quads
;
610 GlDraw.vertex2
(xl, yb
);
611 GlDraw.vertex2
(xl, yt);
612 GlDraw.vertex2
(xr
, yt);
613 GlDraw.vertex2
(xr
, yb
);
616 let yt = float h *. load
in
618 let () = drawquad yb yt in
619 let () = GlDraw.color
(0.5, 0.5, 0.5) in
622 let () = drawquad yb yt in
625 GlDraw.color
(1.0, 1.0, 0.0);
627 GlDraw.color
(1.0, 0.0, 0.0);
632 let update kload'
iload'
=
633 kload := kload'
/. float NP.nprocs;
634 iload := iload'
/. float NP.nprocs;
638 module Graph
(V
: View
) = struct
639 let ox = if !Args.scalebar then 0 else !Args.barw
640 let sw = float V.w /. float (!Args.w - ox)
641 let sh = float V.h /. float !Args.h
642 let sx = float (V.x
- ox) /. float V.w
643 let sy = float V.y /. float V.h
648 let scale = V.freq /. V.interval
649 let gscale = 1.0 /. float V.sgrid
654 then 3 * Glut.bitmapWidth
font (Char.code '
%'
), 20
658 let base = GlList.gen_lists ~len
:1 in
659 GlList.nth
base ~
pos:0
662 let ox = if !Args.scalebar then 0 else !Args.barw in
665 | `
labels -> (!vx + ox, !vy + 5, fw, !vh - fh
)
666 | `graph
-> (!vx + fw + 5 + ox, !vy + 5, !vw - fw - 10, !vh - fh
)
668 GlDraw.viewport x y w h;
674 let x = if i = 0 then 0.0009 else float i *. gscale in
675 GlDraw.vertex ~
x ~
y:0.0 ();
676 GlDraw.vertex ~
x ~
y:1.0 ();
682 GlDraw.line_width
1.0;
683 GlDraw.color
(0.0, 1.0, 0.0);
684 GlDraw.begins `lines
;
688 GlDraw.vertex2
(0.0009, 0.0);
689 GlDraw.vertex2
(0.0009, 1.0);
690 GlDraw.vertex2
(1.0000, 0.0);
691 GlDraw.vertex2
(1.0000, 1.0);
697 let lim = 100 / V.pgrid in
700 let y = (i * V.pgrid |> float) /. 100.0 in
701 let y = if i = lim then y -. 0.0009 else y in
702 GlDraw.vertex ~
x:0.0 ~
y ();
703 GlDraw.vertex ~
x:1.0 ~
y ();
706 let () = GlDraw.ends
() in
711 GlDraw.color
(1.0, 1.0, 1.0);
713 for i = 0 to 100 / V.pgrid
715 let p = i * V.pgrid in
716 let y = float p /. ohp in
717 let s = Printf.sprintf
"%3d%%" p in
724 let wxsw = float (w - ox) *. sw
725 and hxsh
= float h *. sh in
726 vw := wxsw |> truncate
;
727 vh := hxsh
|> truncate
;
728 vx := wxsw *. sx |> truncate
;
729 vy := hxsh
*. sy |> truncate
;
730 GlList.begins
gridlist `compile
;
736 Glut.swapBuffers
|> oohz !Args.delay;
739 let inc () = incr
nsamples
742 GlDraw.line_width
1.0;
743 GlDraw.color
(0.0, 1.0, 0.0);
744 GlDraw.begins `lines
;
746 ((pred
!nsamples |> float) *. scale /. gscale |> modf
|> fst
) *. gscale
748 for i = 0 to pred
V.sgrid
750 let x = offset +. float i *. gscale in
751 GlDraw.vertex ~
x ~
y:0.0 ();
752 GlDraw.vertex ~
x ~
y:1.0 ();
758 GlList.call
gridlist;
760 if !Args.mgrid then mgrid ();
761 GlDraw.line_width
1.5;
764 GlDraw.color sampler
.color
;
767 then GlDraw.begins `line_strip
770 GlDraw.begins `polygon
;
771 GlDraw.vertex2
(0.0, 0.0);
774 let yield = sampler
.getyielder () in
775 let rec loop last
i =
778 let x = float i *. scale in
779 GlDraw.vertex ~
x ~
y ();
787 let x = float (pred
i) *. scale in
788 GlDraw.vertex ~
x ~
y:0.0 ()
793 List.iter
sample V.samplers
;
796 let funcs = display, reshape, inc
799 let getplacements w h n barw =
800 let sr = float n |> sqrt
|> ceil
|> truncate
in
802 let r = if n mod sr = 0 then 0 else 1 in
814 let rec loop accu
i =
820 let xc = xc * vw + barw in
822 (i, xc, yc) :: accu
|> loop |< succ
i
829 let freq = !Args.freq
830 let nsamples = !Args.interval /. freq |> ceil
|> truncate
833 let placements, vw, vh = getplacements w h NP.nprocs !Args.barw in
835 let iget () = NP.idletimeofday fd
NP.nprocs in
839 let gks = NP.parse_stat () in
840 gks () |> Array.of_list
844 let crgraph (kaccu
, iaccu
, gaccu
) (i, x, y) =
845 let module Si
= Sampler
(S
) in
847 { getyielder = Si.getyielder
848 ; color
= (1.0, 1.0, 0.0)
852 let (kcalc
, ksampler) =
853 let module Sc
= Sampler
(S
) in
855 { getyielder = Sc.getyielder
856 ; color
= (1.0, 0.0, 0.0)
864 let f d'
= d := d'
in
865 let () = Gzh.gen f in
866 fun _ _ _ -> (0.0, !d)
870 let (u1
, i1
) = NP.parse_uptime () in
874 let (u2
, i2
) = NP.parse_uptime () in
876 and di
= i2
-. !i1
in
881 let i'
= if i = NP.nprocs then 0 else succ
i in
883 let g ks = Array.get
ks i'
|> snd
|> Array.get
|< n in
884 let i1 = g ks |> ref in
887 let i1'
= NP.jiffies_to_sec !i1
888 and i2'
= NP.jiffies_to_sec i2 in
901 let interval = !Args.interval
902 let pgrid = !Args.pgrid
903 let sgrid = !Args.sgrid
906 then [isampler; ksampler]
910 let module Graph
= Graph
(V
) in
912 let i1 = Array.get
is i |> ref in
914 let i2 = Array.get
is i in
921 then (i, kcalc
, ksampler) :: kaccu
924 kaccu, (i, icalc, isampler) :: iaccu
, Graph.funcs :: gaccu
926 let kl, il
, gl
= List.fold_left
crgraph ([], [], []) placements in
927 ((if kl == [] then (fun () -> [||]) else kget), kl), (iget, il
), gl
935 Unix.openfile path
[Unix.O_RDONLY
] 0
937 | Unix.Unix_error
(Unix.ENODEV
, s1
, s2
) ->
938 eprintf
"Could not open ITC device %S:\n%s(%s): %s)\n"
939 path s1 s2
|< Unix.error_message
Unix.ENODEV
;
940 eprintf
"(perhaps the module is not loaded?)@.";
943 | Unix.Unix_error
(Unix.ENOENT
, s1
, s2
) ->
944 eprintf
"Could not open ITC device %S:\n%s(%s): %s\n"
945 path s1 s2
|< Unix.error_message
Unix.ENOENT
;
949 eprintf
"Could not open ITC device %S:\n%s\n"
950 path
|< Printexc.to_string exn
;
954 let module X
= struct external seticon : string -> unit = "ml_seticon" end in
956 let data = String.create |< 32*len + 2*4 in
961 and a = Char.chr
a in
962 let s = String.create len in
968 x + 0 |> String.set
s |< b;
969 x + 1 |> String.set
s |< g;
970 x + 2 |> String.set
s |< r;
971 x + 3 |> String.set
s |< a;
977 let el = line 0x00 0x00 0x00 0xff
978 and kl = line 0xff 0x00 0x00 0xff
979 and il
= line 0xff 0xff 0x00 0xff in
981 let src = l and dst
= data and src_pos
= 0 in
982 let rec loop n dst_pos
=
986 StringLabels.blit ~
src ~src_pos ~dst ~dst_pos ~
len;
987 pred
n |> loop |< dst_pos
+ len
990 (ey
- sy) |> loop |< (32 - ey
) * len + 4*2
993 let iy = iload *. 32.0 |> ceil
|> truncate
|> max
0 |> min
32
994 and ky
= kload *. 32.0 |> ceil
|> truncate
|> max
0 |> min
32 in
997 then (fill kl 0 ky
; fill il ky
iy; iy)
998 else (fill kl 0 ky
; ky
)
1005 let _ = Glut.init [|""|] in
1006 let () = Args.init () in
1007 let () = if !Args.gzh then Gzh.init !Args.verbose in
1008 let () = Delay.init !Args.timer !Args.gzh in
1009 let () = if !Args.niceval != 0 then NP.setnice
!Args.niceval in
1012 let fd = opendev !Args.devpath in
1013 let module FullV
= View
(struct let w = w let h = h end) in
1014 let _winid = FullV.init () in
1015 let (kget, kfuncs
), (iget, ifuncs
), gl
= create fd w h in
1017 List.iter
FullV.add gl
;
1021 Bar
(struct let barw = !Args.barw let bars = !Args.bars end)
1023 FullV.add (Bar.display, Bar.reshape, fun _ -> ());
1028 let seticon = if !Args.icon then seticon () else fun ~
iload ~
kload -> () in
1029 let rec loop t1 () =
1030 let t2 = Unix.gettimeofday
() in
1031 let dt = t2 -. t1 in
1036 let rec loop2 load
s = function
1038 | (nr
, calc, sampler) :: rest
->
1039 let i1, i2 = calc s t1 t2 in
1040 let thisload = 1.0 -. ((i2 -. i1) /. dt) in
1041 let thisload = max
0.0 thisload in
1045 ("cpu load(" ^ string_of_int nr ^
"): "
1046 ^
(thisload *. 100.0 |> string_of_float
)
1049 let load = load +. thisload in
1050 sampler.update t1 t2 i1 i2;
1053 let iload = loop2 0.0 is ifuncs
in
1054 let kload = loop2 0.0 ks kfuncs
in
1058 iload |> string_of_float
|> prerr_endline
;
1059 kload |> string_of_float
|> prerr_endline
;
1062 seticon ~
iload ~
kload;
1063 bar_update kload iload;
1066 FullV.func (Some
(loop t2))
1070 FullV.func (Some
(Unix.gettimeofday
() |> loop));
1076 | Unix.Unix_error
(e
, s1
, s2
) ->
1077 eprintf
"%s(%s): %s@." s1 s2
|< Unix.error_message e
1080 Printexc.to_string exn
|> eprintf
"Exception: %s@."