Skip to content

Commit df96041

Browse files
author
Dmitrii Vasilev
committed
refactor(background_agent,hybrid): SPARC protocol implementation and refactoring (#503)
1 parent 202c501 commit df96041

File tree

16 files changed

+13293
-48
lines changed

16 files changed

+13293
-48
lines changed

.trinity/mu/heartbeat.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"agent":"mu","wake":139,"timestamp":1775206215,"errors_scanned":0,"fixes_applied":0,"build_ok":false,"test_ok":false}
1+
{"agent":"mu","wake":145,"timestamp":1775208352,"errors_scanned":0,"fixes_applied":0,"build_ok":false,"test_ok":false}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"title": "TEFB Multiple Choice",
3+
"id": "playra/trinity-cognitive-probes-tefb-mc",
4+
"licenses": [{"name": "CC0-1.0"}]
5+
}

kaggle/data/upload_tefb_mc/tefb_mc.csv

Lines changed: 11656 additions & 0 deletions
Large diffs are not rendered by default.

src/background_agent/db/client.zig

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ pub const PostgresClient = struct {
110110
_ = try stream.writeAll(startup_msg);
111111

112112
// Handle authentication
113-
try self.handleAuthentication(&stream);
113+
try handleAuthentication(&stream);
114114

115115
// Wait for ReadyForQuery
116116
try self.waitForReady(&stream);
@@ -156,7 +156,7 @@ pub const PostgresClient = struct {
156156
}
157157

158158
/// Handle authentication response from server
159-
fn handleAuthentication(self: *PostgresClient, stream: *net.Stream) !void {
159+
fn handleAuthentication(stream: *net.Stream) !void {
160160
var len_buf: [4]u8 = undefined;
161161
_ = try stream.readAll(&len_buf);
162162
const msg_len = std.mem.readInt(u32, &len_buf, .big);
@@ -281,7 +281,7 @@ pub const PostgresClient = struct {
281281
try row.values.append("");
282282
} else {
283283
const value_len_usize = @as(usize, @intCast(value_len));
284-
var value_buf = try self.allocator.alloc(u8, value_len_usize);
284+
const value_buf = try self.allocator.alloc(u8, value_len_usize);
285285
_ = try stream.readAll(value_buf);
286286
try row.values.append(value_buf);
287287
try row.columns.append(""); // Column name not in DataRow
@@ -294,7 +294,7 @@ pub const PostgresClient = struct {
294294
}
295295

296296
/// Read and parse error response
297-
fn readErrorResponse(self: *PostgresClient, stream: *net.Stream, len: u32) !void {
297+
fn readErrorResponse(stream: *net.Stream, len: u32) !void {
298298
var message: [256]u8 = undefined;
299299
var message_len: usize = 0;
300300

@@ -326,7 +326,7 @@ pub const PostgresClient = struct {
326326
}
327327

328328
/// Skip a message
329-
fn skipMessage(self: *PostgresClient, stream: *net.Stream, len: u32) !void {
329+
fn skipMessage(stream: *net.Stream, len: u32) !void {
330330
var buf: [1024]u8 = undefined;
331331
var remaining: u32 = len;
332332

@@ -415,29 +415,29 @@ pub fn buildStartupMessage(allocator: Allocator, user: []const u8, database: []c
415415
var offset: usize = 0;
416416

417417
// Message length (including self, excluding length field)
418-
std.mem.writeInt(u32, msg[offset..][0..4], @intCast(size - 4), .big);
418+
std.mem.writeInt(u32, msg[0..4], @intCast(size - 4), .big);
419419
offset += 4;
420420

421421
// Protocol version 3.0
422-
std.mem.writeInt(u32, msg[offset..][0..4], PROTOCOL_VERSION, .big);
422+
std.mem.writeInt(u32, msg[4..8], PROTOCOL_VERSION, .big);
423423
offset += 4;
424424

425425
// User parameter
426-
@memcpy(msg[offset..][0..5], "user");
426+
@memcpy(msg[offset..offset+5], "user");
427427
offset += 5;
428428
msg[offset] = 0;
429429
offset += 1;
430-
@memcpy(msg[offset..][0..user.len], user);
430+
@memcpy(msg[offset..offset+user.len], user);
431431
offset += user.len;
432432
msg[offset] = 0;
433433
offset += 1;
434434

435435
// Database parameter
436-
@memcpy(msg[offset..][0..9], "database");
436+
@memcpy(msg[offset..offset+9], "database");
437437
offset += 9;
438438
msg[offset] = 0;
439439
offset += 1;
440-
@memcpy(msg[offset..][0..database.len], database);
440+
@memcpy(msg[offset..offset+database.len], database);
441441
offset += database.len;
442442
msg[offset] = 0;
443443
offset += 1;
@@ -457,8 +457,8 @@ pub fn buildQueryMessage(allocator: Allocator, sql: []const u8) ![]u8 {
457457
errdefer allocator.free(msg);
458458

459459
msg[0] = @intFromEnum(MessageType.Query);
460-
std.mem.writeInt(u32, msg[1..][0..4], @intCast(sql.len + 1), .big);
461-
@memcpy(msg[5..][0..sql.len], sql);
460+
std.mem.writeInt(u32, msg[1..5], @intCast(sql.len + 1), .big);
461+
@memcpy(msg[5..5+sql.len], sql);
462462
msg[5 + sql.len] = 0;
463463

464464
return msg;
@@ -473,8 +473,8 @@ pub fn buildAuthenticationOk(allocator: Allocator) ![]u8 {
473473
errdefer allocator.free(msg);
474474

475475
msg[0] = @intFromEnum(MessageType.AuthenticationOk);
476-
std.mem.writeInt(u32, msg[1..][0..4], 4, .big); // length of auth_code
477-
std.mem.writeInt(u32, msg[5..][0..4], 0, .big); // AUTH_OK
476+
std.mem.writeInt(u32, msg[1..5], 4, .big); // length of auth_code
477+
std.mem.writeInt(u32, msg[5..9], 0, .big); // AUTH_OK
478478

479479
return msg;
480480
}
@@ -489,9 +489,9 @@ pub fn buildBackendKeyData(allocator: Allocator, pid: i32, key: i32) ![]u8 {
489489
errdefer allocator.free(msg);
490490

491491
msg[0] = @intFromEnum(MessageType.BackendKeyData);
492-
std.mem.writeInt(u32, msg[1..][0..4], 8, .big);
493-
std.mem.writeInt(i32, msg[5..][0..4], pid, .big);
494-
std.mem.writeInt(i32, msg[9..][0..4], key, .big);
492+
std.mem.writeInt(u32, msg[1..5], 8, .big);
493+
std.mem.writeInt(i32, msg[5..9], pid, .big);
494+
std.mem.writeInt(i32, msg[9..13], key, .big);
495495

496496
return msg;
497497
}
@@ -506,7 +506,7 @@ pub fn buildReadyForQuery(allocator: Allocator, status: TransactionStatus) ![]u8
506506
errdefer allocator.free(msg);
507507

508508
msg[0] = @intFromEnum(MessageType.ReadyForQuery);
509-
std.mem.writeInt(u32, msg[1..][0..4], 1, .big);
509+
std.mem.writeInt(u32, msg[1..5], 1, .big);
510510
msg[5] = @intFromEnum(status);
511511

512512
return msg;
@@ -522,8 +522,8 @@ pub fn buildCommandComplete(allocator: Allocator, tag: []const u8) ![]u8 {
522522
errdefer allocator.free(msg);
523523

524524
msg[0] = @intFromEnum(MessageType.CommandComplete);
525-
std.mem.writeInt(u32, msg[1..][0..4], @intCast(tag.len + 1), .big);
526-
@memcpy(msg[5..][0..tag.len], tag);
525+
std.mem.writeInt(u32, msg[1..5], @intCast(tag.len + 1), .big);
526+
@memcpy(msg[5..5+tag.len], tag);
527527
msg[5 + tag.len] = 0;
528528

529529
return msg;
@@ -540,9 +540,9 @@ pub fn buildErrorResponse(allocator: Allocator, message: []const u8) ![]u8 {
540540
errdefer allocator.free(msg);
541541

542542
msg[0] = @intFromEnum(MessageType.ErrorResponse);
543-
std.mem.writeInt(u32, msg[1..][0..4], @intCast(size - 5), .big);
543+
std.mem.writeInt(u32, msg[1..5], @intCast(size - 5), .big);
544544
msg[5] = 'M'; // Message field
545-
@memcpy(msg[6..][0..message.len], message);
545+
@memcpy(msg[6..6+message.len], message);
546546
msg[6 + message.len] = 0; // Null terminator for value
547547
msg[6 + message.len + 1] = 0; // Terminator
548548

src/background_agent/server.zig

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ pub const Server = struct {
8787
self.handleConnection(connection) catch |err| {
8888
std.log.err("Connection error: {}", .{err});
8989
};
90+
}
9091
}
9192

9293
/// Stop server
@@ -149,8 +150,8 @@ pub const Server = struct {
149150
var body_len: usize = 0;
150151
var body_start: usize = request.len;
151152

152-
for (lines) |line, i| {
153-
const offset = if (i == 0) 0 else @intCast(usize, std.mem.indexOfPos(u8, request_str, line, @intCast(i32, @intFrom usize, lines.len - 1))) + line.len;
153+
for (lines, 0..) |line, i| {
154+
const offset = if (i == 0) 0 else @intCast(usize, std.mem.indexOfPos(u8, request_str, line, @intCast(i32, lines.len - 1))) + line.len;
154155
if (offset + 2 < request.len and
155156
request[offset + 1] == '\r' and request[offset + 2] == '\n')
156157
{

src/hybrid.zig

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -238,13 +238,14 @@ pub const HybridBigInt = struct {
238238

239239
self.ensureUnpacked();
240240

241+
const cache = self.unpacked_cache orelse return;
241242
const num_packs = (self.trit_len + TRITS_PER_BYTE - 1) / TRITS_PER_BYTE;
242243
for (0..num_packs) |pack_idx| {
243244
const base = pack_idx * TRITS_PER_BYTE;
244245
var trits: [5]Trit = .{ 0, 0, 0, 0, 0 };
245246
for (0..TRITS_PER_BYTE) |j| {
246247
if (base + j < self.trit_len) {
247-
trits[j] = self.unpacked_cache[base + j];
248+
trits[j] = cache[base + j];
248249
}
249250
}
250251
self.packed_data[pack_idx] = tvc_packed.encodePack(trits);
@@ -372,7 +373,7 @@ pub const HybridBigInt = struct {
372373
inline for (0..SIMD_WIDTH) |i| {
373374
const idx = base + i;
374375
a_vec[i] = if (idx < a.trit_len) a.getTritChecked(idx) else 0;
375-
b_vec[i] = if (idx < b.trit_len) .getTritChecked(idx) else 0;
376+
b_vec[i] = if (idx < b.trit_len) b.getTritChecked(idx) else 0;
376377
}
377378

378379
const simd_result = simdAddTrits(a_vec, b_vec);
@@ -452,7 +453,7 @@ pub const HybridBigInt = struct {
452453
for (0..b.trit_len) |j| {
453454
if (i + j >= MAX_TRITS) break;
454455

455-
var prod: i16 = @as(i16, a_trit) * @as(i16, .getTritChecked(j));
456+
var prod: i16 = @as(i16, a_trit) * @as(i16, b.getTritChecked(j));
456457
prod += result.unpacked_cache[i + j];
457458
prod += carry;
458459
carry = 0;
@@ -581,28 +582,28 @@ test "HybridBigInt fromI64 and toI64" {
581582
const cases = [_]i64{ 0, 1, -1, 10, -10, 100, -100, 12345, -12345 };
582583
for (cases) |val| {
583584
var hybrid = HybridBigInt.fromI64(val);
584-
const back = hybrid.toI64();
585+
const back = hybrid.toI64(std.testing.allocator);
585586
try std.testing.expectEqual(val, back);
586587
}
587588
}
588589

589590
test "HybridBigInt addition" {
590591
var a = HybridBigInt.fromI64(123);
591592
var b = HybridBigInt.fromI64(456);
592-
var sum = a.add(&b);
593-
try std.testing.expectEqual(@as(i64, 579), sum.toI64());
593+
var sum = a.add(&b, std.testing.allocator);
594+
try std.testing.expectEqual(@as(i64, 579), sum.toI64(std.testing.allocator));
594595
}
595596

596597
test "HybridBigInt multiplication" {
597598
var a = HybridBigInt.fromI64(12);
598599
var b = HybridBigInt.fromI64(34);
599-
var prod = a.mul(&b);
600-
try std.testing.expectEqual(@as(i64, 408), prod.toI64());
600+
var prod = a.mul(&b, std.testing.allocator);
601+
try std.testing.expectEqual(@as(i64, 408), prod.toI64(std.testing.allocator));
601602
}
602603

603604
test "HybridBigInt pack/unpack roundtrip" {
604605
var hybrid = HybridBigInt.fromI64(12345);
605-
const val1 = hybrid.toI64();
606+
const val1 = hybrid.toI64(std.testing.allocator);
606607

607608
// Force pack
608609
hybrid.pack();
@@ -612,7 +613,7 @@ test "HybridBigInt pack/unpack roundtrip" {
612613
_ = hybrid.getTrit(0);
613614
try std.testing.expectEqual(StorageMode.unpacked_mode, hybrid.mode);
614615

615-
const val2 = hybrid.toI64();
616+
const val2 = hybrid.toI64(std.testing.allocator);
616617
try std.testing.expectEqual(val1, val2);
617618
}
618619

@@ -627,13 +628,13 @@ test "HybridBigInt memory efficiency" {
627628
test "HybridBigInt conversion from BigInt" {
628629
const val: i64 = 12345;
629630
const big = tvc_bigint.TVCBigInt.fromI64(val);
630-
var hybrid = HybridBigInt.fromBigInt(&big);
631-
try std.testing.expectEqual(val, hybrid.toI64());
631+
var hybrid = HybridBigInt.fromBigInt(&big, std.testing.allocator);
632+
try std.testing.expectEqual(val, hybrid.toI64(std.testing.allocator));
632633
}
633634

634635
test "HybridBigInt conversion to BigInt" {
635636
var hybrid = HybridBigInt.fromI64(12345);
636-
const big = hybrid.toBigInt();
637+
const big = hybrid.toBigInt(std.testing.allocator);
637638
try std.testing.expectEqual(@as(i64, 12345), big.toI64());
638639
}
639640

@@ -650,18 +651,18 @@ test "SIMD addSimd correctness" {
650651
var a = HybridBigInt.fromI64(pair[0]);
651652
var b = HybridBigInt.fromI64(pair[1]);
652653

653-
var sum_scalar = a.add(&b);
654-
var sum_simd = a.addSimd(&b);
654+
var sum_scalar = a.add(&b, std.testing.allocator);
655+
var sum_simd = a.addSimd(&b, std.testing.allocator);
655656

656-
try std.testing.expectEqual(sum_scalar.toI64(), sum_simd.toI64());
657+
try std.testing.expectEqual(sum_scalar.toI64(std.testing.allocator), sum_simd.toI64(std.testing.allocator));
657658
}
658659
}
659660

660661
test "SIMD dotProduct" {
661662
var a = HybridBigInt.fromI64(12345);
662663
var b = HybridBigInt.fromI64(12345);
663664

664-
const dot = a.dotProduct(&b);
665+
const dot = a.dotProduct(&b, std.testing.allocator);
665666
// dot product of identical vectors = sum of squares of trits
666667
// For balanced ternary, each trit is -1, 0, or 1, so trit^2 = 0 or 1
667668
try std.testing.expect(dot > 0);
@@ -744,7 +745,7 @@ pub fn runBenchmarks() void {
744745
var hybrid_result = HybridBigInt.zero();
745746
i = 0;
746747
while (i < iterations) : (i += 1) {
747-
hybrid_result = hybrid_a.add(&hybrid_b);
748+
hybrid_result = hybrid_a.add(&hybrid_b, std.heap.page_allocator);
748749
}
749750
const hybrid_end = std.time.nanoTimestamp();
750751
std.mem.doNotOptimizeAway(hybrid_result);
@@ -770,7 +771,7 @@ pub fn runBenchmarks() void {
770771
var simd_result = HybridBigInt.zero();
771772
i = 0;
772773
while (i < iterations) : (i += 1) {
773-
simd_result = hybrid_a.addSimd(&hybrid_b);
774+
simd_result = hybrid_a.addSimd(&hybrid_b, std.heap.page_allocator);
774775
}
775776
const simd_end = std.time.nanoTimestamp();
776777
std.mem.doNotOptimizeAway(simd_result);
@@ -790,7 +791,7 @@ pub fn runBenchmarks() void {
790791
var dot_result: i32 = 0;
791792
i = 0;
792793
while (i < iterations) : (i += 1) {
793-
dot_result = hybrid_a.dotProduct(&hybrid_b);
794+
dot_result = hybrid_a.dotProduct(&hybrid_b, std.heap.page_allocator);
794795
}
795796
const dot_end = std.time.nanoTimestamp();
796797
std.mem.doNotOptimizeAway(dot_result);
@@ -800,8 +801,8 @@ pub fn runBenchmarks() void {
800801

801802
std.debug.print("\nResults match:\n", .{});
802803
std.debug.print(" Unpacked == Packed: {}\n", .{unpacked_result.toI64() == packed_result.toI64()});
803-
std.debug.print(" Unpacked == Hybrid: {}\n", .{unpacked_result.toI64() == hybrid_result.toI64()});
804-
std.debug.print(" Hybrid == SIMD: {}\n", .{hybrid_result.toI64() == simd_result.toI64()});
804+
std.debug.print(" Unpacked == Hybrid: {}\n", .{unpacked_result.toI64() == hybrid_result.toI64(std.heap.page_allocator)});
805+
std.debug.print(" Hybrid == SIMD: {}\n", .{hybrid_result.toI64(std.heap.page_allocator) == simd_result.toI64(std.heap.page_allocator)});
805806
}
806807

807808
pub fn main() !void {

0 commit comments

Comments
 (0)