benchmarks
This commit is contained in:
232
benches/actor_patterns.cm
Normal file
232
benches/actor_patterns.cm
Normal file
@@ -0,0 +1,232 @@
|
||||
// actor_patterns.cm — Actor concurrency benchmarks
|
||||
// Message passing, fan-out/fan-in, mailbox throughput.
|
||||
// These use structured benchmarks with setup/run/teardown.
|
||||
|
||||
// Note: actor benchmarks are measured differently from pure compute.
|
||||
// Each iteration sends messages and waits for results, so they're
|
||||
// inherently slower but test real concurrency costs.
|
||||
|
||||
// Simple ping-pong: two actors sending messages back and forth
|
||||
// Since we can't create real actors from a module, we simulate
|
||||
// the message-passing patterns with function call overhead that
|
||||
// mirrors what the actor dispatch does.
|
||||
|
||||
// Simulate message dispatch overhead
|
||||
function make_mailbox() {
|
||||
return {
|
||||
queue: [],
|
||||
delivered: 0
|
||||
}
|
||||
}
|
||||
|
||||
function send(mailbox, msg) {
|
||||
push(mailbox.queue, msg)
|
||||
return null
|
||||
}
|
||||
|
||||
function receive(mailbox) {
|
||||
if (length(mailbox.queue) == 0) return null
|
||||
mailbox.delivered++
|
||||
return pop(mailbox.queue)
|
||||
}
|
||||
|
||||
function drain(mailbox) {
|
||||
var count = 0
|
||||
while (length(mailbox.queue) > 0) {
|
||||
pop(mailbox.queue)
|
||||
count++
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
// Ping-pong: simulate two actors exchanging messages
|
||||
function ping_pong(rounds) {
|
||||
var box_a = make_mailbox()
|
||||
var box_b = make_mailbox()
|
||||
var i = 0
|
||||
var msg = null
|
||||
|
||||
send(box_a, {type: "ping", val: 0})
|
||||
|
||||
for (i = 0; i < rounds; i++) {
|
||||
// A receives and sends to B
|
||||
msg = receive(box_a)
|
||||
if (msg) {
|
||||
send(box_b, {type: "pong", val: msg.val + 1})
|
||||
}
|
||||
// B receives and sends to A
|
||||
msg = receive(box_b)
|
||||
if (msg) {
|
||||
send(box_a, {type: "ping", val: msg.val + 1})
|
||||
}
|
||||
}
|
||||
|
||||
return box_a.delivered + box_b.delivered
|
||||
}
|
||||
|
||||
// Fan-out: one sender, N receivers
|
||||
function fan_out(n_receivers, messages_per) {
|
||||
var receivers = []
|
||||
var i = 0
|
||||
var j = 0
|
||||
for (i = 0; i < n_receivers; i++) {
|
||||
push(receivers, make_mailbox())
|
||||
}
|
||||
|
||||
// Send messages to all receivers
|
||||
for (j = 0; j < messages_per; j++) {
|
||||
for (i = 0; i < n_receivers; i++) {
|
||||
send(receivers[i], {seq: j, data: j * 17})
|
||||
}
|
||||
}
|
||||
|
||||
// All receivers drain
|
||||
var total = 0
|
||||
for (i = 0; i < n_receivers; i++) {
|
||||
total += drain(receivers[i])
|
||||
}
|
||||
|
||||
return total
|
||||
}
|
||||
|
||||
// Fan-in: N senders, one receiver
|
||||
function fan_in(n_senders, messages_per) {
|
||||
var inbox = make_mailbox()
|
||||
var i = 0
|
||||
var j = 0
|
||||
|
||||
// Each sender sends messages
|
||||
for (i = 0; i < n_senders; i++) {
|
||||
for (j = 0; j < messages_per; j++) {
|
||||
send(inbox, {sender: i, seq: j, data: i * 100 + j})
|
||||
}
|
||||
}
|
||||
|
||||
// Receiver processes all
|
||||
var total = 0
|
||||
var msg = null
|
||||
msg = receive(inbox)
|
||||
while (msg) {
|
||||
total += msg.data
|
||||
msg = receive(inbox)
|
||||
}
|
||||
|
||||
return total
|
||||
}
|
||||
|
||||
// Pipeline: chain of processors
|
||||
function pipeline(stages, items) {
|
||||
var boxes = []
|
||||
var i = 0
|
||||
var j = 0
|
||||
var msg = null
|
||||
|
||||
for (i = 0; i <= stages; i++) {
|
||||
push(boxes, make_mailbox())
|
||||
}
|
||||
|
||||
// Feed input
|
||||
for (i = 0; i < items; i++) {
|
||||
send(boxes[0], {val: i})
|
||||
}
|
||||
|
||||
// Process each stage
|
||||
for (j = 0; j < stages; j++) {
|
||||
msg = receive(boxes[j])
|
||||
while (msg) {
|
||||
send(boxes[j + 1], {val: msg.val * 2 + 1})
|
||||
msg = receive(boxes[j])
|
||||
}
|
||||
}
|
||||
|
||||
// Drain output
|
||||
var total = 0
|
||||
msg = receive(boxes[stages])
|
||||
while (msg) {
|
||||
total += msg.val
|
||||
msg = receive(boxes[stages])
|
||||
}
|
||||
|
||||
return total
|
||||
}
|
||||
|
||||
// Request-response pattern (simulate RPC)
|
||||
function request_response(n_requests) {
|
||||
var client_box = make_mailbox()
|
||||
var server_box = make_mailbox()
|
||||
var i = 0
|
||||
var req = null
|
||||
var resp = null
|
||||
var total = 0
|
||||
|
||||
for (i = 0; i < n_requests; i++) {
|
||||
// Client sends request
|
||||
send(server_box, {id: i, payload: i * 3, reply_to: client_box})
|
||||
|
||||
// Server processes
|
||||
req = receive(server_box)
|
||||
if (req) {
|
||||
send(req.reply_to, {id: req.id, result: req.payload * 2 + 1})
|
||||
}
|
||||
|
||||
// Client receives response
|
||||
resp = receive(client_box)
|
||||
if (resp) {
|
||||
total += resp.result
|
||||
}
|
||||
}
|
||||
|
||||
return total
|
||||
}
|
||||
|
||||
return {
|
||||
// Ping-pong: 10K rounds
|
||||
ping_pong_10k: function(n) {
|
||||
var i = 0
|
||||
var x = 0
|
||||
for (i = 0; i < n; i++) {
|
||||
x += ping_pong(10000)
|
||||
}
|
||||
return x
|
||||
},
|
||||
|
||||
// Fan-out: 100 receivers, 100 messages each
|
||||
fan_out_100x100: function(n) {
|
||||
var i = 0
|
||||
var x = 0
|
||||
for (i = 0; i < n; i++) {
|
||||
x += fan_out(100, 100)
|
||||
}
|
||||
return x
|
||||
},
|
||||
|
||||
// Fan-in: 100 senders, 100 messages each
|
||||
fan_in_100x100: function(n) {
|
||||
var i = 0
|
||||
var x = 0
|
||||
for (i = 0; i < n; i++) {
|
||||
x += fan_in(100, 100)
|
||||
}
|
||||
return x
|
||||
},
|
||||
|
||||
// Pipeline: 10 stages, 1000 items
|
||||
pipeline_10x1k: function(n) {
|
||||
var i = 0
|
||||
var x = 0
|
||||
for (i = 0; i < n; i++) {
|
||||
x += pipeline(10, 1000)
|
||||
}
|
||||
return x
|
||||
},
|
||||
|
||||
// Request-response: 5K requests
|
||||
rpc_5k: function(n) {
|
||||
var i = 0
|
||||
var x = 0
|
||||
for (i = 0; i < n; i++) {
|
||||
x += request_response(5000)
|
||||
}
|
||||
return x
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user