All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.oracle.graal.python.builtins.modules.ResourceModuleBuiltins Maven / Gradle / Ivy

There is a newer version: 24.1.1
Show newest version
/*
 * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * The Universal Permissive License (UPL), Version 1.0
 *
 * Subject to the condition set forth below, permission is hereby granted to any
 * person obtaining a copy of this software, associated documentation and/or
 * data (collectively the "Software"), free of charge and under any and all
 * copyright rights in the Software, and any and all patent rights owned or
 * freely licensable by each licensor hereunder covering either (i) the
 * unmodified Software as contributed to or provided by such licensor, or (ii)
 * the Larger Works (as defined below), to deal in both
 *
 * (a) the Software, and
 *
 * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
 * one is included with the Software each a "Larger Work" to which the Software
 * is contributed by such licensors),
 *
 * without restriction, including without limitation the rights to copy, create
 * derivative works of, display, perform, and distribute the Software and make,
 * use, sell, offer for sale, import, export, have made, and have sold the
 * Software and the Larger Work(s), and to sublicense the foregoing rights on
 * either these or other terms.
 *
 * This license is subject to the following condition:
 *
 * The above copyright notice and either this complete permission notice or at a
 * minimum a reference to the UPL must be included in all copies or substantial
 * portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.oracle.graal.python.builtins.modules;

import static com.oracle.graal.python.runtime.exception.PythonErrorType.ValueError;

import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryUsage;
import java.lang.management.ThreadMXBean;
import java.util.List;

import org.graalvm.nativeimage.ImageInfo;

import com.oracle.graal.python.builtins.Builtin;
import com.oracle.graal.python.builtins.CoreFunctions;
import com.oracle.graal.python.builtins.Python3Core;
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
import com.oracle.graal.python.builtins.PythonBuiltins;
import com.oracle.graal.python.builtins.objects.thread.PThread;
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
import com.oracle.graal.python.builtins.objects.tuple.StructSequence;
import com.oracle.graal.python.nodes.ErrorMessages;
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.dsl.Fallback;
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
import com.oracle.truffle.api.dsl.ImportStatic;
import com.oracle.truffle.api.dsl.NodeFactory;
import com.oracle.truffle.api.dsl.Specialization;

@CoreFunctions(defineModule = "resource")
public final class ResourceModuleBuiltins extends PythonBuiltins {

    static int RUSAGE_CHILDREN = -1;
    static int RUSAGE_SELF = 0;
    static int RUSAGE_THREAD = 1;

    static int RLIMIT_CPU = 0;
    static int RLIMIT_FSIZE = 1;
    static int RLIMIT_DATA = 2;
    static int RLIMIT_STACK = 3;
    static int RLIMIT_CORE = 4;
    static int RLIMIT_AS = 5;
    static int RLIMIT_RSS = 5;
    static int RLIMIT_MEMLOCK = 6;
    static int RLIMIT_NPROC = 7;
    static int RLIMIT_NOFILE = 8;

    static long RLIM_INFINITY = Long.MAX_VALUE;

    static final StructSequence.BuiltinTypeDescriptor STRUCT_RUSAGE_DESC = new StructSequence.BuiltinTypeDescriptor(
                    PythonBuiltinClassType.PStructRusage,
                    // @formatter:off The formatter joins these lines making it less readable
                    "struct_rusage: Result from getrusage.\n\n" +
                    "This object may be accessed either as a tuple of\n" +
                    "    (utime,stime,maxrss,ixrss,idrss,isrss,minflt,majflt,\n" +
                    "    nswap,inblock,oublock,msgsnd,msgrcv,nsignals,nvcsw,nivcsw)\n" +
                    "or via the attributes ru_utime, ru_stime, ru_maxrss, and so on.",
                    // @formatter:on
                    16,
                    new String[]{
                                    "ru_utime", "ru_stime", "ru_maxrss",
                                    "ru_ixrss", "ru_idrss", "ru_isrss",
                                    "ru_minflt", "ru_majflt",
                                    "ru_nswap", "ru_inblock", "ru_oublock",
                                    "ru_msgsnd", "ru_msgrcv", "ru_nsignals",
                                    "ru_nvcsw", "ru_nivcsw"
                    },
                    new String[]{
                                    "user time used", "system time used", "max. resident set size",
                                    "shared memory size", "unshared data size", "unshared stack size",
                                    "page faults not requiring I/O", "page faults requiring I/O",
                                    "number of swap outs", "block input operations", "block output operations",
                                    "IPC messages sent", "IPC messages received", "signals received",
                                    "voluntary context switches", "involuntary context switches"
                    });

    @Override
    protected List> getNodeFactories() {
        return ResourceModuleBuiltinsFactory.getFactories();
    }

    @Override
    public void initialize(Python3Core core) {
        super.initialize(core);
        addBuiltinConstant("RUSAGE_CHILDREN", RUSAGE_CHILDREN);
        addBuiltinConstant("RUSAGE_SELF", RUSAGE_SELF);
        addBuiltinConstant("RUSAGE_THREAD", RUSAGE_THREAD);

        addBuiltinConstant("RLIMIT_CPU", RLIMIT_CPU);
        addBuiltinConstant("RLIMIT_FSIZE", RLIMIT_FSIZE);
        addBuiltinConstant("RLIMIT_DATA", RLIMIT_DATA);
        addBuiltinConstant("RLIMIT_STACK", RLIMIT_STACK);
        addBuiltinConstant("RLIMIT_CORE", RLIMIT_CORE);
        addBuiltinConstant("RLIMIT_AS", RLIMIT_AS);
        addBuiltinConstant("RLIMIT_RSS", RLIMIT_RSS);
        addBuiltinConstant("RLIMIT_MEMLOCK", RLIMIT_MEMLOCK);
        addBuiltinConstant("RLIMIT_NPROC", RLIMIT_NPROC);
        addBuiltinConstant("RLIMIT_NOFILE", RLIMIT_NOFILE);

        addBuiltinConstant("RLIM_INFINITY", RLIM_INFINITY);

        StructSequence.initType(core, STRUCT_RUSAGE_DESC);
    }

    @Builtin(name = "getrusage", minNumOfPositionalArgs = 1)
    @GenerateNodeFactory
    @ImportStatic(ResourceModuleBuiltins.class)
    abstract static class GetRuUsageNode extends PythonBuiltinNode {

        @Specialization(guards = {"who == RUSAGE_THREAD"})
        @TruffleBoundary
        PTuple getruusageThread(@SuppressWarnings("unused") int who) {
            long id = PThread.getThreadId(Thread.currentThread());
            Runtime runtime = Runtime.getRuntime();

            double ru_utime = 0; // time in user mode (float)
            double ru_stime = 0; // time in system mode (float)
            long ru_maxrss; // maximum resident set size

            if (!ImageInfo.inImageCode()) {
                ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
                if (threadMXBean.isCurrentThreadCpuTimeSupported()) {
                    ru_utime = threadMXBean.getThreadUserTime(id) / 1000000000.0;
                    ru_stime = Math.max(0, (threadMXBean.getThreadCpuTime(id) - threadMXBean.getThreadUserTime(id))) / 1000000000.0;
                }

                if (threadMXBean instanceof com.sun.management.ThreadMXBean) {
                    com.sun.management.ThreadMXBean thMxBean = (com.sun.management.ThreadMXBean) threadMXBean;
                    ru_maxrss = thMxBean.getThreadAllocatedBytes(id);
                } else {
                    ru_maxrss = runtime.maxMemory();
                }
            } else {
                ru_maxrss = runtime.maxMemory();
            }

            String osName = System.getProperty("os.name");
            if (osName.contains("Linux")) {
                // peak memory usage (kilobytes on Linux
                ru_maxrss /= 1024;
            }

            long ru_ixrss = -1; // shared memory size
            long ru_idrss = -1; // unshared memory size
            long ru_isrss = -1; // unshared stack size
            long ru_minflt = -1; // page faults not requiring I/O
            long ru_majflt = -1;  // page faults requiring I/O
            long ru_nswap = -1;  // number of swap outs
            long ru_inblock = -1; // block input operations
            long ru_oublock = -1;  // block output operations
            long ru_msgsnd = -1; // messages sent
            long ru_msgrcv = -1; // messages received
            long ru_nsignals = -1; // signals received
            long ru_nvcsw = -1; // voluntary context switches
            long ru_nivcsw = -1; // nvoluntary context switches
            return factory().createStructSeq(STRUCT_RUSAGE_DESC, ru_utime, ru_stime, ru_maxrss, ru_ixrss, ru_idrss, ru_isrss,
                            ru_minflt, ru_majflt, ru_nswap, ru_inblock, ru_oublock, ru_msgsnd, ru_msgrcv, ru_nsignals,
                            ru_nvcsw, ru_nivcsw);
        }

        @Specialization(guards = {"who == RUSAGE_SELF"})
        @TruffleBoundary
        PTuple getruusageSelf(@SuppressWarnings("unused") int who) {
            Runtime runtime = Runtime.getRuntime();

            double ru_utime = 0; // time in user mode (float)
            double ru_stime = 0; // time in system mode (float)
            long ru_maxrss;

            if (!ImageInfo.inImageCode()) {
                ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
                if (threadMXBean.isThreadCpuTimeSupported()) {
                    for (long thId : threadMXBean.getAllThreadIds()) {
                        long tu = threadMXBean.getThreadUserTime(thId);
                        long tc = threadMXBean.getThreadCpuTime(thId);

                        if (tu != -1) {
                            ru_utime += tu / 1000000000.0;
                        }

                        if (tu != -1 && tc != -1) {
                            ru_stime += Math.max(0, tc - tu) / 1000000000.0;
                        }
                    }
                }

                MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
                MemoryUsage heapMemoryUsage = memoryMXBean.getHeapMemoryUsage();
                MemoryUsage nonHeapMemoryUsage = memoryMXBean.getNonHeapMemoryUsage();
                ru_maxrss = heapMemoryUsage.getCommitted() + nonHeapMemoryUsage.getCommitted();
            } else {
                ru_maxrss = runtime.maxMemory();
            }

            String osName = System.getProperty("os.name");
            if (osName.contains("Linux")) {
                // peak memory usage (kilobytes on Linux
                ru_maxrss /= 1024;
            }

            long ru_ixrss = -1; // shared memory size
            long ru_idrss = -1; // unshared memory size
            long ru_isrss = -1; // unshared stack size
            long ru_minflt = -1; // page faults not requiring I/O
            long ru_majflt = -1;  // page faults requiring I/O
            long ru_nswap = -1;  // number of swap outs
            long ru_inblock = -1; // block input operations
            long ru_oublock = -1;  // block output operations
            long ru_msgsnd = -1; // messages sent
            long ru_msgrcv = -1; // messages received
            long ru_nsignals = -1; // signals received
            long ru_nvcsw = -1; // voluntary context switches
            long ru_nivcsw = -1; // nvoluntary context switches
            return factory().createStructSeq(STRUCT_RUSAGE_DESC, ru_utime, ru_stime, ru_maxrss, ru_ixrss, ru_idrss, ru_isrss,
                            ru_minflt, ru_majflt, ru_nswap, ru_inblock, ru_oublock, ru_msgsnd, ru_msgrcv, ru_nsignals,
                            ru_nvcsw, ru_nivcsw);
        }

        @Fallback
        PTuple getruusage(@SuppressWarnings("unused") Object who) {
            throw raise(ValueError, ErrorMessages.RUSAGE_NOT_YET_IMPLEMENED);
        }
    }

    @Builtin(name = "getpagesize", minNumOfPositionalArgs = 0)
    @GenerateNodeFactory
    abstract static class GetPageSizeNode extends PythonBuiltinNode {
        @Specialization
        int getPageSize() {
            return 4096;
        }
    }

    @Builtin(name = "getrlimit", minNumOfPositionalArgs = 1)
    @GenerateNodeFactory
    abstract static class GetRLimitNode extends PythonBuiltinNode {
        @Specialization
        PTuple getPageSize(@SuppressWarnings("unused") int which) {
            // dummy implementation - report "unrestricted" for everything
            return factory().createTuple(new Object[]{RLIM_INFINITY, RLIM_INFINITY});
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy