Skip to content

runtime/cgo: Memory RSS has been growing abnormally when call cgo and go #43160

Closed
@bluce-ldg

Description

@bluce-ldg

What version of Go are you using (go version)?

$ go version
go1.15.6 linux/amd64

Does this issue reproduce with the latest release?

yes, reproduce with version 1.13、1.15

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/root/.cache/go-build"
GOENV="/root/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/root/go/pkg/mod"
GONOPROXY=".gitlab.com,.gitee.com"
GONOSUMDB=".gitlab.com,.gitee.com"
GOOS="linux"
GOPATH="/root/go"
GOPRIVATE=".gitlab.com,.gitee.com"
GOPROXY="https://goproxy.cn,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.google.cn"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build926124830=/tmp/go-build -gno-record-gcc-switches"

What did you do?

demo code
package main

/*
#cgo CFLAGS: -I${SRCDIR}/so -fpermissive -std=c99 -std=c++11 -Wall -w -O0 -fpie -pthread -pedantic
//#cgo LDFLAGS: -Wl,-rpath-link=${SRCDIR}/so -L${SRCDIR}/so -ldl -lm -lcpp_clustersdk
#cgo LDFLAGS: -Wl,-rpath-link=${SRCDIR}/so -L${SRCDIR}/so -ldl -lm
//#cgo LDFLAGS: -Wl,-rpath-link=${SRCDIR}/so -I${SRCDIR}/so -L${SRCDIR}/so -ldl -lm -lcpp_clustersdk -lcwcluster
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
//#include <string.h>
//#include <dlfcn.h>

char* _gTestFeatures = NULL;
char* _gHashs = NULL;
char* _gAttrs = NULL;
bool g_init = false;
long g_testSize = 100000;
long g_testCount = 1000000;

typedef struct CMemTest_
{
long _index;
long _count;

char* pFeas;
char* pHashs;
char* pAttrs;

}CMemTest;

CMemTest* gMemTest = NULL;

void PushMemTest(CMemTest* obj)
{
if(!obj->pFeas)
{
obj->pFeas = (char*)malloc(384g_testSize);
obj->pHashs = (char
)malloc(64g_testSize);
obj->pAttrs = (char
)malloc(832g_testSize);
}

    memcpy(obj->pFeas+obj->_index*384, &_gTestFeatures[obj->_index*384], 384);
    memcpy(obj->pHashs+obj->_index*64, &_gHashs[obj->_index*64], 64);
    memcpy(obj->pAttrs+obj->_index*8*32, &_gAttrs[obj->_index*8*32], 8*32);
    obj->_index++;
    obj->_count++;
    if (obj->_index >= g_testSize)
    {
        obj->_index = 0;
    }

}

CMemTest* AllocMemTest()
{
if(gMemTest != NULL)
abort();

gMemTest = (CMemTest*)malloc(sizeof(CMemTest));
gMemTest->_index = 0;
gMemTest->_count = 0;
gMemTest->pFeas = NULL;
gMemTest->pHashs = NULL;
gMemTest->pAttrs = NULL;

}

void FreeMemTest(CMemTest* obj)
{
if(obj->pFeas) free(obj->pFeas);
if(obj->pHashs) free(obj->pHashs);
if(obj->pAttrs) free(obj->pAttrs);
free(obj);
}

int c_Master_TestMem1()
{
if (g_init == false)
{
_gTestFeatures = (char*)malloc(384*(g_testSize+1));
_gHashs = (char*)malloc(64*(g_testSize+1));
_gAttrs = (char*)malloc(832(g_testSize+1));
for (long i = 0; i < g_testSize; i++)
{
for (long j = 0; j < 384; j++)
{
_gTestFeatures[i384+j] = ij;
}
for (long j = 0; j < 64; j++)
{
_gHashs[i64+j] = ij;
}
for (long j = 0; j < 832; j++)
{
_gAttrs[i
832+j] = ij;
}
}

// new std::thread(& {
// uint64_t timeCount = 0;
// while (1)
// {
// #ifndef _WIN32
// malloc_trim(0);
// printf("-----------------\n");
// #endif
// std::chrono::seconds dura(1);
// std::this_thread::sleep_for(dura);
// }
// });
g_init = true;
}

if(gMemTest == NULL)
{
     gMemTest = AllocMemTest();
}

printf("====================================== gMemTest count:%lld =============================\n", gMemTest->_count);

if (0 == (gMemTest->_count % g_testCount))
{
    FreeMemTest(gMemTest);
    gMemTest = NULL;
	printf("\n\n\n\n====================================== reset, press anykey continue =============================\n\n\n\n\n");
	//getchar();

     gMemTest = AllocMemTest();
  //  sleep(1);
}

for (long i = 0; i < 10000; i++)
{
    //if ((i % 1000) == 0)
    //{
    //    //usleep(1000*100);
    //}
    PushMemTest(gMemTest);
}
return 0;

}
*/
import "C"
import (
"fmt"
"net/http"
_ "net/http/pprof"
"os"
)

type DBFeatureJournalnfo struct {
InstType int
FaceId int64
UserId string
PriorLabel int64
GroupIdMapAlgo int32
Feature []byte
ShortFeatureA []byte
ShortFeatureB []byte
ImageUrl string
Qualityscore []byte
FailedModelingInfo string
AddScoreFlag bool
AddScore float32
Time int64
Status int32
TrackId int64
TrackBeginTime int64
TrackEndTime int64
ExtData string
}

var rawFea = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"

func GetMemTest() []DBFeatureJournalnfo {
results := make([]DBFeatureJournalnfo, 10000)
result := DBFeatureJournalnfo{}
result.InstType = 1
result.FaceId = 1
result.UserId = "1111111111111111111111111111111111111111111111111"
result.PriorLabel = 1
result.GroupIdMapAlgo = 1

//result.Feature = append(result.Feature, rawFea[0:384]...)
//result.Feature = append(result.Feature, rawFea[0:384]...)

result.Feature = make([]byte, 384, 384*2)
//copy(result.Feature, "11111111111fgdgggggggggggggggggggggggggsgsfddddddddddddddddddddddddddddddddddddddddddddd")
result.Qualityscore = make([]byte, 32*8, 32*8*2)
result.ImageUrl = "ffffffffffffffffffffffffff"

for i := 0; i < 10000; i++ {
	results = append(results, result)
}
return results

}

func main() {
go func() {
http.ListenAndServe("0.0.0.0:8080", nil)
}()

//go func() {
//	http.ListenAndServe("0.0.0.0:8080", nil)
//	debug.FreeOSMemory()
//	time.Sleep(time.Second*5)
//}()

fmt.Println("------------------------------------------")
N := 100000000

for i := 0; ; i++ {
	// step 1 call cgo test function
	C.c_Master_TestMem1()
	// step 2 call go test function
	test := GetMemTest()
	if test == nil {
		os.Exit(1)
	}
}

}

What did you expect to see?

when both call cgo test and go test, It would taking 167Mb of RSS and should be able to stabilize around 170Mb,instead of memory increase several times.

What did you see instead?

  1. We can see from the code,when only call cgo test function(step 1), not call go test function(step 2), It would taking ~142Mb of RSS(resident set size memory) .
    2.when only call go test function(step 2), not call cgo test function(step 1), It would taking ~33Mb of RSS(resident set size memory) .
    3.when both call cgo test and go test, It would taking 167Mb of RSS and then grow to >700Mb
    4.In addition, Using the windows platform,RSS is normal , not as high as linux

Metadata

Metadata

Assignees

No one assigned

    Labels

    FrozenDueToAgeNeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.WaitingForInfoIssue is not actionable because of missing required information, which needs to be provided.

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions