Looks like the problem is with receipts.
I ran some additional tests without using receipts and was able to do about 4000 messages per second in these message size ranges. As soon as I enable receiving of receipts, it goes back to 24 messages per second. I'm using the Net::STOMP::Client module. The documentation says this about receipts:
"By default, you do not get any confirmation that the message has indeed been received by the broker. If you want such a confirmation, you have to use receipts. The following code snippet sends two messages with a receipt header containing a pseudo-unique id and waits for matching RECEIPT frames coming from the broker. This is easy because the Net::STOMP::Client module keeps track of which receipts are expected and have not been received yet."
I am using the ack => 'client' parameter when subscribing to a queue. Seems like sending an ack would be sufficient, but apparently I also need to send a receipt.