Live data from Hacker News

Memory – Part 4: Intersec’s custom allocators

techtalk.intersec.com

41–50 of 62 posts

Re: Memory – Part 4: Intersec’s custom allocators

#41

Not about heap allocators but I followed the "About" link to this text: > At Intersec, technology matters…Because it’s the core of our business, we aim to provide our clients with the most innovative and disruptive technological solutions. We do not believe in the benefits of reusing and staking external software bricks when developing our products. Our software is built in C language under Linux, with PHP/JavaScript…

I think the really hard stuff isn't done via PHP. Seems to me they use PHP as the front end because they want to focus on their really valuable technology - their C code.

Re: Memory – Part 4: Intersec’s custom allocators

#42
post #29
post #27

Earlier quoted context omitted.

Contra "exDM69", there's nothing unreasonable or "unrealistic" about allocating 8 bytes at a time; it's in fact extremely convenient to be able to do that. I think it's telling that someone would call that workload unrealistic; it indicates to me that they've never even really considered alternatives to malloc. It's a little like those C programmers who try to use 256 byte static arrays for all their strings because…

Well, personally, if I'm using C, it's typically for a very narrowly defined, performance-sensitive problem. Both times I've done this in the last couple years, I found myself doing a couple big mallocs at the start and then running some tight loops over that memory with no further mallocs -- for use cases with more allocation, I'll just use whatever other language is more convenient, preferably one with a GC. But if…

That's essentially what I do in much of my C code: implement pool allocators. And that's essentially what the post we're commenting on is talking about.

Incidentally, good common case for 8-byte allocations that is actually common in real-world C code: 32 bit linked list nodes (4 bytes nextptr, 4 bytes dataptr).

Re: Memory – Part 4: Intersec’s custom allocators

#43
post #32

Earlier quoted context omitted.

Then "they" later discovered the name was no longer apt and it should have been called ++C.

C++ is the correct name, you write a few thousand lines C code and then write class LargeObject in the first line. So C++.

I'm concerned that would create a temporary variable, I'll try and decipher the ISO spec to verify. Is LargeObject POD?

Re: Memory – Part 4: Intersec’s custom allocators

#44
Sorry to nitpick, but I believe the time difference code has an error of 1 millisecond 25% of the time:

    int64_t delta = tv2->tv_sec - tv1->tv_sec;
    return delta * 1000 + (tv2->tv_usec - tv1->tv_usec) / 1000;
One way to fix it is:

    int64_t deltasec = tv2->tv_sec - tv1->tv_sec - 1;
    int64_t deltausec = tv2->tv_usec - tv1->tv_usec + 1000000;
    return deltasec * 1000 + deltausec / 1000;

Re: Memory – Part 4: Intersec’s custom allocators

#46

Not about heap allocators but I followed the "About" link to this text: > At Intersec, technology matters…Because it’s the core of our business, we aim to provide our clients with the most innovative and disruptive technological solutions. We do not believe in the benefits of reusing and staking external software bricks when developing our products. Our software is built in C language under Linux, with PHP/JavaScript…

I think the really hard stuff isn't done via PHP. Seems to me they use PHP as the front end because they want to focus on their really valuable technology - their C code.

PHP is used as a small layer that enables talking to our C code from javascript. We have a custom (Protocol Buffer-like) protocol to manage our RPC, the PHP embeds a native module that implements that protocol and exposes a webservice to which our Javascript code can talk in order to provide some valuable user-experience on top of our C-written technologies.

Nowadays there is so little intelligence in the PHP that we only consider it as a pass-through layer.

Re: Memory – Part 4: Intersec’s custom allocators

#48
post #44

Sorry to nitpick, but I believe the time difference code has an error of 1 millisecond 25% of the time: int64_t delta = tv2->tv_sec - tv1->tv_sec; return delta * 1000 + (tv2->tv_usec - tv1->tv_usec) / 1000; One way to fix it is: int64_t deltasec = tv2->tv_sec - tv1->tv_sec - 1; int64_t deltausec = tv2->tv_usec - tv1->tv_usec + 1000000; return deltasec * 1000 + deltausec / 1000;

The diff is a truncation. The actual error rate is 0.5ms on average. By using a round instead of truncation, we can reduce the error to 0.25ms on average.

Re: Memory – Part 4: Intersec’s custom allocators

#49
post #48
post #44

Sorry to nitpick, but I believe the time difference code has an error of 1 millisecond 25% of the time: int64_t delta = tv2->tv_sec - tv1->tv_sec; return delta * 1000 + (tv2->tv_usec - tv1->tv_usec) / 1000; One way to fix it is: int64_t deltasec = tv2->tv_sec - tv1->tv_sec - 1; int64_t deltausec = tv2->tv_usec - tv1->tv_usec + 1000000; return deltasec * 1000 + deltausec / 1000;

The diff is a truncation. The actual error rate is 0.5ms on average. By using a round instead of truncation, we can reduce the error to 0.25ms on average.

Well, that much is obvious. But if you are going to truncate, you should be consistent. Always truncate towards 0, not sometimes towards 0 and sometimes towards infinity.

Re: Memory – Part 4: Intersec’s custom allocators

#50
post #35

Earlier quoted context omitted.

C++ has an IMHO worse version of this feature, that requires a custom type, and that only allows a single function to be called for that type. This is more like Go's defer, and is far more appropriate for my use cases.

I haven't written much C++ in quite a few years - mostly do Ruby these days, so I'm sure I'm making some terribly embarrassing faux pas or other with the example below. But you don't need more than the C++ functionality to compose your own variations if you want more flexibility. For example: #include #include class Scope { private: typedef std::vector FV; FV fv; public: void on_return(void (* f)()) { fv.push_back(f)…

Better would be to just have the Scope class take a single function to run and establish multiple stack entries for them. This would be my version:

  #include 

  template 
  class ScopeFunc {
  private:
    tFunc mFunc;

  public:
    ScopeFunc(tFunc func) : mFunc(func) {}

    ~ScopeFunc() {
      mFunc();
    }
  };

  template 
  ScopeFunc on_return(tFunc func)
  {
    return ScopeFunc(func);
  }

  int main() {
    auto first = on_return([]() { std::puts("first"); });
    auto second = on_return([]() { std::puts("second"); });

    std::puts("Hello");
  }
Note that this is C++11, using lambdas. Also that the output will be reversed from your expectation since it's a lifo, but that's probably actually what you want for real deferred behaviour and not text output.

It also optimizes nicely, which yours may not because the loop unrolling may be complicated and there's a higher chance of aliasing of the function pointers in the vector:

  0000000000400600 :
    400600:	53                   	push   %rbx
    400601:	bf e4 07 40 00       	mov    $0x4007e4,%edi
    400606:	e8 b5 ff ff ff       	callq  4005c0 
    40060b:	bf ea 07 40 00       	mov    $0x4007ea,%edi
    400610:	e8 ab ff ff ff       	callq  4005c0 
    400615:	bf f1 07 40 00       	mov    $0x4007f1,%edi
    40061a:	e8 a1 ff ff ff       	callq  4005c0 
    40061f:	31 c0                	xor    %eax,%eax
    400621:	5b                   	pop    %rbx
    400622:	c3                   	retq
Post reply on HN