File: memusage.gi

package info (click to toggle)
gap 4.11.0-4
  • links: PTS
  • area: main
  • in suites: bullseye
  • size: 49,632 kB
  • sloc: ansic: 104,958; xml: 47,068; cpp: 11,393; sh: 4,165; perl: 1,652; makefile: 291
file content (117 lines) | stat: -rw-r--r-- 3,406 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#############################################################################
##
##  This file is part of GAP, a system for computational discrete algebra.
##
##  Copyright of GAP belongs to its developers, whose names are too numerous
##  to list here. Please refer to the COPYRIGHT file for details.
##
##  SPDX-License-Identifier: GPL-2.0-or-later
##


#############################################################################
##
#M  MemoryUsage( <obj> )
##
InstallGlobalFunction( MemoryUsage, function( o )
    local isImmediateObj, visit, mem, cache, todo, i, sub;
    
    isImmediateObj := x -> TNUM_OBJ(x) in [T_INT, T_FFE];
    visit := function(sub)
        if not isImmediateObj(sub) and not FIND_OBJ_SET(cache, sub) then
            ADD_OBJ_SET(cache, sub);
            Add(todo, sub);
        fi;
    end;

    if isImmediateObj(o) then
        return MU_MemPointer;
    fi;
    
    mem := 0;
    todo := [ o ];
    cache := OBJ_SET(todo);
    while Length(todo) > 0 do
        o := Remove(todo);
        
        if IsFamily(o) or IsType(o) then
            # Intentionally ignore families and types
            continue;
        fi;

        mem := mem + SIZE_OBJ(o) + MU_MemBagHeader + MU_MemPointer;
        if IsRat(o) then
            visit(NumeratorRat(o));
            visit(DenominatorRat(o));
        elif IsFunction(o) then
            if FUNC_BODY_SIZE(o) > 0 then
                # count the body (T_BODY)
                mem := mem + MU_MemBagHeader + MU_MemPointer + FUNC_BODY_SIZE(o);
            fi;
        elif IsPlistRep(o) then
            for sub in o do
                visit(sub);
            od;
        elif IsRecord(o) then
            for i in RecNames(o) do
                visit(o.(i));
            od;
        elif IS_POSOBJ(o) then
            for i in [1..LEN_POSOBJ(o)] do
                if IsBound(o![i]) then
                    visit(o![i]);
                fi;
            od;
        elif IS_DATOBJ(o) then
            # a DATOBJ cannot reference any subobjects (other than its type,
            # which we ignore for all kinds of objects)
        elif IS_COMOBJ(o) then
            for i in NamesOfComponents(o) do
                visit(o!.(i));
            od;
        elif TNUM_OBJ(o) <= LAST_LIST_TNUM then
            # o is another constant TNUM, or a blist, range, string...
            # so we don't need to visit subobjects, nor is there anything extra.
        else
            # Use method dispatch to deal with other kinds of objects. Mostly
            # intended to allow kernel extensions to add MemoryUsage support
            # for their custom TNUMs.
            mem := mem + MemoryUsageOp(o, visit);
        fi;
    od;

    return mem;
end);


InstallMethod( MemoryUsageOp,
    [ IsObjSet, IsFunction ],
function(o, visit)
    local sub;
    for sub in OBJ_SET_VALUES(o) do
        visit(sub);
    od;
    return 0;
end);

InstallMethod( MemoryUsageOp,
    [ IsObjMap, IsFunction ],
function(o, visit)
    local sub;
    for sub in OBJ_MAP_KEYS(o) do
        visit(sub);
    od;
    for sub in OBJ_MAP_VALUES(o) do
        visit(sub);
    od;
    return 0;
end);

InstallMethod( MemoryUsageOp,
    [ IsObject, IsFunction ],
function(o, visit)
    Info(InfoWarning, 1, "No MemoryUsage method installed for ",
                         TNAM_OBJ(o),
                         ", reported usage may be too low" );
    return 0;
end);