Format memory warning in human-friendly way.
PiperOrigin-RevId: 486610408 Change-Id: I6beecb12059e69f4407e921d20efc54ce6b3f491
This commit is contained in:
committed by
Copybara-Service
parent
fc24097b92
commit
fd4d47e4a5
@@ -6601,6 +6601,17 @@ Convert type name to type id (mjtObj).
|
|||||||
|
|
||||||
.. _mju_warningText:
|
.. _mju_warningText:
|
||||||
|
|
||||||
|
mju_writeNumBytes
|
||||||
|
~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. code-block:: C
|
||||||
|
|
||||||
|
const char* mju_writeNumBytes(const int nbytes);
|
||||||
|
|
||||||
|
Construct a human readable number of bytes using standard letter suffix.
|
||||||
|
|
||||||
|
.. _mju_warningText:
|
||||||
|
|
||||||
mju_warningText
|
mju_warningText
|
||||||
~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|||||||
@@ -1095,6 +1095,9 @@ MJAPI const char* mju_type2Str(int type);
|
|||||||
// Convert type name to type id (mjtObj).
|
// Convert type name to type id (mjtObj).
|
||||||
MJAPI int mju_str2Type(const char* str);
|
MJAPI int mju_str2Type(const char* str);
|
||||||
|
|
||||||
|
// Return human readable number of bytes using standard letter suffix.
|
||||||
|
MJAPI const char* mju_writeNumBytes(const size_t nbytes);
|
||||||
|
|
||||||
// Construct a warning message given the warning type and info.
|
// Construct a warning message given the warning type and info.
|
||||||
MJAPI const char* mju_warningText(int warning, size_t info);
|
MJAPI const char* mju_warningText(int warning, size_t info);
|
||||||
|
|
||||||
|
|||||||
@@ -6937,6 +6937,20 @@ FUNCTIONS: Mapping[str, FunctionDecl] = dict([
|
|||||||
),
|
),
|
||||||
doc='Convert type name to type id (mjtObj).',
|
doc='Convert type name to type id (mjtObj).',
|
||||||
)),
|
)),
|
||||||
|
('mju_writeNumBytes',
|
||||||
|
FunctionDecl(
|
||||||
|
name='mju_writeNumBytes',
|
||||||
|
return_type=PointerType(
|
||||||
|
inner_type=ValueType(name='char', is_const=True),
|
||||||
|
),
|
||||||
|
parameters=(
|
||||||
|
FunctionParameterDecl(
|
||||||
|
name='nbytes',
|
||||||
|
type=ValueType(name='size_t', is_const=True),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
doc='Return human readable number of bytes using standard letter suffix.', # pylint: disable=line-too-long
|
||||||
|
)),
|
||||||
('mju_warningText',
|
('mju_warningText',
|
||||||
FunctionDecl(
|
FunctionDecl(
|
||||||
name='mju_warningText',
|
name='mju_warningText',
|
||||||
|
|||||||
@@ -1061,6 +1061,7 @@ PYBIND11_MODULE(_functions, pymodule) {
|
|||||||
Def<traits::mju_round>(pymodule);
|
Def<traits::mju_round>(pymodule);
|
||||||
Def<traits::mju_type2Str>(pymodule);
|
Def<traits::mju_type2Str>(pymodule);
|
||||||
Def<traits::mju_str2Type>(pymodule);
|
Def<traits::mju_str2Type>(pymodule);
|
||||||
|
Def<traits::mju_writeNumBytes>(pymodule);
|
||||||
Def<traits::mju_warningText>(pymodule);
|
Def<traits::mju_warningText>(pymodule);
|
||||||
Def<traits::mju_isBad>(pymodule);
|
Def<traits::mju_isBad>(pymodule);
|
||||||
DEF_WITH_OMITTED_PY_ARGS(traits::mju_isZero, "n")(
|
DEF_WITH_OMITTED_PY_ARGS(traits::mju_isZero, "n")(
|
||||||
|
|||||||
@@ -33,6 +33,13 @@
|
|||||||
#define mjMAX(a, b) (((a) > (b)) ? (a) : (b))
|
#define mjMAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||||
#define mjMIN(a, b) (((a) < (b)) ? (a) : (b))
|
#define mjMIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||||
|
|
||||||
|
// thread local macro
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#define mjTHREADLOCAL __declspec(thread)
|
||||||
|
#else
|
||||||
|
#define mjTHREADLOCAL _Thread_local
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
//-------------------------- timer macros ----------------------------------------------------------
|
//-------------------------- timer macros ----------------------------------------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "engine/engine_macro.h"
|
||||||
//------------------------- cross-platform aligned malloc/free -------------------------------------
|
//------------------------- cross-platform aligned malloc/free -------------------------------------
|
||||||
|
|
||||||
static inline void* mju_alignedMalloc(size_t size, size_t align) {
|
static inline void* mju_alignedMalloc(size_t size, size_t align) {
|
||||||
@@ -73,11 +74,6 @@ void mju_clearHandlers(void) {
|
|||||||
|
|
||||||
typedef void (*callback_fn)(const char*);
|
typedef void (*callback_fn)(const char*);
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#define mjTHREADLOCAL __declspec(thread)
|
|
||||||
#else
|
|
||||||
#define mjTHREADLOCAL _Thread_local
|
|
||||||
#endif
|
|
||||||
static mjTHREADLOCAL callback_fn _mjPRIVATE_tls_error_fn = NULL;
|
static mjTHREADLOCAL callback_fn _mjPRIVATE_tls_error_fn = NULL;
|
||||||
static mjTHREADLOCAL callback_fn _mjPRIVATE_tls_warning_fn = NULL;
|
static mjTHREADLOCAL callback_fn _mjPRIVATE_tls_warning_fn = NULL;
|
||||||
|
|
||||||
|
|||||||
@@ -946,9 +946,30 @@ int mju_str2Type(const char* str) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// return human readable number of bytes using standard letter suffix
|
||||||
|
const char* mju_writeNumBytes(const size_t nbytes) {
|
||||||
|
int i;
|
||||||
|
static mjTHREADLOCAL char message[20];
|
||||||
|
static const char suffix[] = " KMGTPE";
|
||||||
|
for (i=0; i<6; i++) {
|
||||||
|
const size_t bits = (size_t)(1) << (10*(6-i));
|
||||||
|
if (nbytes >= bits && !(nbytes & (bits - 1))) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i<6) {
|
||||||
|
mjSNPRINTF(message, "%zu%c", nbytes >> (10*(6-i)), suffix[6-i]);
|
||||||
|
} else {
|
||||||
|
mjSNPRINTF(message, "%zu", nbytes >> (10*(6-i)));
|
||||||
|
}
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// warning text
|
// warning text
|
||||||
const char* mju_warningText(int warning, size_t info) {
|
const char* mju_warningText(int warning, size_t info) {
|
||||||
static char str[1000];
|
static mjTHREADLOCAL char str[1000];
|
||||||
|
|
||||||
switch (warning) {
|
switch (warning) {
|
||||||
case mjWARN_INERTIA:
|
case mjWARN_INERTIA:
|
||||||
@@ -965,7 +986,7 @@ const char* mju_warningText(int warning, size_t info) {
|
|||||||
case mjWARN_CNSTRFULL:
|
case mjWARN_CNSTRFULL:
|
||||||
mjSNPRINTF(str,
|
mjSNPRINTF(str,
|
||||||
"Insufficient arena memory for the number of constraints generated. "
|
"Insufficient arena memory for the number of constraints generated. "
|
||||||
"Increase arena memory allocation above %zu bytes.", info);
|
"Increase arena memory allocation above %s bytes.", mju_writeNumBytes(info));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case mjWARN_VGEOMFULL:
|
case mjWARN_VGEOMFULL:
|
||||||
|
|||||||
@@ -87,6 +87,9 @@ MJAPI const char* mju_type2Str(int type);
|
|||||||
// convert type name to type id (mjtObj)
|
// convert type name to type id (mjtObj)
|
||||||
MJAPI int mju_str2Type(const char* str);
|
MJAPI int mju_str2Type(const char* str);
|
||||||
|
|
||||||
|
// return human readable number of bytes using standard letter suffix
|
||||||
|
MJAPI const char* mju_writeNumBytes(const size_t nbytes);
|
||||||
|
|
||||||
// warning text
|
// warning text
|
||||||
MJAPI const char* mju_warningText(int warning, size_t info);
|
MJAPI const char* mju_warningText(int warning, size_t info);
|
||||||
|
|
||||||
|
|||||||
@@ -830,28 +830,7 @@ void mjXWriter::Size(XMLElement* root) {
|
|||||||
|
|
||||||
// write memory
|
// write memory
|
||||||
if (model->memory != -1) {
|
if (model->memory != -1) {
|
||||||
const std::size_t memory = static_cast<std::size_t>(model->memory);
|
WriteAttrTxt(section, "memory", mju_writeNumBytes(model->memory));
|
||||||
const std::vector<std::pair<int, char>> kSuffix = {
|
|
||||||
{60, 'E'}, {50, 'P'}, {40, 'T'}, {30, 'G'}, {20, 'M'}, {10, 'K'},
|
|
||||||
};
|
|
||||||
|
|
||||||
std::ostringstream strm;
|
|
||||||
|
|
||||||
// check for divisibility by each suffixed size
|
|
||||||
for (const auto& [multiplier_bit, suffix_char] : kSuffix) {
|
|
||||||
const std::size_t multiplier = static_cast<std::size_t>(1) << multiplier_bit;
|
|
||||||
if (memory >= multiplier && !(memory & (multiplier - 1))) {
|
|
||||||
strm << (memory >> multiplier_bit) << suffix_char;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// doesn't match any suffix, just write the number out as-is
|
|
||||||
if (!strm.tellp()) {
|
|
||||||
strm << memory;
|
|
||||||
}
|
|
||||||
|
|
||||||
WriteAttrTxt(section, "memory", strm.str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// write sizes
|
// write sizes
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
// Copyright 2021 DeepMind Technologies Limited
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// Tests for engine/engine_util_solve.c.
|
||||||
|
|
||||||
|
#include <gmock/gmock.h>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <mujoco/mjdata.h>
|
||||||
|
#include <mujoco/mujoco.h>
|
||||||
|
#include "test/fixture.h"
|
||||||
|
|
||||||
|
namespace mujoco {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
using ::testing::HasSubstr;
|
||||||
|
|
||||||
|
TEST_F(MujocoTest, PrintsMemoryWarning) {
|
||||||
|
EXPECT_THAT(mju_warningText(mjWARN_CNSTRFULL, pow(2, 10)), HasSubstr("1K bytes"));
|
||||||
|
EXPECT_THAT(mju_warningText(mjWARN_CNSTRFULL, pow(2, 20)), HasSubstr("1M bytes"));
|
||||||
|
EXPECT_THAT(mju_warningText(mjWARN_CNSTRFULL, pow(2, 30)), HasSubstr("1G bytes"));
|
||||||
|
EXPECT_THAT(mju_warningText(mjWARN_CNSTRFULL, pow(2, 40)), HasSubstr("1T bytes"));
|
||||||
|
EXPECT_THAT(mju_warningText(mjWARN_CNSTRFULL, pow(2, 50)), HasSubstr("1P bytes"));
|
||||||
|
EXPECT_THAT(mju_warningText(mjWARN_CNSTRFULL, pow(2, 60)), HasSubstr("1E bytes"));
|
||||||
|
EXPECT_THAT(mju_warningText(mjWARN_CNSTRFULL, pow(2, 30)+1), HasSubstr("1073741825 bytes"));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
} // namespace mujoco
|
||||||
@@ -3516,6 +3516,10 @@ public static unsafe extern string mju_type2Str(int type);
|
|||||||
[DllImport("mujoco", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport("mujoco", CallingConvention = CallingConvention.Cdecl)]
|
||||||
public static unsafe extern int mju_str2Type([MarshalAs(UnmanagedType.LPStr)]string str);
|
public static unsafe extern int mju_str2Type([MarshalAs(UnmanagedType.LPStr)]string str);
|
||||||
|
|
||||||
|
[DllImport("mujoco", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
[return: MarshalAs(UnmanagedType.LPStr)]
|
||||||
|
public static unsafe extern string mju_writeNumBytes(UIntPtr nbytes);
|
||||||
|
|
||||||
[DllImport("mujoco", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport("mujoco", CallingConvention = CallingConvention.Cdecl)]
|
||||||
[return: MarshalAs(UnmanagedType.LPStr)]
|
[return: MarshalAs(UnmanagedType.LPStr)]
|
||||||
public static unsafe extern string mju_warningText(int warning, UIntPtr info);
|
public static unsafe extern string mju_warningText(int warning, UIntPtr info);
|
||||||
|
|||||||
Reference in New Issue
Block a user