# I'm trying to write something with the best possible performance (for a library). I keep wishing I was writing C! is that normal? Should I just write C?

**URL:** https://discourse.julialang.org/t/im-trying-to-write-something-with-the-best-possible-performance-for-a-library-i-keep-wishing-i-was-writing-c-is-that-normal-should-i-just-write-c/19286
**Category:** New to Julia
**Created:** [January 4, 2019, 9:09pm UTC](https://discourse.julialang.org/t/im-trying-to-write-something-with-the-best-possible-performance-for-a-library-i-keep-wishing-i-was-writing-c-is-that-normal-should-i-just-write-c/19286 "2019-01-04T21:09:10Z")
**Posts on this page:** 16
**Page:** 3

<div class="post-metadata">

### Author: ![ninjaaron](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ninjaaron/32/6392_2.png) [@ninjaaron](https://discourse.julialang.org/u/ninjaaron)
#### Post date: [January 6, 2019, 8:26am UTC](https://discourse.julialang.org/t/im-trying-to-write-something-with-the-best-possible-performance-for-a-library-i-keep-wishing-i-was-writing-c-is-that-normal-should-i-just-write-c/19286/42 "2019-01-06T08:26:02Z")

</div>

> [@foobar\_lv2](#):
>
> Minor code review: You produce garbage on invalid things like `raw"""\u123x"""` ( `strtoul` fails to signal the error).

Thanks for that. I sort of knew I should be sending something other than NULL to the `char **endptr` parameter and checking it when I was writing the function, but I didn’t do anything about it. I’ll fix it. Thanks for again for spotting it and mentioning it. (OK, I implemented it, and man is it awkward to deal with `char**` using ccall, but at least it works.)

I’ll look at seeing what I can do with the SIMD in Julia first (great idea, by the way). Writing ASM or LLVM IR or ASM-like C is currently above my paygrade.

---

<div class="post-metadata">

### Author: ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)
#### Post date: [January 6, 2019, 12:31pm UTC](https://discourse.julialang.org/t/im-trying-to-write-something-with-the-best-possible-performance-for-a-library-i-keep-wishing-i-was-writing-c-is-that-normal-should-i-just-write-c/19286/43 "2019-01-06T12:31:45Z")

</div>

See also this thread on writing fast string processing code by operating in chunks, including both SIMD and non-SIMD examples: [https://github.com/JuliaLang/julia/pull/30400](https://github.com/JuliaLang/julia/pull/30400) … using these techniques is sometimes harder if you don’t assume valid UTF-8 (`isvalid` strings), however.

(You can work on 64-bit chunks without SIMD and get quite a speedup over byte-by-byte processing, but not as much as with AVX instructions on 512-bit chunks.)

---

<div class="post-metadata">

### Author: ![oschulz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oschulz/32/2998_2.png) [@oschulz](https://discourse.julialang.org/u/oschulz)
#### Post date: [January 9, 2019, 9:04am UTC](https://discourse.julialang.org/t/im-trying-to-write-something-with-the-best-possible-performance-for-a-library-i-keep-wishing-i-was-writing-c-is-that-normal-should-i-just-write-c/19286/44 "2019-01-09T09:04:15Z")

</div>

Didn’t we have an “unsafe”, allocation-free, pointer-based string type in some package? I forgot where I saw it, but maybe something like that would enable more Julianic code here (via `AbstractString` and substrings instead of low-level buffer operations), without high-frequency memory allocation?

---

<div class="post-metadata">

### Author: ![ninjaaron](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ninjaaron/32/6392_2.png) [@ninjaaron](https://discourse.julialang.org/u/ninjaaron)
#### Post date: [January 9, 2019, 11:46am UTC](https://discourse.julialang.org/t/im-trying-to-write-something-with-the-best-possible-performance-for-a-library-i-keep-wishing-i-was-writing-c-is-that-normal-should-i-just-write-c/19286/45 "2019-01-09T11:46:30Z")

</div>

> [@stevengj](#):
>
> See also this thread on writing fast string processing code by operating in chunks, including both SIMD and non-SIMD examples: [https://github.com/JuliaLang/julia/pull/30400](https://github.com/JuliaLang/julia/pull/30400) … using these techniques is sometimes harder if you don’t assume valid UTF-8 ( `isvalid` strings), however.

Very interesting reading. I’ll have to dig into this more over the weekend.

> [@oschulz](#):
>
> Didn’t we have an “unsafe”, allocation-free, pointer-based string type in some package? I forgot where I saw it, but maybe something like that would enable more Julianic code here (via `AbstractString` and substrings instead of low-level buffer operations), without high-frequency memory allocation?

Interesting thought. I don’t see how your going to get out of allocations, though, if you’re creating a lot of new substring instances (even if they just contain pointers), but maybe the JIT can make that go away in the right circumstances.

I can comprehend how to write C-like Julia now that is fast, but I still have no idea what LLVM and the compiler are doing behind the scenes, so I’m not sure what optimizations I can depend on. (On the other hand, I have no clue how GCC optimizes things either, so maybe I’m in a similar place with C anyway).

---

<div class="post-metadata">

### Author: ![oschulz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oschulz/32/2998_2.png) [@oschulz](https://discourse.julialang.org/u/oschulz)
#### Post date: [January 9, 2019, 12:18pm UTC](https://discourse.julialang.org/t/im-trying-to-write-something-with-the-best-possible-performance-for-a-library-i-keep-wishing-i-was-writing-c-is-that-normal-should-i-just-write-c/19286/46 "2019-01-09T12:18:35Z")

</div>

> [@ninjaaron](#):
>
> Interesting thought. I don’t see how your going to get out of allocations, though, if you’re creating a lot of new substring instances (even if they just contain pointers), but maybe the JIT can make that go away in the right circumstances.

Because for a pointer-based (“unsafe”) string type (has to be used with care!), the instances would be immutable structs that are stack-allocated. So GC will never know about them. If wrote a packages that does this for arrays (UnsafeArrays.jl), and I think I saw the same for Strings somewhere, but I forgot in which package.

---

<div class="post-metadata">

### Author: ![ninjaaron](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ninjaaron/32/6392_2.png) [@ninjaaron](https://discourse.julialang.org/u/ninjaaron)
#### Post date: [January 9, 2019, 12:24pm UTC](https://discourse.julialang.org/t/im-trying-to-write-something-with-the-best-possible-performance-for-a-library-i-keep-wishing-i-was-writing-c-is-that-normal-should-i-just-write-c/19286/47 "2019-01-09T12:24:32Z")

</div>

> [@oschulz](#):
>
> the instances would be immutable structs that are stack-allocated.

Side track: How do I know when Julia is allocating something on the stack or the heap? This topic is extremely relevant to my interests.

---

<div class="post-metadata">

### Author: ![oschulz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oschulz/32/2998_2.png) [@oschulz](https://discourse.julialang.org/u/oschulz)
#### Post date: [January 9, 2019, 12:48pm UTC](https://discourse.julialang.org/t/im-trying-to-write-something-with-the-best-possible-performance-for-a-library-i-keep-wishing-i-was-writing-c-is-that-normal-should-i-just-write-c/19286/48 "2019-01-09T12:48:54Z")

</div>

In general, mutable structs and instances of `Array` are heap-allocated. Primitive data types and immutable structs that are free from references to heap-allocated values are stack-allocated.

You can use `isbitstype` , `isbits` and `Base.isbitsunion` to check if instances of types will be stack-allocated.

Disclaimer: This may be a bit simplified, I seem to remember that @yuyichao once wrote here that isbits and stack-allocated isn’t strictly the same thing, technically.

---

<div class="post-metadata">

### Author: ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)
#### Post date: [January 9, 2019, 7:07pm UTC](https://discourse.julialang.org/t/im-trying-to-write-something-with-the-best-possible-performance-for-a-library-i-keep-wishing-i-was-writing-c-is-that-normal-should-i-just-write-c/19286/49 "2019-01-09T19:07:44Z")

</div>

> [@oschulz](#):
>
> that isbits and stack-allocated isn’t strictly the same thing, technically.

They are not the same practically.

---

<div class="post-metadata">

### Author: ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)
#### Post date: [January 9, 2019, 7:11pm UTC](https://discourse.julialang.org/t/im-trying-to-write-something-with-the-best-possible-performance-for-a-library-i-keep-wishing-i-was-writing-c-is-that-normal-should-i-just-write-c/19286/50 "2019-01-09T19:11:48Z")

</div>

When `@time` or `@btime` or `julia --track-allocations` reports “allocations”, those refer to heap-allocations.

Constructing an instance of an `isbitstype` struct can be done without any heap allocation, while non-`isbitstype` instances _may_ require heap allocation. This is why, for example, you can construct `SVector{3, Int}` or similar from StaticArrays.jl all day long without incurring any heap allocation.

---

<div class="post-metadata">

### Author: ![oschulz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oschulz/32/2998_2.png) [@oschulz](https://discourse.julialang.org/u/oschulz)
#### Post date: [January 9, 2019, 10:07pm UTC](https://discourse.julialang.org/t/im-trying-to-write-something-with-the-best-possible-performance-for-a-library-i-keep-wishing-i-was-writing-c-is-that-normal-should-i-just-write-c/19286/52 "2019-01-09T22:07:20Z")

</div>

> [@yuyichao](#):
>
> They are not the same practically.

@yuyichao, I feared you might say something like that … 😉

That’s why I mentioned you, I had a feeling that I wasn’t entirely correct. But in regard to @ninjaaron’s question: If `isbitstype` returns true, then instances of the type will at least usually be stack-allocated, correct?

I’d also like to learn a bit more about the deeper issues here (e.g. why and when isbits and stack-allocation may not the be same, even practically). Is there any source you can recommend to read more on this?

---

<div class="post-metadata">

### Author: ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)
#### Post date: [January 9, 2019, 10:27pm UTC](https://discourse.julialang.org/t/im-trying-to-write-something-with-the-best-possible-performance-for-a-library-i-keep-wishing-i-was-writing-c-is-that-normal-should-i-just-write-c/19286/53 "2019-01-09T22:27:24Z")

</div>

> [@oschulz](#):
>
> If `isbitstype` returns true, then instances of the type will at least usually be stack-allocated, correct?

No. But if it’s type stable then mostly yes.

> [@oschulz](#):
>
> Is there any source you can recommend to read more on this?

This (stack allocation) is completely in the land of compiler optimization so it’s mostly about what information the compiler have access to and what information it is able to use. It’s a moving target so there won’t be a stable document about it. I doubt there will be very detailed implementation document other than code comments either since given what the compiler knows now, it’s actually easier to understand what the compiler should do based on the intention of the code…

---

<div class="post-metadata">

### Author: ![ninjaaron](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ninjaaron/32/6392_2.png) [@ninjaaron](https://discourse.julialang.org/u/ninjaaron)
#### Post date: [January 9, 2019, 10:43pm UTC](https://discourse.julialang.org/t/im-trying-to-write-something-with-the-best-possible-performance-for-a-library-i-keep-wishing-i-was-writing-c-is-that-normal-should-i-just-write-c/19286/54 "2019-01-09T22:43:41Z")

</div>

What I think I’m hearing is that objects which can be statically analysed to have compile-time guarantees about size should generally be allocated on the stack, and check to make sure in places where it counts (and check again between updates)

---

<div class="post-metadata">

### Author: ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)
#### Post date: [January 10, 2019, 2:59am UTC](https://discourse.julialang.org/t/im-trying-to-write-something-with-the-best-possible-performance-for-a-library-i-keep-wishing-i-was-writing-c-is-that-normal-should-i-just-write-c/19286/55 "2019-01-10T02:59:01Z")

</div>

> [@ninjaaron](#):
>
> objects which can be statically analysed to have compile-time guarantees about size should generally be allocated on the stack

No. Basically all objects have static size at allocation site. `Array` and `String` are the only exceptions other than other extremely special types like `Task`, `Module` etc. Escape (and in general usage) analysis is what matters.

> [@ninjaaron](#):
>
> check to make sure in places where it counts (and check again between updates)

Not sure what this means…

---

<div class="post-metadata">

### Author: ![oschulz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oschulz/32/2998_2.png) [@oschulz](https://discourse.julialang.org/u/oschulz)
#### Post date: [January 10, 2019, 9:44am UTC](https://discourse.julialang.org/t/im-trying-to-write-something-with-the-best-possible-performance-for-a-library-i-keep-wishing-i-was-writing-c-is-that-normal-should-i-just-write-c/19286/56 "2019-01-10T09:44:15Z")

</div>

> [@yuyichao](#):
>
> No. But if it’s type stable then mostly yes.

Oh, sure, I had assumed type stability - sorry, @ninjaaron, should have mentioned that. But I guess your code was already type stable, right?

---

<div class="post-metadata">

### Author: ![ninjaaron](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ninjaaron/32/6392_2.png) [@ninjaaron](https://discourse.julialang.org/u/ninjaaron)
#### Post date: [January 10, 2019, 10:49am UTC](https://discourse.julialang.org/t/im-trying-to-write-something-with-the-best-possible-performance-for-a-library-i-keep-wishing-i-was-writing-c-is-that-normal-should-i-just-write-c/19286/57 "2019-01-10T10:49:31Z")

</div>

I try my best! (in this case, yes)

---

<div class="post-metadata">

### Author: ![ninjaaron](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ninjaaron/32/6392_2.png) [@ninjaaron](https://discourse.julialang.org/u/ninjaaron)
#### Post date: [January 10, 2019, 10:50am UTC](https://discourse.julialang.org/t/im-trying-to-write-something-with-the-best-possible-performance-for-a-library-i-keep-wishing-i-was-writing-c-is-that-normal-should-i-just-write-c/19286/58 "2019-01-10T10:50:24Z")

</div>

I meant check between releases to make sure your not getting more allocations that before (c.f. moving target)

[Previous page](https://discourse.julialang.org/t/im-trying-to-write-something-with-the-best-possible-performance-for-a-library-i-keep-wishing-i-was-writing-c-is-that-normal-should-i-just-write-c/19286.md?page=2)
