Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add: get host/container cpu/mem info #37

Merged
merged 6 commits into from
Dec 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ github.com/mattn/go-colorable v0.1.7 h1:bQGKb3vps/j0E9GfJQ03JyhRuxsvdAanXlT9BTw3
github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/pbnjay/memory v0.0.0-20201129165224-b12e5d931931 h1:EeWknjeRU+R3O4ghG7XZCpgSfJNStZyEP8aWyQwJM8s=
github.com/pbnjay/memory v0.0.0-20201129165224-b12e5d931931/go.mod h1:RMU2gJXhratVxBDTFeOdNhd540tG57lt9FIUV0YLvIQ=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
Expand Down
4 changes: 2 additions & 2 deletions page/page.go → hash/page/page.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ func (d *Page) HasData() bool {
return d.GetDataSize() > 0
}

// New will create an instance
func New(requestOffset int, pageSize int,
// NewPage will create an instance
func NewPage(requestOffset int, pageSize int,
AlexStocks marked this conversation as resolved.
Show resolved Hide resolved
data []interface{}, totalSize int) *Page {

remain := totalSize % pageSize
Expand Down
4 changes: 2 additions & 2 deletions page/page_test.go → hash/page/page_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import (

func TestNewDefaultPage(t *testing.T) {
data := make([]interface{}, 10)
page := New(121, 10, data, 499)
page := NewPage(121, 10, data, 499)

assert.Equal(t, 10, page.GetDataSize())
assert.Equal(t, 121, page.GetOffset())
Expand All @@ -37,6 +37,6 @@ func TestNewDefaultPage(t *testing.T) {
assert.True(t, page.HasNext())
assert.True(t, page.HasData())

page = New(492, 10, data, 499)
page = NewPage(492, 10, data, 499)
assert.False(t, page.HasNext())
}
File renamed without changes.
64 changes: 64 additions & 0 deletions path/filepath/path.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package gxfilepath

import (
"fmt"
"os"
)

// Exists returns whether the given file or directory exists
func Exists(path string) (bool, error) {
_, err := os.Lstat(path)
if err == nil {
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}

return false, err
}

// FileExists checks whether a file exists in the given path. It also fails if
// the path points to a directory or there is an error when trying to check the file.
func FileExists(path string) (bool, error) {
info, err := os.Lstat(path)
if err != nil {
return false, err
}
if info.IsDir() {
return false, fmt.Errorf("%q is a directory", path)
}

return true, nil
}

// DirExists checks whether a directory exists in the given path. It also fails
// if the path is a file rather a directory or there is an error checking whether it exists.
func DirExists(path string) (bool, error) {
info, err := os.Lstat(path)
if err != nil {
return false, err
}
if !info.IsDir() {
return false, fmt.Errorf("%q is a file", path)
}

return true, nil
}
74 changes: 74 additions & 0 deletions path/filepath/path_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package gxfilepath

import (
"testing"
)

import (
"github.com/stretchr/testify/assert"
)

func TestFileExists(t *testing.T) {
file := "./path_test.go"
ok, err := Exists(file)
assert.True(t, ok)
assert.Nil(t, err)
ok, err = DirExists(file)
assert.False(t, ok)
assert.NotNil(t, err)
ok, err = FileExists(file)
assert.True(t, ok)
assert.Nil(t, err)

file = "./path_test1.go"
ok, err = Exists(file)
assert.False(t, ok)
assert.Nil(t, err)
ok, err = DirExists(file)
assert.False(t, ok)
assert.NotNil(t, err)
ok, err = FileExists(file)
assert.False(t, ok)
assert.NotNil(t, err)
}

func TestDirExists(t *testing.T) {
file := "./"
ok, err := Exists(file)
assert.True(t, ok)
assert.Nil(t, err)
ok, err = DirExists(file)
assert.True(t, ok)
assert.Nil(t, err)
ok, err = FileExists(file)
assert.False(t, ok)
assert.NotNil(t, err)

file = "./go"
ok, err = Exists(file)
assert.False(t, ok)
assert.Nil(t, err)
ok, err = DirExists(file)
assert.False(t, ok)
assert.NotNil(t, err)
ok, err = FileExists(file)
assert.False(t, ok)
assert.NotNil(t, err)
}
4 changes: 2 additions & 2 deletions runtime/goroutine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import (
func TestGoSafe(t *testing.T) {
times := int32(1)

wg := sync.WaitGroup{}
var wg sync.WaitGroup
GoSafely(&wg,
false,
func() {
Expand Down Expand Up @@ -60,7 +60,7 @@ func TestGoSafe(t *testing.T) {

func TestGoUnterminated(t *testing.T) {
times := uint64(1)
wg := sync.WaitGroup{}
var wg sync.WaitGroup
GoUnterminated(
func() {
if atomic.AddUint64(&times, 1) == 2 {
Expand Down
39 changes: 35 additions & 4 deletions runtime/sys.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,14 @@ import (
)

import (
"github.com/shirou/gopsutil/mem"
"github.com/shirou/gopsutil/process"
)

import (
"github.com/dubbogo/gost/path/filepath"
)

var (
CurrentPID = os.Getpid()
)
Expand All @@ -39,6 +44,36 @@ const (
cgroupMemLimitPath = "/sys/fs/cgroup/memory/memory.limit_in_bytes"
)

// GetCPUNum gets current os's cpu number
func GetCPUNum() int {
return runtime.NumCPU()
}

// GetMemoryStat gets current os's memory size in bytes
func GetMemoryStat() (total, used, free uint64, usedPercent float64) {
stat, err := mem.VirtualMemory()
if err != nil {
return 0, 0, 0, 0
}

return stat.Total, stat.Used, stat.Free, stat.UsedPercent
}

// IsCgroup checks whether current os is a container or not
func IsCgroup() bool {
ok, _ := gxfilepath.Exists(cgroupMemLimitPath)
if ok {
return true
}

return false
}

// GetCgroupMemoryLimit returns a container's total memory in bytes
func GetCgroupMemoryLimit() (uint64, error) {
return readUint(cgroupMemLimitPath)
}

// GetThreadNum gets current process's thread number
func GetThreadNum() int {
return pprof.Lookup("threadcreate").Count()
Expand Down Expand Up @@ -124,10 +159,6 @@ func readUint(path string) (uint64, error) {
return parseUint(strings.TrimSpace(string(v)), 10, 64)
}

func GetCgroupMemoryLimit() (uint64, error) {
return readUint(cgroupMemLimitPath)
}

// GetCgroupProcessMemoryPercent gets current process's memory usage percent in cgroup env
func GetCgroupProcessMemoryPercent() (float64, error) {
p, err := process.NewProcess(int32(os.Getpid()))
Expand Down
32 changes: 25 additions & 7 deletions runtime/sys_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ import (
"time"
)

func TestProcessSysStat(t *testing.T) {
func TestSysStat(t *testing.T) {
t.Logf("current os cpu number %d", GetCPUNum())
total, used, free, usedPercent := GetMemoryStat()
t.Logf("memory: limit %d bytes, used %d bytes, free %d bytes, usedPercent %f", total, used, free, usedPercent)
t.Logf("current prcess thread number %d", GetThreadNum())
go func() {
time.Sleep(10e9)
Expand All @@ -40,21 +43,36 @@ func TestProcessSysStat(t *testing.T) {
t.Logf("process cpu stat %v", cpu)

size := 100 * 1024 * 1024
bytes := make([]byte, size)
_ = bytes[:size-1]
arr := make([]byte, size)
for idx := range arr {
arr[idx] = byte(idx / 255)
}
memoryStat, err := GetProcessMemoryStat()
if err != nil {
t.Errorf("GetProcessMemoryStat() = error %+v", err)
}
t.Logf("process memory usage stat %v", memoryStat)
//if memoryStat <= uint64(size) {
// t.Errorf("memory usage stat %d < %d", memoryStat, size)
//}
//t.Logf("process memory usage stat %v", memoryStat)
if memoryStat <= uint64(size) {
t.Errorf("memory usage stat %d < %d", memoryStat, size)
}

memoryUsage, err := GetProcessMemoryPercent()
if err != nil {
t.Errorf("GetProcessMemoryPercent() = error %+v", err)
}
t.Logf("process memory usage percent %v", memoryUsage)

if IsCgroup() {
memoryLimit, err := GetCgroupMemoryLimit()
if err != nil {
t.Errorf("GetCgroupMemoryLimit() = error %+v", err)
}
t.Logf("CGroupMemoryLimit() = %d", memoryLimit)

memoryPercent, err := GetCgroupProcessMemoryPercent()
if err != nil {
t.Errorf("GetCgroupProcessMemoryPercent(ps:%d) = error %+v", CurrentPID, err)
}
t.Logf("GetCgroupProcessMemoryPercent(ps:%d) = %+v", CurrentPID, memoryPercent)
}
}
5 changes: 3 additions & 2 deletions sync/task_pool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,9 @@ func TestTaskPoolSimple(t *testing.T) {
}
wg.Wait()

if taskCnt != atomic.LoadInt64(cnt) {
t.Error("want ", taskCnt, " got ", *cnt)
cntValue := atomic.LoadInt64(cnt)
if taskCnt != cntValue {
t.Error("want ", taskCnt, " got ", cntValue)
}
}

Expand Down