Skip to content

Allocation Question for Linux #1224

@barisyild

Description

@barisyild

I think there is a memory leak in haxe's garbage collector, as seen in the example below, the final memory offset must be 0 for the test to pass.

If you define clear_all_allocation you will see that the test always passes, I think the garbage collector has a leak because the required behavior is that there is no memory allocation.

Only for Linux

Reproduce Code:

package;
import haxe.atomic.AtomicInt;
import sys.thread.FixedThreadPool;

#if linux
@:cppFileCode("
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
")
#end

class AllocationTest {
    private static var completedCount:AtomicInt = new AtomicInt(0);
    private static var maxThreadCount:Int = 3;
    private static var workCount:Int = 100;
    private static var threadPool:FixedThreadPool;

    public static function main() {
        threadPool = new FixedThreadPool(maxThreadCount);
        run(true);
    }

    public static function run(firstRun:Bool):Void {

        completedCount = new AtomicInt(0);

        var endMemory:Float;
        var finalAllocation:Float;
        var startMemory:Float;

        // Clear garbage to get actual memory usage
        #if !clear_all_allocation
        cpp.vm.Gc.compact();
        #end
        startMemory = getMemoryUsage();

        for(i in 0...workCount) {
            createThread();
        }

        while (completedCount.load() < workCount) {
            Sys.sleep(0.01);
        }

        if(!firstRun) {
            // Clear garbage to get actual memory usage
            #if !clear_all_allocation
            cpp.vm.Gc.compact();
            #end
            endMemory = getMemoryUsage();

            finalAllocation = endMemory - startMemory;
            if(finalAllocation != 0) {
                trace("Allocation: " + finalAllocation);
                trace("Allocation Test Failed!");
                return;
            }

            trace("Allocation Test Success!");
        }

        run(false);
    }

    public static function createThread() {
        threadPool.run(() -> {
            #if clear_all_allocation
            cpp.vm.Gc.compact();
            #end

            haxe.io.Bytes.alloc(1024 * 50);
            completedCount.add(1);
        });
    }

    #if linux
    private static function getMemoryUsage():Int
    {
        untyped __cpp__('FILE *fp;
    char line[256];
    long memory = 0;

    // Open the /proc/self/status file
    fp = fopen("/proc/self/status", "r");
    if (fp == NULL) {
        perror("fopen");
        return -1;
    }

    // Read each line and look for the VmRSS field
    while (fgets(line, sizeof(line), fp)) {
        if (strncmp(line, "VmRSS:", 6) == 0) {
            // VmRSS is in kilobytes, so we convert it to a long
            sscanf(line, "VmRSS: %ld kB", &memory);
            break;
        }
    }

    fclose(fp);
    return memory * 1024;');

        return -1;
    }
    #end
}

Definitions:

-D HXCPP_VERBOSE
-D HXCPP_STACK_LINE
-D HXCPP_STACK_TRACE
-D HXCPP_CHECK_POINTER
-D HXCPP_CPP11
-D HXCPP_GC_MOVING

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions