@@ -409,3 +409,242 @@ function runtests(tests = ["all"], numcores = ceil(Int,CPU_CORES/2))
409409 " including error messages above and the output of versioninfo():\n $(readall (buf)) " )
410410 end
411411end
412+
413+ # testing
414+
415+ function whos (io:: IO = STDOUT, m:: Module = current_module (), pattern:: Regex = r" " )
416+ maxline = tty_size ()[2 ]
417+ line = zeros (UInt8, maxline)
418+ head = PipeBuffer (maxline + 1 )
419+ for v in sort! (names (m))
420+ s = string (v)
421+ if isdefined (m, v) && ismatch (pattern, s)
422+ value = getfield (m, v)
423+ bytes = summarysize (value, true )
424+ @printf head " %30s " s
425+ if bytes < 10_000
426+ @printf (head, " %6d bytes " , bytes)
427+ else
428+ @printf (head, " %6d KB " , bytes ÷ (1024 ))
429+ end
430+ print (head, summary (value))
431+ print (head, " : " )
432+ show (head, value)
433+
434+ newline = search (head, UInt8 (' \n ' )) - 1
435+ if newline < 0
436+ newline = nb_available (head)
437+ end
438+ if newline > maxline
439+ newline = maxline - 1 # make space for ...
440+ end
441+ line = resize! (line, newline)
442+ line = read! (head, line)
443+
444+ write (io, line)
445+ if nb_available (head) > 0 # more to read? replace with ...
446+ print (io, ' \u 2026' ) # hdots
447+ end
448+ println (io)
449+ seekend (head) # skip the rest of the text
450+ end
451+ end
452+ end
453+ whos (m:: Module , pat:: Regex = r" " ) = whos (STDOUT, m, pat)
454+ whos (pat:: Regex ) = whos (STDOUT, current_module (), pat)
455+
456+ # summarysize is an estimate of the size of the object
457+ # as if all iterables were allocated inline
458+ # in general, this forms a conservative lower bound
459+ # on the memory "controlled" by the object
460+ # if recurse is true, then simply reachable memory
461+ # should also be included, otherwise, only
462+ # directly used memory should be included
463+ # you should never ignore recurse in cases where recursion is possible
464+
465+ summarysize (obj:: ANY , recurse:: Bool ) = try convert (Int, sizeof (obj)); catch ; Core. sizeof (obj); end
466+
467+ # these three cases override the exception that would be thrown by Core.sizeof
468+ summarysize (obj:: Symbol , recurse:: Bool ) = 0
469+ summarysize (obj:: DataType , recurse:: Bool ) = 0
470+ function summarysize (obj:: Module , recurse:: Bool )
471+ size:: Int = sizeof (obj)
472+ if recurse
473+ for binding in names (obj, true )
474+ if isdefined (obj, binding)
475+ value = getfield (obj, binding)
476+ if (value != = obj) # skip the self-recursive definition
477+ recurseok = ! isa (value, Module) || module_parent (value) === obj
478+ size += summarysize (value, recurseok):: Int # recurse on anything that isn't a module
479+ end
480+ end
481+ end
482+ end
483+ return size
484+ end
485+
486+ function summarysize (obj:: Task , recurse:: Bool )
487+ size:: Int = sizeof (obj)
488+ if recurse
489+ size += summarysize (obj. code, true ):: Int
490+ size += summarysize (obj. storage, true ):: Int
491+
492+ size += summarysize (obj. backtrace, false ):: Int
493+ size += summarysize (obj. donenotify, false ):: Int
494+ size += summarysize (obj. exception, false ):: Int
495+ size += summarysize (obj. result, false ):: Int
496+ end
497+ return size
498+ end
499+
500+ function summarysize (obj:: SimpleVector , recurse:: Bool )
501+ size:: Int = sizeof (obj)
502+ if recurse
503+ for val in obj
504+ if val != = obj
505+ size += summarysize (val, false ):: Int
506+ end
507+ end
508+ end
509+ return size
510+ end
511+
512+ function summarysize (obj:: Tuple , recurse:: Bool )
513+ size:: Int = sizeof (obj)
514+ if recurse
515+ for val in obj
516+ if val != = obj && ! isbits (val)
517+ size += summarysize (val, recurse):: Int
518+ end
519+ end
520+ end
521+ return size
522+ end
523+
524+ function summarysize (obj:: Array , recurse:: Bool )
525+ size:: Int = sizeof (obj)
526+ if recurse && ! isbits (eltype (obj))
527+ for i in 1 : length (obj)
528+ if isdefined (obj, i) && (val = obj[i]) != = obj
529+ size += summarysize (val, false ):: Int
530+ end
531+ end
532+ end
533+ return size
534+ end
535+
536+ function summarysize (obj:: AbstractArray , recurse:: Bool )
537+ size:: Int = sizeof (obj)
538+ if recurse && ! isbits (eltype (obj))
539+ for val in obj
540+ if val != = obj
541+ size += summarysize (val, false ):: Int
542+ end
543+ end
544+ end
545+ return size
546+ end
547+
548+ function summarysize (obj:: Associative , recurse:: Bool )
549+ size:: Int = sizeof (obj)
550+ if recurse
551+ for (key, val) in obj
552+ if key != = obj
553+ size += summarysize (key, false ):: Int
554+ end
555+ if val != = obj
556+ size += summarysize (val, false ):: Int
557+ end
558+ end
559+ end
560+ return size
561+ end
562+
563+ function summarysize (obj:: Dict , recurse:: Bool )
564+ size:: Int = sizeof (obj)
565+ size += summarysize (obj. keys, recurse):: Int
566+ size += summarysize (obj. vals, recurse):: Int
567+ size += summarysize (obj. slots, recurse):: Int
568+ return size
569+ end
570+
571+ summarysize (obj:: Set , recurse:: Bool ) =
572+ sizeof (obj) + summarysize (obj. dict, recurse)
573+
574+ function summarysize (obj:: Function , recurse:: Bool )
575+ size:: Int = sizeof (obj)
576+ size += summarysize (obj. env, recurse):: Int
577+ if isdefined (obj, :code )
578+ size += summarysize (obj. code, recurse):: Int
579+ end
580+ return size
581+ end
582+
583+ function summarysize (obj:: MethodTable , recurse:: Bool )
584+ size:: Int = sizeof (obj)
585+ size += summarysize (obj. defs, recurse):: Int
586+ size += summarysize (obj. cache, recurse):: Int
587+ size += summarysize (obj. cache_arg1, recurse):: Int
588+ size += summarysize (obj. cache_targ, recurse):: Int
589+ if isdefined (obj, :kwsorter )
590+ size += summarysize (obj. kwsorter, recurse):: Int
591+ end
592+ return size
593+ end
594+
595+ function summarysize (obj:: Method , recurse:: Bool )
596+ size:: Int = sizeof (obj)
597+ size += summarysize (obj. func, recurse):: Int
598+ size += summarysize (obj. next, recurse):: Int
599+ return size
600+ end
601+
602+ function summarysize (obj:: LambdaStaticData , recurse:: Bool )
603+ size:: Int = sizeof (obj)
604+ size += summarysize (obj. ast, true ):: Int # always include the AST
605+ size += summarysize (obj. sparams, true ):: Int
606+ if isdefined (obj, :roots )
607+ size += summarysize (obj. roots, recurse):: Int
608+ end
609+ if isdefined (obj, :capt )
610+ size += summarysize (obj. capt, false ):: Int
611+ end
612+ return size
613+ end
614+
615+ function summarysize (obj:: Expr , recurse:: Bool )
616+ size:: Int = sizeof (obj) + sizeof (obj. args)
617+ if recurse
618+ for arg in obj. args
619+ size += summarysize (arg, isa (arg, Expr)):: Int
620+ end
621+ end
622+ return size
623+ end
624+
625+ function summarysize (obj:: Box , recurse:: Bool )
626+ size:: Int = sizeof (obj)
627+ # ignore the recurse parameter for Box,
628+ # even though it could in theory recurse
629+ # since it is an internal construct
630+ # used by codegen with very limited usage
631+ if isdefined (obj, :contents )
632+ if obj. contents != = obj
633+ size += summarysize (obj. contents, false ):: Int
634+ end
635+ end
636+ return size
637+ end
638+
639+ function summarysize (obj:: Ref , recurse:: Bool )
640+ size:: Int = sizeof (obj)
641+ if recurse && ! isbits (eltype (obj))
642+ try
643+ val = obj[]
644+ if val != = obj
645+ size += summarysize (val, false ):: Int
646+ end
647+ end
648+ end
649+ return size
650+ end
0 commit comments