From 69fd196471751f6dbbeb2d6e098ba07c8f59f21a Mon Sep 17 00:00:00 2001 From: Krishna Srinivas Date: Tue, 2 Aug 2016 22:34:35 +0530 Subject: [PATCH] Object-cache: enforce cache size to be less than RAM. (#2338) --- pkg/sys/stats.go | 27 ++++++++++++++++++++ pkg/sys/stats_bsd.go | 24 ++++++++++++++++++ pkg/sys/stats_darwin.go | 51 +++++++++++++++++++++++++++++++++++++ pkg/sys/stats_linux.go | 34 +++++++++++++++++++++++++ pkg/sys/stats_windows.go | 55 ++++++++++++++++++++++++++++++++++++++++ server-rlimit-nix.go | 17 ++++++++++++- 6 files changed, 207 insertions(+), 1 deletion(-) create mode 100644 pkg/sys/stats.go create mode 100644 pkg/sys/stats_bsd.go create mode 100644 pkg/sys/stats_darwin.go create mode 100644 pkg/sys/stats_linux.go create mode 100644 pkg/sys/stats_windows.go diff --git a/pkg/sys/stats.go b/pkg/sys/stats.go new file mode 100644 index 000000000..ea89c7ec9 --- /dev/null +++ b/pkg/sys/stats.go @@ -0,0 +1,27 @@ +/* + * Minio Cloud Storage, (C) 2016 Minio, Inc. + * + * Licensed 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 sys + +import "errors" + +// ErrNotImplemented - GetStats() is not implemented on bsds. +var ErrNotImplemented = errors.New("not implemented") + +// Stats - system statistics. +type Stats struct { + TotalRAM uint64 // Physical RAM size in bytes, +} diff --git a/pkg/sys/stats_bsd.go b/pkg/sys/stats_bsd.go new file mode 100644 index 000000000..276d0c01b --- /dev/null +++ b/pkg/sys/stats_bsd.go @@ -0,0 +1,24 @@ +// +build !linux,!windows,!darwin + +/* + * Minio Cloud Storage, (C) 2016 Minio, Inc. + * + * Licensed 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 sys + +// GetStats - return system statistics for windows. +func GetStats() (stats Stats, err error) { + return Stats{}, ErrNotImplemented +} diff --git a/pkg/sys/stats_darwin.go b/pkg/sys/stats_darwin.go new file mode 100644 index 000000000..98d9dcc31 --- /dev/null +++ b/pkg/sys/stats_darwin.go @@ -0,0 +1,51 @@ +// +build darwin + +/* + * Minio Cloud Storage, (C) 2016 Minio, Inc. + * + * Licensed 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 sys + +import ( + "encoding/binary" + "syscall" +) + +func getHwMemsize() (uint64, error) { + totalString, err := syscall.Sysctl("hw.memsize") + if err != nil { + return 0, err + } + + // syscall.sysctl() helpfully assumes the result is a null-terminated string and + // removes the last byte of the result if it's 0 :/ + totalString += "\x00" + + total := uint64(binary.LittleEndian.Uint64([]byte(totalString))) + + return total, nil +} + +// GetStats - return system statistics for windows. +func GetStats() (stats Stats, err error) { + memSize, err := getHwMemsize() + if err != nil { + return Stats{}, err + } + stats = Stats{ + TotalRAM: memSize, + } + return stats, nil +} diff --git a/pkg/sys/stats_linux.go b/pkg/sys/stats_linux.go new file mode 100644 index 000000000..8099e72f2 --- /dev/null +++ b/pkg/sys/stats_linux.go @@ -0,0 +1,34 @@ +// +build linux + +/* + * Minio Cloud Storage, (C) 2016 Minio, Inc. + * + * Licensed 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 sys + +import "syscall" + +// GetStats - return system statistics. +func GetStats() (stats Stats, err error) { + si := syscall.Sysinfo_t{} + err = syscall.Sysinfo(&si) + if err != nil { + return + } + stats = Stats{ + TotalRAM: si.Totalram, + } + return stats, nil +} diff --git a/pkg/sys/stats_windows.go b/pkg/sys/stats_windows.go new file mode 100644 index 000000000..7ae7b9437 --- /dev/null +++ b/pkg/sys/stats_windows.go @@ -0,0 +1,55 @@ +// +build windows + +/* + * Minio Cloud Storage, (C) 2016 Minio, Inc. + * + * Licensed 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 sys + +import ( + "syscall" + "unsafe" +) + +var ( + modkernel32 = syscall.NewLazyDLL("kernel32.dll") + procGlobalMemoryStatusEx = modkernel32.NewProc("GlobalMemoryStatusEx") +) + +type memoryStatusEx struct { + cbSize uint32 + dwMemoryLoad uint32 + ullTotalPhys uint64 // in bytes + ullAvailPhys uint64 + ullTotalPageFile uint64 + ullAvailPageFile uint64 + ullTotalVirtual uint64 + ullAvailVirtual uint64 + ullAvailExtendedVirtual uint64 +} + +// GetStats - return system statistics for windows. +func GetStats() (stats Stats, err error) { + var memInfo memoryStatusEx + memInfo.cbSize = uint32(unsafe.Sizeof(memInfo)) + mem, _, _ := procGlobalMemoryStatusEx.Call(uintptr(unsafe.Pointer(&memInfo))) + if mem == 0 { + return Stats{}, syscall.GetLastError() + } + stats = Stats{ + TotalRAM: memInfo.ullTotalPhys, + } + return stats, nil +} diff --git a/server-rlimit-nix.go b/server-rlimit-nix.go index 549e39b12..13a233b52 100644 --- a/server-rlimit-nix.go +++ b/server-rlimit-nix.go @@ -18,7 +18,11 @@ package main -import "syscall" +import ( + "syscall" + + "github.com/minio/minio/pkg/sys" +) // For all unixes we need to bump allowed number of open files to a // higher value than its usual default of '1024'. The reasoning is @@ -72,5 +76,16 @@ func setMaxMemory() error { if rLimit.Cur < globalMaxCacheSize { globalMaxCacheSize = (80 / 100) * rLimit.Cur } + + // Make sure globalMaxCacheSize is less than RAM size. + stats, err := sys.GetStats() + if err != nil && err != sys.ErrNotImplemented { + // sys.GetStats() is implemented only on linux. Ignore errors + // from other OSes. + return err + } + if err == nil && stats.TotalRAM < globalMaxCacheSize { + globalMaxCacheSize = (80 / 100) * stats.TotalRAM + } return nil }