Format memory warning in human-friendly way.

PiperOrigin-RevId: 486610408
Change-Id: I6beecb12059e69f4407e921d20efc54ce6b3f491
This commit is contained in:
Alessio Quaglino
2022-11-07 02:55:37 -08:00
committed by Copybara-Service
parent fc24097b92
commit fd4d47e4a5
11 changed files with 107 additions and 29 deletions
+11
View File
@@ -6601,6 +6601,17 @@ Convert type name to type id (mjtObj).
.. _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
~~~~~~~~~~~~~~~
+3
View File
@@ -1095,6 +1095,9 @@ MJAPI const char* mju_type2Str(int type);
// Convert type name to type id (mjtObj).
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.
MJAPI const char* mju_warningText(int warning, size_t info);
+14
View File
@@ -6937,6 +6937,20 @@ FUNCTIONS: Mapping[str, FunctionDecl] = dict([
),
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',
FunctionDecl(
name='mju_warningText',
+1
View File
@@ -1061,6 +1061,7 @@ PYBIND11_MODULE(_functions, pymodule) {
Def<traits::mju_round>(pymodule);
Def<traits::mju_type2Str>(pymodule);
Def<traits::mju_str2Type>(pymodule);
Def<traits::mju_writeNumBytes>(pymodule);
Def<traits::mju_warningText>(pymodule);
Def<traits::mju_isBad>(pymodule);
DEF_WITH_OMITTED_PY_ARGS(traits::mju_isZero, "n")(
+7
View File
@@ -33,6 +33,13 @@
#define mjMAX(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 ----------------------------------------------------------
+1 -5
View File
@@ -24,6 +24,7 @@
#include <unistd.h>
#endif
#include "engine/engine_macro.h"
//------------------------- cross-platform aligned malloc/free -------------------------------------
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*);
#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_warning_fn = NULL;
+23 -2
View File
@@ -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
const char* mju_warningText(int warning, size_t info) {
static char str[1000];
static mjTHREADLOCAL char str[1000];
switch (warning) {
case mjWARN_INERTIA:
@@ -965,7 +986,7 @@ const char* mju_warningText(int warning, size_t info) {
case mjWARN_CNSTRFULL:
mjSNPRINTF(str,
"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;
case mjWARN_VGEOMFULL:
+3
View File
@@ -87,6 +87,9 @@ MJAPI const char* mju_type2Str(int type);
// convert type name to type id (mjtObj)
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
MJAPI const char* mju_warningText(int warning, size_t info);
+1 -22
View File
@@ -830,28 +830,7 @@ void mjXWriter::Size(XMLElement* root) {
// write memory
if (model->memory != -1) {
const std::size_t memory = static_cast<std::size_t>(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());
WriteAttrTxt(section, "memory", mju_writeNumBytes(model->memory));
}
// write sizes
+39
View File
@@ -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
+4
View File
@@ -3516,6 +3516,10 @@ public static unsafe extern string mju_type2Str(int type);
[DllImport("mujoco", CallingConvention = CallingConvention.Cdecl)]
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)]
[return: MarshalAs(UnmanagedType.LPStr)]
public static unsafe extern string mju_warningText(int warning, UIntPtr info);