registrar: Avoid cloning buffers when delivering messages in most cases.

If we succeed in sending the message on the first try, then we don't
need to allocate anything at all.

This two allocations and a memcpy in the fast path (which is
hit the vast majority of the time, it appears.)
This commit is contained in:
Augustin Cavalier
2025-02-12 16:42:00 -05:00
parent ff808e1b64
commit bf13ecf7cf
+20 -15
View File
@@ -640,19 +640,7 @@ MessageDeliverer::DeliverMessage(const void *messageData, int32 messageSize,
if (!messageData || messageSize <= 0)
return B_BAD_VALUE;
// clone the buffer
void *data = malloc(messageSize);
if (!data)
return B_NO_MEMORY;
memcpy(data, messageData, messageSize);
// create a Message
Message *message = new(nothrow) Message(data, messageSize, timeout);
if (!message) {
free(data);
return B_NO_MEMORY;
}
BReference<Message> _(message, true);
BReference<Message> messageRef;
// add the message to the respective target ports
BAutolock locker(fLock);
@@ -668,7 +656,8 @@ MessageDeliverer::DeliverMessage(const void *messageData, int32 messageSize,
// try sending the message, if there are no queued messages yet
if (port->IsEmpty()) {
status_t error = _SendMessage(message, portID, token);
status_t error = BMessage::Private::SendFlattenedMessage((void*)messageData,
messageSize, portID, token, 0);
// if the message was delivered OK, we're done with the target
if (error == B_OK) {
_PutTargetPort(port);
@@ -684,8 +673,24 @@ MessageDeliverer::DeliverMessage(const void *messageData, int32 messageSize,
}
}
if (!messageRef.IsSet()) {
// clone the buffer
void *data = malloc(messageSize);
if (!data)
return B_NO_MEMORY;
memcpy(data, messageData, messageSize);
// create a Message
Message *message = new(nothrow) Message(data, messageSize, timeout);
if (!message) {
free(data);
return B_NO_MEMORY;
}
messageRef.SetTo(message, true);
}
// add the message
status_t error = port->PushMessage(message, token);
status_t error = port->PushMessage(messageRef, token);
_PutTargetPort(port);
if (error != B_OK)
return error;