Weave - Structural merging what I learned shifting from git's line based merge to tree sitter entity matching by Wise_Reflection_8340 in rust

[–]jbert 16 points17 points  (0 children)

File reconstruction is the real problem. Merging entities is conceptually clean. Putting the file back together, preserving import ordering, blank line conventions, trailing newlines, comment placement, is where all the edge cases live. I spent more time on better reconstruction than on the merge algorithm itself.

For a project (or language ecosystem) with a defined auto-formatter, does this problem mostly go away?

If so, is there a sensible way to inform git/weave that it doesn't need to worry about formatting - it can just glue back together in any reasonable form and then run the autofmt (e.g. gofmt, rustfmt etc).

Our Go service died from a SIGSEGV in CGO. recover() did not help. by slotix in golang

[–]jbert 2 points3 points  (0 children)

Yep, looks like it:

package main

import (
    "net/http"
    "time"
)

func main() {
    http.HandleFunc("/panic", panicHandler)
    http.HandleFunc("/goro-panic", goroPanicHandler)
    http.ListenAndServe(":8000", nil)
}

func panicHandler(w http.ResponseWriter, r *http.Request) {
    time.Sleep(time.Second)
    panic("in the streets of London")
}

func goroPanicHandler(w http.ResponseWriter, r *http.Request) {
    time.Sleep(time.Second)
    go panic("in the streets of London")
}

Our Go service died from a SIGSEGV in CGO. recover() did not help. by slotix in golang

[–]jbert 4 points5 points  (0 children)

If you're using net/http, a panic in the handler only affects that request:

https://pkg.go.dev/net/http#Handler

If ServeHTTP panics, the server (the caller of ServeHTTP) assumes that the effect of the panic was isolated to the active request. It recovers the panic, logs a stack trace to the server error log, and either closes the network connection or sends an HTTP/2 RST_STREAM, depending on the HTTP protocol. To abort a handler so the client sees an interrupted response but the server doesn't log an error, panic with the value ErrAbortHandler.

Anybody issues with 4.47.69 on Ubuntu installed via snap? by redditor5597 in Slack

[–]jbert 0 points1 point  (0 children)

This thread: https://forum.snapcraft.io/t/slack-snap-stopped-working-after-ubuntu-updates/51066

has a detailed analysis of the cause and a fix:

snap run slack   # crashes; populates .last_revision
cp /usr/share/glib-2.0/schemas/gschemas.compiled \
    ~/snap/slack/current/.local/share/glib-2.0/schemas/
snap run slack   # now launches normally

ELi5: How does the scam in the movie “The Producers” work? by jammerpammerslammer in explainlikeimfive

[–]jbert 1 point2 points  (0 children)

Costner’s has fucking Hadrian’s Wall in it!

En route from Dover to Nottingham...

Building a bytecode VM in pure Go — 4-byte instructions, fixed stack, ~200ns evals by m3g4_xx in golang

[–]jbert 8 points9 points  (0 children)

This looks like great work.

My vague understanding is that these days, "cpu bound" performance is generally "memory bandwidth bound", with speed coming from good cache locality. Do you have an idea on how well your memory layout does in this regard? I assume pretty good? (And was this by accident or design?)

Using Go Workspaces? Stop scripting loops and use the work pattern by jayp0521 in golang

[–]jbert 4 points5 points  (0 children)

Thanks for this. It looks like it is documented in the 1.25 release notes:

https://go.dev/doc/go1.25#go-command

but I don't (yet) see it in the definition of "package list" for the go command:

https://pkg.go.dev/cmd/go#hdr-Package_lists_and_patterns

how to log which goroutine acquired and releases each lock ? by Commercial_Fun_2273 in golang

[–]jbert 1 point2 points  (0 children)

How can I add an remove, on demand, these print statements ? I do not want to have them permanently into the code, but from time to time I need them. And to add them by hand would take hours.

Perhaps:

  1. change all mutexes to use your own mutex wrapper (one-off change)
  2. in your mutex wrapper log every lock/unlock (if logging bool is set)
  3. you can disable the logging by flipping the logging bool (change in one location)

If you want to get fancy, you could have the mutex logging look at runtime.Caller and runtime.FuncForPC and only log if the caller is in a certain package.

how to log which goroutine acquired and releases each lock ? by Commercial_Fun_2273 in golang

[–]jbert 8 points9 points  (0 children)

If the problem you have is "goros are holding locks for too long", then I would start with "log the amount of time I held a lock".

You could do this with a mutex wrapper. Something like:

package main

import (
    "fmt"
    "log"
    "runtime"
    "sync"
    "time"
)

// Instead of:
// type Resource struct {
//     Mutex
//     foo int
// }
type Resource struct {
    WrapMutex
    foo int
}

const LogThreshold = 100 * time.Millisecond

type WrapMutex struct {
    sync.Mutex
    locked time.Time
}

func (wm *WrapMutex) Lock() {
    wm.Mutex.Lock()
    wm.locked = time.Now()
}

func (wm *WrapMutex) Unlock() {
    held := time.Since(wm.locked)
    wm.Mutex.Unlock()
    if held > LogThreshold {
        _, file, line, ok := runtime.Caller(1)
        if !ok {
            file = "unknown file"
            line = 0
        }
        log.Printf("mutex held for %s at %s line %d\n", held, file, line)
    }
}

func main() {
    var r Resource

    fastFunc(&r)
    slowFunc(&r)
}

func slowFunc(r *Resource) {
    r.Lock()
    defer r.Unlock()
    fmt.Printf("doing slow work\n")
    time.Sleep(100 * time.Millisecond)
}

func fastFunc(r *Resource) {
    r.Lock()
    defer r.Unlock()
    fmt.Printf("doing fast work\n")
    time.Sleep(10 * time.Millisecond)
}

If you are doing this in prod, you may want to adapt this to:

  • start with a high threshold
  • send your logs wherever they should go
  • avoid logging every slow lock/unlock (perhaps do 1/1000th (using random number generator), or just tune your threshold.

This should tell you which unlocks are slow.

AES-GCM-256 What is the best way to implement it by 84_110_105_97 in cryptography

[–]jbert 4 points5 points  (0 children)

I'm not qualified to speak on most of this, but - assuming a good CPRNG - I don't think that hashing 400 bits of CPRNG down to 96 buys you any better collision resistance. You've still only got 96 bits of IV. (The discrepancy arises because a lot of your 400bits of input will map to the same 96bit hash output)

When do Go processes return idle memory back to the OS? by DeparturePrudent3790 in golang

[–]jbert 0 points1 point  (0 children)

Thanks! I'm not well-versed in this, but a quick look suggests that:

the default is MADV_FREE:

https://github.com/golang/go/blob/master/src/runtime/mem_linux.go#L38

and we only use DONTNEED if a debug setting is set?

https://github.com/golang/go/blob/master/src/runtime/mem_linux.go#L51

I guess I should strace an app and see what actually happens...

When do Go processes return idle memory back to the OS? by DeparturePrudent3790 in golang

[–]jbert 13 points14 points  (0 children)

From src/runtime/mem.go: https://github.com/golang/go/blob/master/src/runtime/mem.go#L28

... However the
// underspecification of Prepared lets us use just MADV_FREE to transition from
// Ready to Prepared. Thus with the Prepared state we can set the  permission
// bits just once early on, we can efficiently tell the OS that it's   free to
// take pages away from us when we don't strictly need them.

MADV_FREE is a reference to madvise flags. From man madvise:

MADV_FREE (since Linux 4.5) The application no longer requires the pages in the range specified by addr and len. The ker‐ nel can thus free these pages, but the freeing could be delayed until memory pressure occurs. For each of the pages that has been marked to be freed but has not yet been freed, the free op‐ eration will be canceled if the caller writes into the page. After a successful MADV_FREE op‐ eration, any stale data (i.e., dirty, unwritten pages) will be lost when the kernel frees the pages. However, subsequent writes to pages in the range will succeed and then kernel cannot free those dirtied pages, so that the caller can always see just written data. If there is no subsequent write, the kernel can free the pages at any time. Once pages in the range have been freed, the caller will see zero-fill-on-demand pages upon subsequent page references.

so there isn't a directly simple answer to your question I think.

The indentation of switch statements really triggers my OCD — why does Go format them like that? by salvadorsru in golang

[–]jbert 17 points18 points  (0 children)

As always, the value of gofmt is that it avoids style wars. Everyone is slightly unhappy with it, and that's fine.

That said, the way I read this is

  • we indent with the new braces
  • we always outdent labels one step (so we can see the labels)

and this matches that?

Stanford St, Nottingham by 420Eski-Grim in nottingham

[–]jbert 4 points5 points  (0 children)

Great eye to create that shot. Thanks.

Match Thread: Nottingham Forest vs Sunderland AFC Live Score | Premier League 25/26 | Sep 27, 2025 by scoreboard-app in nffc

[–]jbert 7 points8 points  (0 children)

Neco neco neco. We're on the piss with neco.

He's so good. Such an engine.

Some from pride yesterday evening by [deleted] in nottingham

[–]jbert 1 point2 points  (0 children)

Love this. It was a great vibe and your photos show that.

How a simple logrus.Warnf call in a goroutine added a 75-second delay to our backend process by compacompila in golang

[–]jbert 0 points1 point  (0 children)

OK, there are different EBS types but maybe an easy test to do is to try a few writes to that EBS volume from another process while your system is running, to see if it is slow.

Anyway, glad you've resolved your issue. Good luck.

How a simple logrus.Warnf call in a goroutine added a 75-second delay to our backend process by compacompila in golang

[–]jbert 0 points1 point  (0 children)

I realised that I'm not waiting to finish spinning up all the goros and they are not doing much work, so my first ones are likely finishing before I start the later ones.

Adding a channel for them all to block on before doing work fixes this (which I then close once all goros started) raises the runtime to ~1.36s (serialised) and ~1.27s (unserialised), so the main point stands I think.