diff options
| author | Polesznyák Márk <contact@pml68.dev> | 2026-04-08 15:12:45 +0200 |
|---|---|---|
| committer | Polesznyák Márk <contact@pml68.dev> | 2026-04-08 15:12:45 +0200 |
| commit | 40f0c5a4559f0d837d4738ff483736f1fad2865f (patch) | |
| tree | a928f9dd891a88430cd816bf64251c4bbb94f21a | |
| parent | feat: initial commit (diff) | |
| download | hare-1brc-40f0c5a4559f0d837d4738ff483736f1fad2865f.tar.gz | |
feat: Hare updates (rt -> sys), fix sorting and parsing
| -rw-r--r-- | hashmap.ha | 25 | ||||
| -rw-r--r-- | main.ha | 48 |
2 files changed, 44 insertions, 29 deletions
@@ -1,15 +1,28 @@ -use hash::fnv; - def BUCKETS: size = 1 << 17; -type hashmap = [BUCKETS](str, data); +type hashmap = [BUCKETS][](size, data); fn getitem(map: *hashmap, hash: size) data = { let bucket = &map[hash & (BUCKETS - 1)]; - return bucket.1; + for (let i = 0z; i < len(bucket); i += 1) { + if (bucket[i].0 == hash) + return bucket[i].1; + }; + return data { ... }; }; -fn setitem(map: *hashmap, hash: size, key: str, value: data) void = { +fn setitem(map: *hashmap, hash: size, value: data) void = { let bucket = &map[hash & (BUCKETS - 1)]; - *bucket = (key, value); + for (let i = 0z; i < len(bucket); i += 1) { + if (bucket[i].0 == hash) { + bucket[i].1 = value; + return; + }; + }; + append(bucket, (hash, value))!; +}; + +fn finish(map: *hashmap) void = { + for (let i = 0z; i < len(map); i += 1) + free(map[i]); }; @@ -5,10 +5,10 @@ use hash; use hash::fnv; use io; use os; -use rt; +use sys; use sort; use sort::cmp; -use strings::{fromutf8_unsafe, split, toutf8}; +use strings; use types; type data = struct { @@ -44,23 +44,23 @@ fn i64parse(bytes: []u8) (i64, size) = { }; @test fn parsei64() void = { - assert(i64parse(toutf8("0.0")).0 == 0); - assert(i64parse(toutf8("9.2")).0 == 92); - assert(i64parse(toutf8("-9.2")).0 == -92); - assert(i64parse(toutf8("98.2")).0 == 982); - assert(i64parse(toutf8("-98.2")).0 == -982); + assert(i64parse(strings::toutf8("0.0")).0 == 0); + assert(i64parse(strings::toutf8("9.2")).0 == 92); + assert(i64parse(strings::toutf8("-9.2")).0 == -92); + assert(i64parse(strings::toutf8("98.2")).0 == 982); + assert(i64parse(strings::toutf8("-98.2")).0 == -982); }; fn mmap(fd: io::file) []u8 = { - let sb = rt::st { ... }; - rt::fstat(fd, &sb)!; + let sb = sys::st { ... }; + sys::fstat(fd, &sb)!; - let ptr = rt::mmap(null, sb.sz, rt::PROT_READ, rt::MAP_PRIVATE, fd, 0)!; + let ptr = sys::mmap(null, sb.sz, sys::PROT_READ, sys::MAP_PRIVATE, fd, 0)!; // Hardcoded value for MADV_SEQUENTIAL, from libc-rs it seems like it's // 2 on all currently supported platforms (Linux, FreeBSD, NetBSD, // OpenBSD, Dragonfly). - assert(rt::syscall(rt::SYS_madvise, ptr: uintptr: u64, sb.sz: u64, 2) == 0); + assert(sys::syscall(sys::SYS_madvise, ptr: uintptr: u64, sb.sz: u64, 2) == 0); return *(&types::slice { data = ptr, @@ -71,7 +71,7 @@ fn mmap(fd: io::file) []u8 = { fn free_mmap(map: []u8) void = { let map = &map: *types::slice; - rt::munmap(map.data: *opaque, map.length)!; + sys::munmap(map.data: *opaque, map.length)!; }; fn names_cmp(a: *opaque, b: *opaque) int = { @@ -82,7 +82,8 @@ fn names_cmp(a: *opaque, b: *opaque) int = { }; export fn main() void = { - let map: hashmap = [("", data { ... })...]; + let map: hashmap = [[]...]; + defer finish(&map); if (len(os::args) != 2) fmt::fatalf("usage: {} <file>", os::args[0]); @@ -93,6 +94,7 @@ export fn main() void = { free_mmap(fmap); let buf: *[1024 * 1024]u8 = alloc([0...])!; + defer free(buf); let read_start = 0z; let names_buf: *[10000](u64, str) = alloc([(0, "")...])!; @@ -111,7 +113,7 @@ export fn main() void = { let chunk = buf[..read_start + n]; - let newline = match(bytes::index(chunk, '\n': u8)) { + let newline = match(bytes::rindex(chunk, '\n': u8)) { case let idx: size => yield idx; case void => @@ -141,7 +143,7 @@ export fn main() void = { hash::reset(&fnv); let after = chunk[sep_idx + 1..]; - const name = fromutf8_unsafe(chunk[..sep_idx]); + const name = strings::fromutf8_unsafe(chunk[..sep_idx]); const (temp, index) = i64parse(after); chunk = after[index..]; @@ -149,7 +151,7 @@ export fn main() void = { let item = getitem(&map, hash); if (item.count == 0) { - static append(names, (hash, name))!; + static append(names, (hash, strings::dup(name)!))!; item.min = temp; item.max = temp; } else { @@ -162,7 +164,7 @@ export fn main() void = { item.sum += temp; item.count += 1; - setitem(&map, hash, name, item); + setitem(&map, hash, item); }; read_start = len(remaining); @@ -173,12 +175,8 @@ export fn main() void = { fmt::print("{")!; for (let i = 0z; i < len(names); i += 1) { - let (station, item) = map[names[i].0: size & (BUCKETS - 1)]; - - if (station == "") { - i -= 1; - continue; - }; + let station = names[i].1; + let item = getitem(&map, names[i].0); if (i > 0) fmt::print(", ")!; @@ -189,6 +187,10 @@ export fn main() void = { item.max: f64 / 10.0, item.sum: f64 / 10.0 / item.count: f64, )!; + + free(names[i].1); }; fmt::println("}")!; + + free(names); }; |
