# 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:** 20\
**Page:** 2

<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 4, 2019, 11:46pm 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/21 "2019-01-04T23:46:52Z")

</div>

> [@stevengj](#):
>
> `for i = 0:buffer_len-1` ?

```C
for (i=0; i < string; ++i) {
    ++j;
    if (string[i] == '\\' {
        ++i;
        bytes_written = some_func(string+i, buffer+j);
    }
    keep doing stuff...
}

```

It was a case where I want to be able to increment `i` in the body of the loop. Normally, I’d use `Iterators.Stateful`, but I don’t know how efficient it will be, and I trust integer arithmetic more. Not that that is impossible to do it in Julia, it’s just less natural, at least for me, right now.

---

<div class="post-metadata">

**Author:** ![dfdx](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dfdx/32/120_2.png) [@dfdx](https://discourse.julialang.org/u/dfdx)\
**Post date:** [January 4, 2019, 11:56pm 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/22 "2019-01-04T23:56:54Z")

</div>

> [@ninjaaron](#):
>
> ```julia
> for (i=0; i < string; ++i) {
> ++j;
> if (string[i] == '\\' {
> ++i;
> bytes_written = some_func(string+i, buffer+j);
> }
> keep doing stuff...
> }
> 
> ```

```julia
for i=1:length(string)
    j += 1
    if (string[i] == '\\' 
        bytes_written = some_func(string+i+1, buffer+j)
        continue # move to the next iteration where i is incremented
    end
    keep doing stuff...
end

```

---

<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 4, 2019, 11:58pm 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/23 "2019-01-04T23:58:24Z")

</div>

> [@dfdx](#):
>
> Fortunately, Julia supports alternative implementations of `AbstractString` which should work with most string functions without conversion. You might find something more suitable for your needs in [Strs.jl](https://github.com/JuliaString/Strs.jl) or even implement your own string type.

This might be just what the Dr. ordered! I will look at Strs.jl. I’m not too sure what methods are needed for `AbstractString` and `AbstractChar`. Can you point to some relevant documentation about this topic?

---

<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 5, 2019, 12: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/24 "2019-01-05T00:04:50Z")

</div>

> [@dfdx](#):
>
> `bytes_written = some_func(string+i+1, buffer+j)`

waaaaaat? I don’t thing pointer arithmetic works like that in Julia.

Oh. I see. `string` was supposed to be a pointer to an array, but I there is a bug in my loop declaration (story of my life…). should have been something like `i < length(string)`. I guess I can do something with `@view`. That’s the Julia version of pointer arithmetic, right?

---

<div class="post-metadata">

**Author:** ![dfdx](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dfdx/32/120_2.png) [@dfdx](https://discourse.julialang.org/u/dfdx)\
**Post date:** [January 5, 2019, 12:24am 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/25 "2019-01-05T00:24:04Z")

</div>

> [@ninjaaron](#):
>
> waaaaaat? I don’t thing pointer arithmetic works like that in Julia.

Ah, right, I just copied this line and shifted index by 1 to account 1-based indexing.

> I guess I can do something with `@view` . That’s the Julia version of pointer arithmetic, right?

It depends on what `some_func` actually does. For example, if `some_func` compares `string`’s char at position `i + 1` to another char in `buffer`’s position `j`, then it’s just indexing:

```julia
some_func(string[i + 1], buffer[j])

```

If in C `string + i` and `buffer + j` are pointers in the same array (such as start and end of iterator), you can rewrite it using a view:

```julia
some_func(@view original_array[i + 1 : j])

```

or using 2 indices:

```julia
some_func(original_array, i + 1, j) # iterate over original_array from index i + 1 to index j

```

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [January 5, 2019, 1:34am 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/27 "2019-01-05T01:34:29Z")

</div>

Compare the hash functions 😉

Edit: Post got deleted.

---

<div class="post-metadata">

**Author:** ![bennedich](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bennedich/32/4894_2.png) [@bennedich](https://discourse.julialang.org/u/bennedich)\
**Post date:** [January 5, 2019, 2:02am 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/28 "2019-01-05T02:02:23Z")

</div>

> [@kristoffer.carlsson](#):
>
> Compare the hash functions 😉

Yes… I realized that too just after posting that message and thought I’d save everyone the confusion and potential flaming 🙂 The data structures I’ve actually struggled with are in `DataStructures.jl` btw, not `Dict`, I just thought I’d use that for a better example. I guess I should post some sample code on this forum first before giving up on Julia 🙂

---

<div class="post-metadata">

**Author:** ![Liso](https://avatars.discourse-cdn.com/v4/letter/l/898d66/32.png) [@Liso](https://discourse.julialang.org/u/Liso)\
**Post date:** [January 5, 2019, 7: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/29 "2019-01-05T07:44:34Z")

</div>

> [@ninjaaron](#):
>
> Maybe that’s the problem. I can write C goes fast and does the right things with memory, but I don’t know a lick of assembly. Maybe the next step for me (in general, not necessarily as part of this project) is getting more comfortable with asm so I can understand more about how Julia optimizes.

Which is interesting “solution” to two language problem, right? 😛

---

<div class="post-metadata">

**Author:** ![c42f](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/c42f/32/52842_2.png) [@c42f](https://discourse.julialang.org/u/c42f)\
**Post date:** [January 5, 2019, 9:16am 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/30 "2019-01-05T09:16:35Z")

</div>

> [@Liso](#):
>
> Which is interesting “solution” to two language problem, right?

The point is not to write assembly (or llvm, or indeed, lowered/type inferred julia code) but to understand the kinds of things your julia code will be turned into so you can understand the cost of various constructs. It’s mainly useful for detailed optimizations of innermost loops as a useful complement to benchmarking. Personally I’m not fluent in assembly at all, but I can read it just well enough to see whether desired optimizations are happening.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [January 5, 2019, 10:38am 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/31 "2019-01-05T10:38:02Z")

</div>

> [@ninjaaron](#):
>
> I don’t know a lick of assembly. Maybe the next step for me (in general, not necessarily as part of this project) is getting more comfortable with asm so I can understand more about how Julia optimizes.

This should not be necessary. I don’t know assembly or LLVM primitives either, but by looking at the output of `@code_llvm` you can get a pretty good idea of what is going on, what the compiler figured out, and what it didn’t. But even that is not necessary in most cases, go with `@code_warntype` 99% of the time.

I would also argue that `@code_native` is less useful than `@code_llvm` for most cases, since it is rather a lot of information with even less structure, and easy to get lost in. It is also a common mistake to assume that assembly code length somehow maps to execution speed; this does not necessarily hold when optimizing the same computation.

Also, about the original post: I think that “best possible performance” is not a good goal except in very special situations. Diminishing returns kick in rather early in Julia (because it is so fast already) — typically, in order of descending importance, after you have

1. chosen the right algorithm and data structures,
2. made sure things are concretely typed,
3. made sure the compiler can figure out types (`@code_warntype`),
4. took care of major allocations in inner loops,
5. profiled, optimized, and annotated some parts (eg `@inbounds`), but strictly in Julia.

These days, especially with `master`, this usually gets you within 10–20% of what you could get with micro-optimizations which are much, much more costly to maintain in the long run. Be wary of the latter: a lot of libraries are littered with hacks that looked like a good idea at the time, but then 3 years later are still around and may even be suboptimal until someone bothers to benchmark and refactor (I am guilty of doing this too, but the punishment is self-contained when I need to touch said code).

It sometimes happens that you run into issues where the compiler could figure out something but currently doesn’t. In these cases, you can either wait for the fix and not worry about it in the meantime, or separate the functionality to a kernel function that contains the workaround, and make a note about the issue so that you can remove it once it is fixed.

The strategy I would recommend is writing clean Julia code, and trusting that the compiler is getting more and more clever, and confine micro-optimizations to 1% of the cases where it is really needed.

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [January 5, 2019, 12:37pm 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/32 "2019-01-05T12:37:41Z")

</div>

> [@Liso](#):
>
> Which is interesting “solution” to two language problem, right? 😛

Assembly instructions are what the processor actually will execute in the end no matter the programming language? In other words, it is the point of _all_ programming languages to turn input code into assembly instructions. Being able to inspect this generated code is very useful and if you want to be able to write performant code you will need to learn it, again, irrespectively of the programming language used.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [January 5, 2019, 1:05pm 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/33 "2019-01-05T13:05:42Z")

</div>

> [@kristoffer.carlsson](#):
>
> if you want to be able to write performant code you will need to learn it

While being able to understand assembly is a very useful skill, I would argue that the majority of Julia users trying to write _reasonably_ performant code (within, say, 50% of C/Fortran) can get away with `@code_warntype` 90% of the time and possibly `@code_llvm` for the remaining 10%. Fortunately, the latter is still pretty readable and much easier to follow than native asm.

---

<div class="post-metadata">

**Author:** ![foobar\_lv2](https://avatars.discourse-cdn.com/v4/letter/f/ee59a6/32.png) [@foobar\_lv2](https://discourse.julialang.org/u/foobar_lv2)\
**Post date:** [January 5, 2019, 1:33pm 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/34 "2019-01-05T13:33:42Z")

</div>

> [@Tamas\_Papp](#):
>
> These days, especially with `master` , this usually gets you within 10–20% of what you could get with micro-optimizations which are much, much more costly to maintain in the long run

With the exception of algorithms that are designed around a specific processor instruction (e.g. aes, more fancy SIMD, bit manipulation). This is currently super annoying in julia (compared to C). Second exception are C-style unions that are just not supported in julia (kinda works by pointer convert, but ugly and often emits very slow and bad code), and third exception are mutable fixed-size stack allocated temporary arrays (kinda works by `unsafe_store!` to `pointer_from_objref` but is more ugly than C).

Some day I want to port/adapt [adaptive radix trees](https://github.com/armon/libart) to pure julia, but this needs all three of these features.

---

<div class="post-metadata">

**Author:** ![chakravala](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chakravala/32/6832_2.png) [@chakravala](https://discourse.julialang.org/u/chakravala)\
**Post date:** [January 5, 2019, 1:37pm 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/35 "2019-01-05T13:37:12Z")

</div>

> [@Tamas\_Papp](#):
>
> It sometimes happens that you run into issues where the compiler could figure out something but currently doesn’t. In these cases, you can either wait for the fix a…

Another thing you can do is use parametric types pass the missing information to the compiler, and use `@pure` if necessary.

> [@Tamas\_Papp](#):
>
> It is also a common mistake to assume that assembly code length somehow maps to execution speed; this does not necessarily hold when optimizing the same computation.

Agreed, I think `@code_warntype` might be more useful in general, because you can see if the type allocations are all stable and where there is an issue with simplifying, which is more important.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [January 5, 2019, 2:16pm 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/36 "2019-01-05T14:16:31Z")

</div>

While I don’t disagree about the importance of these features, I think that these discussions make it difficult for new users to focus on the relatively low-hanging fruits of optimizing Julia code with the simple to use facilities that Julia offers, without worrying about CPU instructions or similar.

There is a healthy tendency to squeeze out performance from code on this forum, but sometimes it very quickly gets to eyeballing output of `@code_native` and discussing SIMD, so I think that some users get the impression that getting reasonable performance out of Julia is a daunting enterprise that involves assembly, SIMD, low-level tricks and interfacing with LLVM. But this is not true: while one can always optimize things, common usage is mostly about [avoiding pitfalls](https://docs.julialang.org/en/v1/manual/performance-tips/#man-performance-tips-1), and then getting reasonable performance.

---

<div class="post-metadata">

**Author:** ![tshort](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tshort/32/43_2.png) [@tshort](https://discourse.julialang.org/u/tshort)\
**Post date:** [January 5, 2019, 2:42pm 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/37 "2019-01-05T14:42:53Z")

</div>

You should probably benchmark [LazyJSON](https://github.com/samoconnor/LazyJSON.jl) and [JSON2](https://github.com/quinnj/JSON2.jl). Both are much faster than the JSON package. Even if you don’t use them, the code might provide inspiration.

[TextParse](https://github.com/JuliaComputing/TextParse.jl) may also be useful, too.

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [January 5, 2019, 6:01pm 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/38 "2019-01-05T18:01:44Z")

</div>

It’s hard to give specific help without specific problems that you’re trying to tackle but one can certainly write high performance string code in Julia using the native `String` type, although it is a bit different than C and does take a little getting used to. The `ncodeunits` and `codeunit` functions give you read access to raw bytes at C performance. The `nextind` and `prevind` functions allow you to navigate between Unicode characters (using code unit indices). Unless you need to modify the string data in place, I suspect you don’t need to convert anything to byte vectors and that doing so may make things less efficient and more complicated. If you have specific questions, I’m happy to give advice.

---

<div class="post-metadata">

**Author:** ![davidanthoff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/davidanthoff/32/223493_2.png) [@davidanthoff](https://discourse.julialang.org/u/davidanthoff)\
**Post date:** [January 5, 2019, 9:36pm 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/39 "2019-01-05T21:36:55Z")

</div>

[TextParse.jl](https://github.com/JuliaComputing/TextParse.jl) has some very highly optimized routines for parsing. In general, at this point, we seem to be very competitive with some of the fastest implementations that exist in C (see [here](https://github.com/JuliaComputing/TextParse.jl/pull/88#issuecomment-449871474) for the latest benchmarks).

Two things you might take a look at: [https://github.com/JuliaComputing/TextParse.jl/blob/master/src/utf8optimizations.jl](https://github.com/JuliaComputing/TextParse.jl/blob/master/src/utf8optimizations.jl) has the really performance critical routines highly optimized using `codeunit` calls. For the best performance, that seems the way to go. Another neat thing is [https://github.com/JuliaComputing/TextParse.jl/blob/master/src/VectorBackedStrings.jl](https://github.com/JuliaComputing/TextParse.jl/blob/master/src/VectorBackedStrings.jl). We use that to provide an `AbstractString` over a memory mapped file, which is great for parsing files that are very large.

So, from spending a fair bit of time with that code base over the last half year, here are some reasons why I think it makes a lot of sense to write this in pure julia and not C:

- while the code might be slightly more verbose than a C version, it generally is mostly “safer”. Essentially no pointer arithmetic etc. And the code is very clear.
- I think the biggest benefit to me is how super productive one can be when working on this type of code, with the help of [Revse.jl](https://github.com/timholy/Revise.jl) and [ProfileView.jl](https://github.com/timholy/ProfileView.jl). Here is my typical workflow: I have a REPL open with Revise loaded, then load TextParse and [BenchmarkTools.jl](https://github.com/JuliaCI/BenchmarkTools.jl). I now load some large file under the profiler, so `@profile csvread("foo.csv")`, then I look at the profiling results with ProfileView.jl and immediately see where it would pay of to optimize code. I pick a certain function to optimize, based on that, and execute that under BenchmarkTools at the REPL: `@btime tryparsenext(....)`. Alright, now I have a baseline. I work a bit on the code, hit up arrow in the REPL and run the benchmark again. Thanks to Revise.jl, the new code now is run, and I can immediately tell whether my new code is better or now. And then I repeat this cycle. I find that unbelievably productive. No long breaks while I have to wait for some compiler to finish something, and a super rapid feedback cycle with some really powerful tools.
- I think this was mentioned above already, but the ability to seamlessly decide at which level you actually need really performant code is also nice. It is just super easy to say “oh, I guess this function also need to be faster”. You can just immediately start working on that function, without worrying how you might move it out into a C library and how things would work together at that poin…

There are some things that I think we could find better patterns for. For example, I’m pretty sure we could write some of this code in a more generic way, so that it has the performance we see right now, but not just for UTF8 encoded strings, but also for other string types. One of my goals is to be able to plug a non-UTF8 string type under the hood of TextParse.jl, so that one can also read files that are encoded with some other encoding. I haven’t found the perfect balance for that issue, but I’m pretty sure it can be done and I just need to think a bit more about it 🙂

---

<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 5, 2019, 9:54pm 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/40 "2019-01-05T21:54:19Z")

</div>

@Sukera @stevengj @StefanKarpinski

All those who asked for sample code, here’s some:

[https://github.com/ninjaaron/LibAaron.jl/blob/master/jsondec.jl](https://github.com/ninjaaron/LibAaron.jl/blob/master/jsondec.jl)

So I got this working, and it’s more than 3x faster _for my usecase_ than any of the JSON alternatives mentioned in this thread (probably because it does much less; my usecase, right now, is dealing with 800 million RDF n-triples, which have JSON strings literals embedded in them with A LOT of unicode escapes in them, so my efforts have been mostly focused on making the conversion of unicode escapes faster–so I’m not interested in parsing huge JSON files at this moment, but in parsing a billion+ tiny JSON strings.)

I would say I’m happy with this performance result, but the code was kind of hard to write, and it’s not very idiomatic Juila. It does have one ccall in it, because it made dealing with Unicode escape parsing more than twice as fast, but it’s just a call to libc, not anything exotic, and certainly not any compile-at-home code. It contains many buffers and more pointers than it probably should, but the results are good. I mean really, the standard library is full of calls to libc.

Also, I commented out the JSON.jl benchmark. You can put it back, you want. Importing JSON.jl actually consistently makes the benchmark for my own code return an ~20% slower result. Not sure why…

---

<div class="post-metadata">

**Author:** ![foobar\_lv2](https://avatars.discourse-cdn.com/v4/letter/f/ee59a6/32.png) [@foobar\_lv2](https://discourse.julialang.org/u/foobar_lv2)\
**Post date:** [January 6, 2019, 1:16am 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/41 "2019-01-06T01:16:44Z")

</div>

Minor code review: You produce garbage on invalid things like `raw"""\u123x"""` (`strtoul` fails to signal the error).

Depending on your actual strings, you might get better mileage by using SIMD (pcmpeqb / vpcmpeqb / \_mm\_cmpeq\_epi8 / \_mm256\_cmpeq\_epi8) to search for backslashes (copy one 16/32 byte chunk, compare all its bytes to `0x5c` at once in a single cycle, fastpath the case of no backslash, otherwise extract position of first backslash and handle it).

That currently needs some processor specific inline llvm though (Kristoffer is working on a package that aims to reach C-intrinsics level of convenience, but it’s not there yet, and not available in `SIMD.jl` either). If you need more speed, then I would probably recommend to write that single function (JSON string unescape, not entire parser logic) in C and `ccall` it, until the situation has improved. Even better, look whether someone already wrote a fast SIMD unescape function with bsd license (effectively in assembly, even if it is formally C code).

[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=1)

[Next 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=3)
