More optimization for Message2. It now uses a more lightweight BSimpleMallocIO instead of the full blown BMallocIO. This wastes less memory and reduces unnecessary overhead when unflattening.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13861 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz
2005-07-31 11:48:38 +00:00
parent 4835f2d292
commit 43abf8a345
7 changed files with 197 additions and 126 deletions
+4 -2
View File
@@ -43,7 +43,7 @@ public:
status_t Flatten(BDataIO *stream) const;
status_t Unflatten(BDataIO *stream);
status_t AddData(const char *name, BMallocIO *buffer,
status_t AddData(const char *name, BSimpleMallocIO *buffer,
type_code type);
status_t RemoveData(const char *name, int32 index = 0);
@@ -52,7 +52,7 @@ public:
int32 index, const void **data,
ssize_t *numBytes) const;
status_t ReplaceData(const char *name, int32 index,
BMallocIO *buffer, type_code type);
BSimpleMallocIO *buffer, type_code type);
status_t Rename(const char *oldName, const char *newName);
status_t RemoveName(const char *name);
@@ -77,6 +77,8 @@ private:
BList fFieldList;
BMessageField **fFieldTable;
int32 fFieldTableSize;
mutable ssize_t fFlattenedSize;
};
} // namespace BPrivate
+5 -4
View File
@@ -25,6 +25,8 @@
namespace BPrivate {
class BSimpleMallocIO;
class BMessageField {
public:
BMessageField();
@@ -41,10 +43,9 @@ public:
uint8 NameLength() const { return fName.Length(); };
type_code Type() const { return fType; };
void AddItem(BMallocIO *item);
void ReplaceItem(int32 index, BMallocIO *item,
bool deleteOld = true);
void RemoveItem(int32 index, bool deleteIt = true);
void AddItem(BSimpleMallocIO *item);
void ReplaceItem(int32 index, BSimpleMallocIO *item);
void RemoveItem(int32 index);
int32 CountItems() const { return fItems.CountItems(); };
size_t SizeAt(int32 index) const;
const void *BufferAt(int32 index) const;
+2 -3
View File
@@ -116,15 +116,14 @@ public:
if (fError < B_OK)
throw fError;
if (IsSwapping()) {
if (IsSwapping())
byte_swap(data);
}
}
template<class T>
inline void operator()(T data, size_t len)
{
fError = fStream->Read((void*)data, len);
fError = fStream->Read((void *)data, len);
if (fError < B_OK)
throw fError;
}
+88
View File
@@ -0,0 +1,88 @@
/*
* Copyright 2005, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Michael Lotz <[email protected]>
*/
/* A BMallocIO similar structure but with less overhead */
#ifndef _SIMPLE_MALLOC_IO_H_
#define _SIMPLE_MALLOC_IO_H_
#include <malloc.h>
namespace BPrivate {
class BSimpleMallocIO {
public:
BSimpleMallocIO(size_t size)
: fSize(size)
{
fBuffer = (char *)malloc(size);
}
~BSimpleMallocIO()
{
free(fBuffer);
}
void Read(void *buffer)
{
memcpy(buffer, fBuffer, fSize);
}
void Read(void *buffer, size_t size)
{
memcpy(buffer, fBuffer, size);
}
void ReadAt(off_t pos, void *buffer, size_t size)
{
memcpy(buffer, fBuffer + pos, size);
}
void Write(const void *buffer)
{
memcpy(fBuffer, buffer, fSize);
}
void Write(const void *buffer, size_t size)
{
memcpy(fBuffer, buffer, size);
}
void WriteAt(off_t pos, const void *buffer, size_t size)
{
memcpy(fBuffer + pos, buffer, size);
}
status_t SetSize(off_t size)
{
fBuffer = (char *)realloc(fBuffer, size);
if (!fBuffer)
return B_NO_MEMORY;
fSize = size;
return B_OK;
}
char *Buffer()
{
return fBuffer;
}
size_t BufferLength()
{
return fSize;
}
private:
char *fBuffer;
size_t fSize;
};
} // namespace BPivate
#endif // _SIMPLE_MALLOC_IO_H_
+32 -35
View File
@@ -34,11 +34,12 @@
#include <AppMisc.h>
#include <KMessage.h>
#include <MessageUtils2.h>
#include <TokenSpace.h>
#include "MessageBody2.h"
#include "MessageField2.h"
#include "MessageUtils2.h"
#include "SimpleMallocIO.h"
#include "dano_message.h"
// flags for the overall message (the bitfield is 1 byte)
@@ -873,9 +874,6 @@ BMessage::Unflatten(BDataIO *stream)
header.WriteTo(*this);
status = fBody->Unflatten(stream);
if (status < B_OK)
return status;
} catch (status_t &error) {
status = error;
}
@@ -1152,11 +1150,9 @@ BMessage::AddMessenger(const char *name, BMessenger messenger)
status_t
BMessage::AddRef(const char* name, const entry_ref* ref)
{
BMallocIO *buffer = new BMallocIO();
buffer->SetSize(sizeof(entry_ref) + B_PATH_NAME_LENGTH);
size_t size;
status_t error = entry_ref_flatten((char *)buffer->Buffer(), &size, ref);
size_t size = sizeof(entry_ref) + B_PATH_NAME_LENGTH;
BSimpleMallocIO *buffer = new BSimpleMallocIO(size);
status_t error = entry_ref_flatten(buffer->Buffer(), &size, ref);
buffer->SetSize(size);
if (error >= B_OK)
@@ -1172,8 +1168,9 @@ BMessage::AddRef(const char* name, const entry_ref* ref)
status_t
BMessage::AddMessage(const char *name, const BMessage *msg)
{
BMallocIO *buffer = new BMallocIO();
status_t error = msg->Flatten(buffer);
size_t size = msg->FlattenedSize();
BSimpleMallocIO *buffer = new BSimpleMallocIO(size);
status_t error = msg->Flatten(buffer->Buffer(), size);
if (error >= B_OK)
error = fBody->AddData(name, buffer, B_MESSAGE_TYPE);
@@ -1189,10 +1186,9 @@ status_t
BMessage::AddFlat(const char *name, BFlattenable *object, int32 count)
{
ssize_t size = object->FlattenedSize();
BMallocIO *buffer = new BMallocIO();
buffer->SetSize(size);
BSimpleMallocIO *buffer = new BSimpleMallocIO(size);
status_t error = object->Flatten(buffer->Buffer(), size);
status_t error = object->Flatten((void *)buffer->Buffer(), size);
if (error >= B_OK)
error = fBody->AddData(name, buffer, object->TypeCode());
@@ -1212,8 +1208,8 @@ BMessage::AddData(const char *name, type_code type, const void *data,
// the user attempts to add something bigger or smaller. We may need to
// enforce the size thing.
BMallocIO *buffer = new BMallocIO();
buffer->Write(data, numBytes);
BSimpleMallocIO *buffer = new BSimpleMallocIO(numBytes);
buffer->Write(data);
status_t error = fBody->AddData(name, buffer, type);
if (error < B_OK)
@@ -1364,7 +1360,7 @@ BMessage::FindMessage(const char *name, int32 index, BMessage *msg) const
status_t error = FindData(name, B_MESSAGE_TYPE, index, (const void **)&data, &size);
if (!error)
error = msg->Unflatten((const char*)data);
error = msg->Unflatten((const char *)data);
else
*msg = BMessage();
@@ -1493,11 +1489,9 @@ BMessage::ReplaceRef(const char *name, const entry_ref *ref)
status_t
BMessage::ReplaceRef(const char *name, int32 index, const entry_ref *ref)
{
BMallocIO *buffer = new BMallocIO();
buffer->SetSize(sizeof(entry_ref) + B_PATH_NAME_LENGTH);
size_t size;
status_t error = entry_ref_flatten((char *)buffer->Buffer(), &size, ref);
size_t size = sizeof(entry_ref) + B_PATH_NAME_LENGTH;
BSimpleMallocIO *buffer = new BSimpleMallocIO(size);
status_t error = entry_ref_flatten(buffer->Buffer(), &size, ref);
buffer->SetSize(size);
if (error >= B_OK)
@@ -1520,8 +1514,9 @@ BMessage::ReplaceMessage(const char *name, const BMessage *msg)
status_t
BMessage::ReplaceMessage(const char *name, int32 index, const BMessage *msg)
{
BMallocIO *buffer = new BMallocIO();
status_t error = msg->Flatten(buffer);
size_t size = msg->FlattenedSize();
BSimpleMallocIO *buffer = new BSimpleMallocIO(size);
status_t error = msg->Flatten(buffer->Buffer(), size);
if (error >= B_OK)
error = fBody->ReplaceData(name, index, buffer, B_MESSAGE_TYPE);
@@ -1544,10 +1539,9 @@ status_t
BMessage::ReplaceFlat(const char *name, int32 index, BFlattenable *object)
{
ssize_t size = object->FlattenedSize();
BMallocIO *buffer = new BMallocIO();
buffer->SetSize(size);
BSimpleMallocIO *buffer = new BSimpleMallocIO(size);
status_t error = object->Flatten(buffer->Buffer(), size);
status_t error = object->Flatten((void *)buffer->Buffer(), size);
if (error >= B_OK)
error = fBody->ReplaceData(name, index, buffer, object->TypeCode());
@@ -1570,8 +1564,8 @@ status_t
BMessage::ReplaceData(const char *name, type_code type, int32 index,
const void *data, ssize_t data_size)
{
BMallocIO *buffer = new BMallocIO();
buffer->Write(data, data_size);
BSimpleMallocIO *buffer = new BSimpleMallocIO(data_size);
buffer->Write(data);
status_t error = fBody->ReplaceData(name, index, buffer, type);
if (error < B_OK)
@@ -1629,7 +1623,7 @@ BMessage::operator delete(void *ptr, size_t size)
status_t
BMessage::real_flatten(char *result, ssize_t size) const
{
BMemoryIO stream((void*)result, size);
BMemoryIO stream((void *)result, size);
return real_flatten(&stream, NULL);
}
@@ -1640,9 +1634,12 @@ BMessage::real_flatten(BDataIO *stream, ssize_t *size) const
Header header(*this);
status_t error = header.WriteTo(*stream);
if (!error)
if (error >= B_OK)
error = fBody->Flatten(stream);
if (size)
*size = FlattenedSize();
return error;
}
@@ -1686,14 +1683,14 @@ BMessage::calc_hdr_size(uchar flags) const
ssize_t size = min_hdr_size();
if (fTarget != B_NULL_TOKEN)
size += sizeof (fTarget);
size += sizeof(fTarget);
if (fReplyTo.port >= 0
&& fReplyTo.target != B_NULL_TOKEN
&& fReplyTo.team >= 0) {
size += sizeof (fReplyTo.port);
size += sizeof (fReplyTo.target);
size += sizeof (fReplyTo.team);
size += sizeof(fReplyTo.port);
size += sizeof(fReplyTo.target);
size += sizeof(fReplyTo.team);
size += 4; // For the "big" flags
}
+43 -50
View File
@@ -9,14 +9,17 @@
/* BMessageBody handles data storage and retrieval for BMessage. */
#include <stdio.h>
#include <DataIO.h>
#include <MessageUtils.h>
#include <TypeConstants.h>
#include "MessageBody2.h"
#include "MessageUtils2.h"
#include "SimpleMallocIO.h"
namespace BPrivate {
static int64 sPadding[2] = { 0, 0 };
static uint8 sPadLengths[8] = { 4, 3, 2, 1, 0, 7, 6, 5 };
#define CALC_PADDING_8(x) sPadLengths[x % 8]
BMessageBody::BMessageBody()
{
@@ -59,6 +62,7 @@ BMessageBody::operator=(const BMessageBody &other)
status_t
BMessageBody::InitCommon()
{
fFlattenedSize = -1;
fFieldTableSize = 100;
fFieldTable = new BMessageField *[fFieldTableSize];
HashClear();
@@ -201,6 +205,7 @@ BMessageBody::Rename(const char *oldName, const char *newName)
field->SetName(newName);
HashInsert(HashRemove(oldName));
fFlattenedSize = -1;
return B_OK;
}
@@ -208,6 +213,9 @@ BMessageBody::Rename(const char *oldName, const char *newName)
ssize_t
BMessageBody::FlattenedSize() const
{
if (fFlattenedSize > 0)
return fFlattenedSize;
ssize_t size = 1; // for MSG_LAST_ENTRY
for (int32 index = 0; index < fFieldList.CountItems(); index++) {
@@ -233,15 +241,12 @@ BMessageBody::FlattenedSize() const
// name length byte and name length
size += 1 + field->NameLength();
// individual sizes
if (!(flags & MSG_FLAG_FIXED_SIZE)) {
size += field->CountItems() * sizeof(size_t);
size += field->TotalPadding();
}
size += field->TotalSize();
}
// cache the value for next time.
// changing the body will reset this.
fFlattenedSize = size;
return size;
}
@@ -249,8 +254,6 @@ BMessageBody::FlattenedSize() const
status_t
BMessageBody::Flatten(BDataIO *stream) const
{
status_t error = B_OK;
for (int32 index = 0; index < fFieldList.CountItems(); index++) {
BMessageField *field = (BMessageField *)fFieldList.ItemAt(index);
@@ -270,16 +273,8 @@ BMessageBody::Flatten(BDataIO *stream) const
stream->Write(&count, sizeof(count));
}
bool isFixed = flags & MSG_FLAG_FIXED_SIZE;
// overall data size
// overall data size (includes padding for non fixed size fields)
size_t size = field->TotalSize();
if (!isFixed) {
// add bytes for holding each items size
size += count * sizeof(size_t);
size += field->TotalPadding();
}
if (flags & MSG_FLAG_MINI_DATA) {
uint8 miniSize = (uint8)size;
stream->Write(&miniSize, sizeof(miniSize));
@@ -293,32 +288,29 @@ BMessageBody::Flatten(BDataIO *stream) const
// name
stream->Write(field->Name(), nameLength);
// if we have a fixed size we initialize size once here
if (isFixed)
size = field->SizeAt(0);
// data items
for (int32 dataIndex = 0; dataIndex < count; dataIndex++) {
if (!isFixed) {
// set the size for each item
if (flags & MSG_FLAG_FIXED_SIZE) {
size = field->SizeAt(0);
for (int32 dataIndex = 0; dataIndex < count; dataIndex++)
stream->Write(field->BufferAt(dataIndex), size);
} else {
for (int32 dataIndex = 0; dataIndex < count; dataIndex++) {
size = field->SizeAt(dataIndex);
stream->Write(&size, sizeof(size));
stream->Write(field->BufferAt(dataIndex), size);
size_t error = stream->Write(sPadding, CALC_PADDING_8(size));
}
error = stream->Write(field->BufferAt(dataIndex), size);
if (!isFixed)
error = stream->Write(sPadding, calc_padding(size + 4, 8));
}
}
if (error >= B_OK) {
uint8 lastEntry = 0;
error = stream->Write(&lastEntry, sizeof(lastEntry));
}
uint8 lastEntry = 0;
size_t error = stream->Write(&lastEntry, sizeof(lastEntry));
if (error >= B_OK)
if (error > B_OK)
return B_OK;
else if (error == 0)
return B_ERROR;
return error;
}
@@ -344,6 +336,7 @@ BMessageBody::Unflatten(BDataIO *stream)
int32 itemCount;
int32 dataLength;
uint8 littleData;
if (flags & MSG_FLAG_SINGLE_ITEM) {
itemCount = 1;
@@ -398,9 +391,8 @@ BMessageBody::Unflatten(BDataIO *stream)
int32 itemSize = dataLength / itemCount;
for (int32 index = 0; index < itemCount; index++) {
BMallocIO *buffer = new BMallocIO();
buffer->SetSize(itemSize);
reader((char *)buffer->Buffer(), itemSize);
BSimpleMallocIO *buffer = new BSimpleMallocIO(itemSize);
reader(buffer->Buffer(), itemSize);
field->AddItem(buffer);
}
} else {
@@ -408,12 +400,10 @@ BMessageBody::Unflatten(BDataIO *stream)
ssize_t dataLength;
for (int32 index = 0; index < itemCount; index++) {
BMallocIO *buffer = new BMallocIO();
reader(dataLength);
buffer->SetSize(dataLength);
reader((char *)buffer->Buffer(), dataLength);
reader(padding, calc_padding(dataLength + 4, 8));
BSimpleMallocIO *buffer = new BSimpleMallocIO(dataLength);
reader(buffer->Buffer(), dataLength);
reader(padding, CALC_PADDING_8(dataLength));
field->AddItem(buffer);
}
}
@@ -429,7 +419,7 @@ BMessageBody::Unflatten(BDataIO *stream)
status_t
BMessageBody::AddData(const char *name, BMallocIO *buffer, type_code type)
BMessageBody::AddData(const char *name, BSimpleMallocIO *buffer, type_code type)
{
status_t error = B_OK;
BMessageField *foundField = FindData(name, type, error);
@@ -457,6 +447,7 @@ BMessageBody::AddData(const char *name, BMallocIO *buffer, type_code type)
foundField->AddItem(buffer);
}
fFlattenedSize = -1;
return error;
}
@@ -485,7 +476,7 @@ BMessageBody::AddField(const char *name, type_code type, status_t &error)
status_t
BMessageBody::ReplaceData(const char *name, int32 index, BMallocIO *buffer,
BMessageBody::ReplaceData(const char *name, int32 index, BSimpleMallocIO *buffer,
type_code type)
{
if (type == B_ANY_TYPE)
@@ -501,6 +492,7 @@ BMessageBody::ReplaceData(const char *name, int32 index, BMallocIO *buffer,
return B_ERROR;
field->ReplaceItem(index, buffer);
fFlattenedSize = -1;
return error;
}
@@ -508,9 +500,8 @@ BMessageBody::ReplaceData(const char *name, int32 index, BMallocIO *buffer,
status_t
BMessageBody::RemoveData(const char *name, int32 index)
{
if (index < 0) {
if (index < 0)
return B_BAD_VALUE;
}
status_t error = B_OK;
BMessageField *field = FindData(name, B_ANY_TYPE, error);
@@ -518,10 +509,10 @@ BMessageBody::RemoveData(const char *name, int32 index)
if (field) {
if (index < field->CountItems()) {
field->RemoveItem(index);
fFlattenedSize = -1;
if (field->CountItems() == 0) {
if (field->CountItems() == 0)
RemoveName(name);
}
} else
error = B_BAD_INDEX;
}
@@ -538,6 +529,7 @@ BMessageBody::RemoveName(const char *name)
if (field) {
fFieldList.RemoveItem(field);
fFlattenedSize = -1;
HashRemove(name);
delete field;
}
@@ -555,6 +547,7 @@ BMessageBody::MakeEmpty()
}
fFieldList.MakeEmpty();
fFlattenedSize = -1;
HashClear();
return B_OK;
}
+23 -32
View File
@@ -7,18 +7,18 @@
*/
#include <stdio.h>
#include <DataIO.h>
#include <MessageUtils.h>
#include <TypeConstants.h>
#include "MessageField2.h"
#include "SimpleMallocIO.h"
namespace BPrivate {
#define ROUND_TO_8(x) (fFixedSize ? x : (x + 11) & ~7)
BMessageField::BMessageField()
: fType(0),
fFixedSize(false),
fTotalSize(0),
fTotalPadding(0),
fNext(NULL)
{
SetName("");
@@ -28,7 +28,6 @@ BMessageField::BMessageField()
BMessageField::BMessageField(const char *name, type_code type)
: fType(type),
fTotalSize(0),
fTotalPadding(0),
fNext(NULL)
{
SetName(name);
@@ -58,13 +57,12 @@ BMessageField::operator=(const BMessageField &other)
fType = other.fType;
fFixedSize = other.fFixedSize;
fTotalSize = other.fTotalSize;
fTotalPadding = other.fTotalPadding;
fNext = NULL;
for (int32 index = 0; index < other.fItems.CountItems(); index++) {
BMallocIO *otherBuffer = (BMallocIO *)other.fItems.ItemAt(index);
BMallocIO *newBuffer = new BMallocIO;
newBuffer->Write(otherBuffer->Buffer(), otherBuffer->BufferLength());
BSimpleMallocIO *otherBuffer = (BSimpleMallocIO *)other.fItems.ItemAt(index);
BSimpleMallocIO *newBuffer = new BSimpleMallocIO(otherBuffer->BufferLength());
newBuffer->Write(otherBuffer->Buffer());
fItems.AddItem((void *)newBuffer);
}
}
@@ -77,7 +75,7 @@ void
BMessageField::MakeEmpty()
{
for (int32 index = 0; index < fItems.CountItems(); index++) {
BMallocIO *item = (BMallocIO *)fItems.ItemAt(index);
BSimpleMallocIO *item = (BSimpleMallocIO *)fItems.ItemAt(index);
delete item;
}
@@ -89,11 +87,11 @@ uint8
BMessageField::Flags()
{
uint8 flags = MSG_FLAG_VALID;
if (fItems.CountItems() == 1)
flags |= MSG_FLAG_SINGLE_ITEM;
if (fTotalSize + fTotalPadding < 255)
if (fTotalSize < 255)
flags |= MSG_FLAG_MINI_DATA;
if (fFixedSize)
@@ -115,46 +113,39 @@ BMessageField::SetName(const char *name)
void
BMessageField::AddItem(BMallocIO *item)
BMessageField::AddItem(BSimpleMallocIO *item)
{
fItems.AddItem((void *)item);
fTotalSize += item->BufferLength();
fTotalPadding += calc_padding(item->BufferLength() + 4, 8);
fTotalSize += ROUND_TO_8(item->BufferLength());
}
void
BMessageField::ReplaceItem(int32 index, BMallocIO *item, bool deleteOld)
BMessageField::ReplaceItem(int32 index, BSimpleMallocIO *item)
{
BMallocIO *oldItem = (BMallocIO *)fItems.ItemAt(index);
fTotalSize -= oldItem->BufferLength();
fTotalPadding -= calc_padding(oldItem->BufferLength() + 4, 8);
BSimpleMallocIO *oldItem = (BSimpleMallocIO *)fItems.ItemAt(index);
fItems.ReplaceItem(index, item);
fTotalSize += item->BufferLength();
fTotalPadding += calc_padding(item->BufferLength() + 4, 8);
if (deleteOld)
delete oldItem;
fTotalSize -= ROUND_TO_8(oldItem->BufferLength());
fTotalSize += ROUND_TO_8(item->BufferLength());
delete oldItem;
}
void
BMessageField::RemoveItem(int32 index, bool deleteIt)
BMessageField::RemoveItem(int32 index)
{
BMallocIO *item = (BMallocIO *)fItems.RemoveItem(index);
fTotalSize -= item->BufferLength();
fTotalPadding -= calc_padding(item->BufferLength() + 4, 8);
if (deleteIt)
delete item;
BSimpleMallocIO *item = (BSimpleMallocIO *)fItems.RemoveItem(index);
fTotalSize -= ROUND_TO_8(item->BufferLength());
delete item;
}
size_t
BMessageField::SizeAt(int32 index) const
{
BMallocIO *buffer = (BMallocIO *)fItems.ItemAt(index);
BSimpleMallocIO *buffer = (BSimpleMallocIO *)fItems.ItemAt(index);
if (buffer)
return buffer->BufferLength();
@@ -166,7 +157,7 @@ BMessageField::SizeAt(int32 index) const
const void *
BMessageField::BufferAt(int32 index) const
{
BMallocIO *buffer = (BMallocIO *)fItems.ItemAt(index);
BSimpleMallocIO *buffer = (BSimpleMallocIO *)fItems.ItemAt(index);
if (buffer)
return buffer->Buffer();