Hacker Newsnew | past | comments | ask | show | jobs | submit | NewJazz's commentslogin

There are probably still ways to maintain a source archive with a ports system. Just analyze the sources used by builds, create a mirror, and redirect fetches to use the mirror. It's not that crazy. The packaging would still be a separate affair.

This is exactly what Nix does, if I understand correctly: the "mirror" is cache.nixos.org as mentioned in XorNot's reply to the same parent post.

I'm about 80% certain that cache.nixos.org caches the results of the builds, not the input sources.

I think it does both, at least for some sources. After all, sources are derivations too.

This is correct; in Nix lingo these are referred to as "fixed output derivations". For some other interesting context, see this Nix forum post from last year in which they discussed deleting some stuff from cache.nixos.org to save money, but were clear that they'd keep all fixed output derivations and only delete other things that aren't derivable from those: https://discourse.nixos.org/t/upcoming-garbage-collection-fo...

A third of my bill is the "base services" charge.

I'm not 100% but I think you may have confused watts and watt hours somewhere in there. Wouldn't it be X kWh/ton?

Yeah, I think you're right. Maff still maffs though. Units work out to MWh/h.. which makes sense to me

Trouble is... You can do it to a few minorities and get away with it. When you act like an asshole to the entire world, well suddenly assholes as big as you are in the minority... Oops.

You can have 0 parameters and the template is a string...

The point of my message is that you should avoid the `log(string)` signature. Even if it's appealing, it's an easy perf trap.

There are many ideas if you look at SQL libs. In my example I used a different type but there other solutions. Be creative.

    logger.log(new Template("foo"))`
    logger.log("foo", [])
    logger.prepare("foo").log()

And none of those solve the issue.

You pass "foo" to Template. The Template will be instantiated before log ever sees it. You conveniently left out where the Foo string is computed from something that actually need computation.

Like both:

    new Template("doing X to " + thingBeingOperatedOn)

    new Template("doing " + expensiveDebugThing(thingBeingOperatedOn))
You just complicated everything to get the same class of error.

Heck even the existing good way of doing it, which is less complicated than your way, still isn't safe from it.

    logger("doing {}", expensiveDebugThing(thingBeingOperatedOn))
All your examples have the same issue, both with just string concatenation and more expensive calls. You can only get around an unknowing or lazy programmer if the compiler can be smart enough to entirely skip these (JIT or not - a JIT would need to see that these calls never amount to anything and decide to skip them after a while. Not deterministically useful of course).

Yeah, it's hard to prevent a sufficiently motivated dev from shooting itself in the foot; but these still help.

> You conveniently left out where the Foo string is computed from something that actually need computation.

I left it out because the comment I was replying to was pointing that some logs don't have params.

For the approach using a `Template` class, the expectation would be that the doc would call out why this class exists in the first place as to enable lazy computation. Doing string concatenation inside a template constructor should raise a few eyebrows when writing or reviewing code.

I wrote `logger.log(new Template("foo"))` in my previous comment for brevity as it's merely an internet comment and not a real framework. In real code I would not even use stringy logs but structured data attached to a unique code. But since this thread discusses performance of stringy logs, I would expect log templates to be defined as statics/constants that don't contain any runtime value. You could also integrate them with metadata such as log levels, schemas, translations, codes, etc.

Regarding args themselves, you're right that they can also be expensive to compute in the first place. You may then design the args to be passed by a callback which would allow to defer the param computation.

A possible example would be:

    const OPERATION_TIMEOUT = new Template("the operation $operationId timed-out after $duration seconds", {level: "error", code: "E_TIMEOUT"});
    // ...
    function handler(...) {
      // ..
      logger.emit(OPERATION_TIMEOUT, () => ({operationId: "foo", duration: someExpensiveOperationToRetrieveTheDuration()}))
    }
This is still not perfect as you may need to compute some data before the log "just in case" you need it for the log. For example you may want to record the current time, do the operation. If the operation times out, you use the time recorded before the op to compute for how long it ran. If you did not time out and don't log, then getting the current system time is "wasted".

All I'm saying is that `logger.log(str)` is not the only possible API; and that splitting the definition of the log from the actual "emit" is a good pattern.


Unless log() is a macro of some sort that expands to if(logEnabled){internalLog(string)} - which a good optimizer will see through and not expand the string when logging is disabled.

Legalization does not signify usage.

Yeah our cloud DBs all have abysmal performance and high recurring cost even compared to metal we didn't even buy for hosting DBs.

Yeah corner and comer is an edit distance of 2 but perhaps more lucrative than corner and corker, as a bad example.

I saw rnicrosoft in use the other day, somewhere.

I'm not sure a junior would immediately understand the risks of what you described. Even if they did well in dist sys 101 last year.

Have you considered other options like woodpecker for example?

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: