Coder Social home page Coder Social logo

jberryman / unagi-chan Goto Github PK

View Code? Open in Web Editor NEW
127.0 9.0 15.0 526 KB

A haskell library implementing fast and scalable concurrent queues for x86, with a Chan-like API

License: BSD 3-Clause "New" or "Revised" License

Haskell 100.00%
haskell concurrency queue

unagi-chan's Introduction

Build Status

The library is available on hackage and you can install it with:

$ cabal install unagi-chan

Design

The idea is to design a queue around the x86 fetch-and-add instruction, which performs well under contention.

The queue is conceptually simple, consisting of: an infinite array, and two atomic counters, one for readers and another for writers. A read or write operation consists of incrementing the appropriate counter and racing to perform an atomic operation on the specified index.

If the writer wins it has written its value for the reader to find and exits. When it loses it does a rendezvous with the blocked or blocking reader, via another mechanism and hands off its value.

Linearizabillity

The queue has FIFO semantics, reasoning in terms of linearizability. Our atomic counter ensures that all non-overlapping reads and writes are assigned indices in temporal order.

Lockfree - ness

Operations are non-blocking, with the exception that a stalled writer may block at most one reader (the reader "assigned" to it by our internal counter).

Performance

Here is an example benchmark measuring the time taken to concurrently write and read 100,000 messages, with work divided amongst increasing number of readers and writers, comparing against the top-performing queues in the standard libraries. The inset graph shows a zoomed-in view on the implementations here.

Benchmarks

Some of these variants may be deprecated in the future if they are found to provide little performance benefit, or no unique features; you should benchmark and experiment with them for your use cases, and please submit pull requests for additions to the benchmark suite that reflect what you find.

unagi-chan's People

Contributors

danclien avatar hvr avatar jberryman avatar jfischoff avatar newhoggy avatar noeda avatar spacekitteh avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

unagi-chan's Issues

Estimated bounded queue length

Is there a way to get an estimated length for a bounded queue? It would be nice to be able to send that metric over to our monitoring system.

Add a bounded version

I would be fine with a fuzzy bounded version, i.e. if the count was incremented non atomically from queue such that the queue could exceed the bounds some what, or think they are higher then they are.

For most of my use cases, I need a bounded queue never blocks on writes, and returns and error code on overflow.

Anyway, very impressed with the performance. Thanks!

Space leak?

I've used unagi-chan in for around a year on a couple of projects. I had always noticed climbing memory usage generally but never needed to track down why. A few weeks ago, that changed and I needed to track down our space leak. Sadly, all signs pointed to unagi-chan as the culprit and once purged from the app the leak disappeared. I've replicated the issue we were seeing in a fork as I was hoping to that added profiling flags to the base library could get better insights into what is going on.

https://github.com/buckie/unagi-chan/tree/bug/spaceleak

This, sadly, didn't work. It seems that there's too much inlining without SCC annotations to get a good look at the root cause.

The replication creates 10k large-ish byte strings, put's them on a channel, read's half (summing their length), performs a major GC, reads the rest, performs another major GC. This is done as one thread and then as two. I've included the ps files in the repo plus a couple scripts to replicate the environment and make running the tests easier.

screen shot 2016-10-19 at 6 36 33 pm

I've done some other tests as well, where the reader thread outruns the writer thread, and those show the expected flat (or pyramid-ish because I drained half, thread delay 1s, drain the rest) memory usage. My interpretation of the results is that memory isn't being allowed GC unless the channel is fully empty.

Capacity-reached callback

It would be really useful for tuning to have a capacity-reached callback on chans. On unbounded chans, the callback could be used to gauge potential memory issues and on bounded chans, its an indication of blocking. Both cases indicate tuning is necessary.

bounded blocking?

I typically use chans for backpressure, so it's important to me to be able to say "the queue can have at most 1000 elements, and subsequent writes block". Any way to build that behaviour out of unagi-chan?

unagi-chan 0.4.1.1 fails to build

unagi-chan 0.4.1.1 currently fails to compile on the latest Stackage nightly with the following error:

    /var/stackage/work/unpack-dir/unpacked/unagi-chan-0.4.1.1-85323be87dcc5cbc82628795ca4c75fa1db82400cc743cbc3d6bb836b4867c70/src/Control/Concurrent/Chan/Unagi/Unboxed/Internal.hs:219:20: error:
        Not in scope: type constructor or class ‘Addr’
        Perhaps you meant ‘Data.Primitive.Addr’ (imported from Data.Primitive)
        |
    219 | instance UnagiPrim Addr where
        |                    ^^^^

cf. commercialhaskell/stackage#4765

Memory consumption of bounded Chan

As I understand unagi-chan create segments with size of queue size which is passed to newChan function. And that means that even with fast readers and almost empty queue we could easily have up to size chan elements in memory which couldn't get garbage collected.
Is there some good way to have large queue size and not waste a lot of memory? Or maybe I read code incorrectly and there is some other explanation for https://gist.github.com/qrilka/1f7cd7c2254b0e267de77d3c61542d43 to consume significant amount of RAM.

Get tests running in CI

The full suite takes too long for travis, and there are a few tests that are pretty sensitive. Probably expose a very minimal set of tests in CI (unfortunately).

Blocking read available contents of Chan to list

Is there a way to flush chan contents to a list? tryReadChan is definitely not what I want, as it removes elements from chan to Element with no way to place it back. NoBlocking version's stream can do what I want, but I need multiple producers/multiple consumers, where each consumer can try to flush whole Chan to list. I think I can go around it using MVar around OutChan, but that feels dirty. Is there anything like flushTBQueue that I missed?

Flipped in and out meaning

We read from stdin and write to stdout. Similarly, io-streams allows you to read from InputStreams and write to OutputStreams. Unagi chans are the reverse of this. Was there a motivation to name unagi chan in and out differently? If not, would you consider flipping it?

Test time out on Stackage

unagi-chan: BuildFailureException Test suite timed out: unagi-chan-0.4.0.0:test

I've added the package to the expected-test-failures for time outs. Hopefully this ticket can track any changes you can make that can get this fixed up.

Document getChanContents so it's clear it blocks & returns an infinite list, not a batch of available elements

I doubt that it's a feature, but getting contents of a channel (both bounded and unbounded) will exhaust computer resources quickly if the lazy list that gets produced gets reversed:

module Main where
import Control.Concurrent.Chan.Unagi

main :: IO ()
main = do
  (_inChan, outChan) <- newChan :: IO (InChan Int, OutChan Int)
  is <- getChanContents outChan
  print $ reverse is

Conceptually it kind of make sense, but in practice it's terrible.

Metadata corrected

As can seen in a prior build report https://matrix.hackage.haskell.org/package/unagi-chan@1565619672 the upper bound base < 5 wasn't accurate as there were build failures with base-4.13

Consequently, I've fixed up the metadata via a few metadata revisions to help the cabal solver avoid picking build-plans that'll fail to compile:

GHC doesn't do floating point constant folding

In the source there are some constants which have type Float wrapped in round. GHC doesn't do any form of Float constant folding yet, so you should hand-calculate these into Int (and probably leave the original ones commented out above) for a tiny speed bonus.

single-producer and/or single-consumer variants

It would be straight-forward to write variants of the readChan and writeChan functions which can omit some atomic operations or bookkeeping when only run from a single thread. At some point I certainly plan to do this for readChan to support an even more efficient MPSC queue.

A cop-out which may happen would be to simply export

unthreadsafeReadChan :: OutChan a -> IO a

Or alternatively, a safe API which uses lazy IO:

newMPSCChan :: IO (InChan a, [a])

I'm not sure if the later is easily-done, or would have performance implications.

Please comment if you have an interest in this use case or any thoughts.

Unagi chan vanishing issue when over 250 unique websockets are sent

https://github.com/bitemyapp/websocket-shootout/pull/3#issuecomment-244559303

Basically if "step-size" from this benchmark is over 250 unagi chan starts having errors like:

$ ./bin/hs-websocket-server 
hs-websocket-server: writev: resource vanished (Connection reset by peer)
hs-websocket-server: ConnectionClosed
hs-websocket-server: writev: resource vanished (Broken pipe)
hs-websocket-server: writev: resource vanished (Broken pipe)
hs-websocket-server: writev: resource vanished (Broken pipe)
hs-websocket-server: writev: resource vanished (Broken pipe)
hs-websocket-server: writev: resource vanished (Broken pipe)
hs-websocket-server: writev: resource vanished (Broken pipe)
hs-websocket-server: hs-websocket-server: writev: resource vanished (Broken pipe)
writev: resource vanished (Broken pipe)
hs-websocket-server: writev: resource vanished (Broken pipe)
hs-websocket-server: writev: resource vanished (Broken pipe)
hs-websocket-server: writev: resource vanished (Broken pipe)
hs-websocket-server: writev: resource vanished (Broken pipe)
hs-websocket-server: writev: resource vanished (Broken pipe)
hs-websocket-server: writev: resource vanished (Broken pipe)
hs-websocket-server: writev: resource vanished (Broken pipe)
hs-websocket-server: writev: resource vanished (Broken pipe)
hs-websocket-server: writev: resource vanished (Broken pipe)
hs-websocket-server: writev: resource vanished (Broken pipe)
hs-websocket-server: writev: resource vanished (Broken pipe)
hs-websocket-server: writev: resource vanished (Connection reset by peer)hs-websocket-server: writev: resource vanished (Broken pipe)

hs-websocket-server: writev: resource vanished (Broken pipe)
hs-websocket-server: ConnectionClosed

Though, this could have been from not increasing number of open files on the OS running the application.

Either way, I saw the performance benchmarks on the cabal page for unagi-chan, thought you seemed very concerned with performance, and as a result would be very interested in the issue happening here.

As a bonus this hashrocket websocket example defintely counts as a realistic use case for benchmarking as you were asking for ideas on in #8.

Hopefully we can figure this out and Haskelll/unagi-chan will have a good showing in the hashrocket websocket benchmark.

Non-blocking reads

It would probably be straightforward to implement functions like:

readChanFuture :: OutChan a -> IO (Future a)
tryGetFuture :: Future a -> IO (Maybe a)  -- returns immediately 
getFuture :: Future a -> IO a                     -- blocks waiting for `a`

where once readChanFuture was called, the only way to access the element would be through the returned Future value. But this would allow the reader to decide when or if to block.

Please comment if this is a function you need, or you have any other feedback.

Realistic use-cases for benchmarking

I'd love to have some small, example programs that each represent some realistic use-case. These would supplement the existing benchmarks which do a good job of measuring the effects of contention and descheduling, and throughput.

Helping

If you have a use-case it would be a great help if you could package it up as a single file living under benchmarks/realistic/ and submit a pull request. I'll then integrate it into the benchmark suites in some way, and use it to guide future development.

If applicable the function you export can take Int arguments for configuring number of threads and iterations.

Document tryReadChan/Element better w/r/t destructive nature of operation

So I am trying to track down an issue I am seeing when using channels with parallel threads. Here is the current scenario that I am seeing give me problems.

Channel: Control.Concurrent.Chan.Unagi

Setup:
I have two threads A and B that share a channel Q; A is producer and B is consumer. Thread A consumes a stream of data and notifies Thread B when the stream is consumed (due to an exception or graceful finish) via a message to the Q. Thread A will then wait for thread B to fully exit by blocking on a takeMVar that is set by a putMvar in thread B.

Scenario:
Thread A and thread B are both created using forkIO and thread B blocks on Q with a "readChan" waiting for messages. Thread A begins processing a stream of data. Eventually thread A has an exception reading stream, catches it and sends a message to B (via Q) to exit. Thread A blocks on MVar, concurrently Thread B receives the exit message and sets the MVar, then exits. Thread A takeMVar succeeds and then clears the Q of any possible messages remaining in it. Thread A then proceeds to retry reading the stream, upon success a new thread B (view forkIO) is created and again thread B blocks on a readChan (on original Q). Eventually another exception is thrown on thread A while reading the stream, so again thread A sends the exit message to B (via Q) and then blocks on MVar waiting on thread B to exit. Only this time thread B never seems to receive the message and sits waiting to read a message from the Q.


So I should call out this doesn't happen every time, sometimes I can get through the work/fail/spawn loop a couple of times before it fails. This leads me to believe it is probably some sort of rare race condition. I'm assuming I don't need to use the readChanOnException within Thread B since this is not where the exception is being generated. I might try using the non-blocking channel with streams and see if it makes a difference. But any thoughts on this would be great!

NOT_x86 discussion

Is there any discussion around the NOT_x86 CPP, that leads to warnings being emitted and subsequent failing builds with -Wall? I have to assume this is due to some ancient atomic-primops limitation?

Which instruction is used here that makes the warning necessary (and restricts the use to x86)?

Concurrent ByteString or Text readers or builders

Unagi.Unboxed could be modified fairly easily to use a payload that matches the internals of either Text or ByteString. I'm a little bit sketchy on details but this could accommodate some pretty interesting and very efficient functions, like:

  • a concurrent builder for Text, something like:

    new :: IO (InTextChan , Lazy.Text)
    write :: String -> InTextChan -> IO ()
    
  • something similar for ByteString (is there a class for types convertable to ByteString?)

  • concurrent Text and/or ByteString readers, something like:

    reader :: Text -> IO TextReader
    takeText :: Int -> TextReader -> IO Text
    
  • functions like the above but where the inputs are already Text. This case would involve efficient memory copies into the unagi array; I'm not sure if this makes more or less sense than functions describes above which would convert and write directly into the unagi array.

Please comment with your particular use case if you need something like these.

Document behaviour of reading from "finished" channel?

In the NoBlocking documentation (under isActive), it says:

Note that in the blocking implementations a BlockedIndefinitelyOnMVar exception is raised, so this function is unnecessary.

I can't see this mentioned anywhere in the blocking documentation...

Bounded Queue with lossy Readers

Currently when the Bounded Queue is full, writes block - is it possible to introduce behavior that lets writes complete successfully when the queue is full? Our use case is a bounded queue of ephemeral, timely data - we do not want to throttle the writer and prefer to have readers that lose messages.

I have not dug into the internals of the library, but noticed some of this kind of behavior with the dupChan:

slower readers of duplicated OutChan may fall arbitrarily behind.

is it possible to bring this behavior in for even a single reader?

I asked about this issue on haskell-cafe, and we ended up with an implementation following the suggested strategy. But would still love to move off our homegrown stuff and on to something hopefully more performant. As mentioned on the email thread, Pipes.Concurrent kind of has this with the newest, though I was unsure of the implementation approach:

        Newest n  -> do
            q <- S.newTBQueueIO n
            let write x = S.writeTBQueue q x <|> (S.tryReadTBQueue q *> write x)
            return (write, S.readTBQueue q)

(at the time, we wanted to be able to have multiple readers from our channels).

I'm happy to help out with the implementation. Thanks!

AArch64 build error

On AArch64, the builds end on a linker error:

[  507s] /usr/bin/ghc -shared -dynamic '-dynload deploy' -optl-Wl,-rpath,/usr/lib64/ghc-8.0.2/atomic-primops-0.8.0.4-FvFLsKpDYPjGSQUM1RkO57 -optl-Wl,-rpath,/usr/lib64/ghc-8.0.2/base-4.9.1.0 -optl-Wl,-rpath,/usr/lib64/ghc-8.0.2/ghc-prim-0.5.0.0 -optl-Wl,-rpath,/usr/lib64/ghc-8.0.2/integer-gmp-1.0.0.1 -optl-Wl,-rpath,/usr/lib64/ghc-8.0.2/primitive-0.6.2.0-4578caNkWQ54Gt1mxLF2Yh -optl-Wl,-rpath,/usr/lib64/ghc-8.0.2/rts -optl-Wl,-rpath,/usr/lib64/ghc-8.0.2/transformers-0.5.2.0 -hide-all-packages -no-auto-link-packages -no-user-package-db -package-db dist/package.conf.inplace -package-id atomic-primops-0.8.0.4-FvFLsKpDYPjGSQUM1RkO57 -package-id base-4.9.1.0 -package-id ghc-prim-0.5.0.0 -package-id primitive-0.6.2.0-4578caNkWQ54Gt1mxLF2Yh dist/build/Control/Concurrent/Chan/Unagi.dyn_o dist/build/Control/Concurrent/Chan/Unagi/Unboxed.dyn_o dist/build/Control/Concurrent/Chan/Unagi/Bounded.dyn_o dist/build/Control/Concurrent/Chan/Unagi/NoBlocking.dyn_o dist/build/Control/Concurrent/Chan/Unagi/NoBlocking/Unboxed.dyn_o dist/build/Control/Concurrent/Chan/Unagi/Internal.dyn_o dist/build/Control/Concurrent/Chan/Unagi/Unboxed/Internal.dyn_o dist/build/Control/Concurrent/Chan/Unagi/Bounded/Internal.dyn_o dist/build/Control/Concurrent/Chan/Unagi/NoBlocking/Internal.dyn_o dist/build/Control/Concurrent/Chan/Unagi/NoBlocking/Types.dyn_o dist/build/Control/Concurrent/Chan/Unagi/NoBlocking/Unboxed/Internal.dyn_o dist/build/Control/Concurrent/Chan/Unagi/Constants.dyn_o dist/build/Utilities.dyn_o dist/build/Data/Atomics/Counter/Fat.dyn_o -o dist/build/libHSunagi-chan-0.4.0.0-5jpOsOJF9IVIuLemdLMVEv-ghc8.0.2.so
[  509s] /usr/bin/ld.gold: error: dist/build/Control/Concurrent/Chan/Unagi/NoBlocking/Unboxed.dyn_o: multiple definition of 'write_barrier'
[  509s] /usr/bin/ld.gold: dist/build/Control/Concurrent/Chan/Unagi/NoBlocking.dyn_o: previous definition here
[  509s] /usr/bin/ld.gold: error: dist/build/Control/Concurrent/Chan/Unagi/Unboxed/Internal.dyn_o: multiple definition of 'load_load_barrier'
[  509s] /usr/bin/ld.gold: dist/build/Control/Concurrent/Chan/Unagi/Internal.dyn_o: previous definition here
[  509s] /usr/bin/ld.gold: error: dist/build/Control/Concurrent/Chan/Unagi/Bounded/Internal.dyn_o: multiple definition of 'load_load_barrier'
[  509s] /usr/bin/ld.gold: dist/build/Control/Concurrent/Chan/Unagi/Internal.dyn_o: previous definition here
[  509s] /usr/bin/ld.gold: error: dist/build/Control/Concurrent/Chan/Unagi/NoBlocking/Internal.dyn_o: multiple definition of 'write_barrier'
[  509s] /usr/bin/ld.gold: dist/build/Control/Concurrent/Chan/Unagi/NoBlocking.dyn_o: previous definition here
[  509s] /usr/bin/ld.gold: error: dist/build/Control/Concurrent/Chan/Unagi/NoBlocking/Internal.dyn_o: multiple definition of 'load_load_barrier'
[  509s] /usr/bin/ld.gold: dist/build/Control/Concurrent/Chan/Unagi/Internal.dyn_o: previous definition here
[  509s] /usr/bin/ld.gold: error: dist/build/Control/Concurrent/Chan/Unagi/NoBlocking/Unboxed/Internal.dyn_o: multiple definition of 'write_barrier'
[  509s] /usr/bin/ld.gold: dist/build/Control/Concurrent/Chan/Unagi/NoBlocking.dyn_o: previous definition here
[  509s] /usr/bin/ld.gold: error: dist/build/Control/Concurrent/Chan/Unagi/NoBlocking/Unboxed/Internal.dyn_o: multiple definition of 'load_load_barrier'
[  509s] /usr/bin/ld.gold: dist/build/Control/Concurrent/Chan/Unagi/Internal.dyn_o: previous definition here
[  509s] collect2: error: ld returned 1 exit status
[  509s] `gcc' failed in phase `Linker'. (Exit code: 1)

Any idea to fix it?

Atomic read and write many

It would be straight-forward to add a function like:

readManyChan :: Int -> OutChan a -> IO [a]

that atomically reads n consecutive messages, blocking until all are present. This would be both faster than a replicateM_ n (readChan c) and might be useful if you need to interleave readers that need to take consecutive chunks of n elements for whatever reason.

Please comment if you need this.

No tag fo 0.4.0.0

I see git tags for the previous versions but not for the latest one - it just wasn't pushed?

Why didn't I use a ring buffer for Unagi.Bounded again?

Re. #1

We could store a lap value in each cell (the writers/reader's count shifted right by logBase 2 bounds_size). Both reader and writer need to CAS and possibly block when they've been lapped or fall too far behind. This might only be possible on 64-bit machines where we know we'll never overflow. We might also lose some API functions, I'm not sure.

What happens to two delayed reader threads waiting on the same cell?

Oh, is there a linearizability issue if a writer is descheduled right after incrementing counter, and another writer wraps around and jumps ahead?

“counter is atomic” test fails

Building unagi-chan-0.4.0.0...
Preprocessing library unagi-chan-0.4.0.0...
[ 1 of 14] Compiling Utilities        ( src/Utilities.hs, dist/build/Utilities.o )
[ 2 of 14] Compiling Data.Atomics.Counter.Fat ( src/Data/Atomics/Counter/Fat.hs, dist/build/Data/Atomics/Counter/Fat.o )
[ 3 of 14] Compiling Control.Concurrent.Chan.Unagi.NoBlocking.Types ( src/Control/Concurrent/Chan/Unagi/NoBlocking/Types.hs, dist/build/Control/Concurrent/Chan/Unagi/NoBlocking/Types.o )
[ 4 of 14] Compiling Control.Concurrent.Chan.Unagi.Constants ( src/Control/Concurrent/Chan/Unagi/Constants.hs, dist/build/Control/Concurrent/Chan/Unagi/Constants.o )
[ 5 of 14] Compiling Control.Concurrent.Chan.Unagi.Internal ( src/Control/Concurrent/Chan/Unagi/Internal.hs, dist/build/Control/Concurrent/Chan/Unagi/Internal.o )
[ 6 of 14] Compiling Control.Concurrent.Chan.Unagi.NoBlocking.Internal ( src/Control/Concurrent/Chan/Unagi/NoBlocking/Internal.hs, dist/build/Control/Concurrent/Chan/Unagi/NoBlocking/Internal.o )
[ 7 of 14] Compiling Control.Concurrent.Chan.Unagi.NoBlocking ( src/Control/Concurrent/Chan/Unagi/NoBlocking.hs, dist/build/Control/Concurrent/Chan/Unagi/NoBlocking.o )
[ 8 of 14] Compiling Control.Concurrent.Chan.Unagi.Unboxed.Internal ( src/Control/Concurrent/Chan/Unagi/Unboxed/Internal.hs, dist/build/Control/Concurrent/Chan/Unagi/Unboxed/Internal.o )
[ 9 of 14] Compiling Control.Concurrent.Chan.Unagi.NoBlocking.Unboxed.Internal ( src/Control/Concurrent/Chan/Unagi/NoBlocking/Unboxed/Internal.hs, dist/build/Control/Concurrent/Chan/Unagi/NoBlocking/Unboxed/Internal.o )
[10 of 14] Compiling Control.Concurrent.Chan.Unagi.Unboxed ( src/Control/Concurrent/Chan/Unagi/Unboxed.hs, dist/build/Control/Concurrent/Chan/Unagi/Unboxed.o )
[11 of 14] Compiling Control.Concurrent.Chan.Unagi.NoBlocking.Unboxed ( src/Control/Concurrent/Chan/Unagi/NoBlocking/Unboxed.hs, dist/build/Control/Concurrent/Chan/Unagi/NoBlocking/Unboxed.o )
[12 of 14] Compiling Control.Concurrent.Chan.Unagi.Bounded.Internal ( src/Control/Concurrent/Chan/Unagi/Bounded/Internal.hs, dist/build/Control/Concurrent/Chan/Unagi/Bounded/Internal.o )
[13 of 14] Compiling Control.Concurrent.Chan.Unagi.Bounded ( src/Control/Concurrent/Chan/Unagi/Bounded.hs, dist/build/Control/Concurrent/Chan/Unagi/Bounded.o )
[14 of 14] Compiling Control.Concurrent.Chan.Unagi ( src/Control/Concurrent/Chan/Unagi.hs, dist/build/Control/Concurrent/Chan/Unagi.o )
Preprocessing test suite 'test' for unagi-chan-0.4.0.0...
[ 1 of 26] Compiling Utilities        ( src/Utilities.hs, dist/build/test/test-tmp/Utilities.dyn_o )
[ 2 of 26] Compiling IndexedMVar      ( tests/IndexedMVar.hs, dist/build/test/test-tmp/IndexedMVar.dyn_o )
[ 3 of 26] Compiling Data.Atomics.Counter.Fat ( src/Data/Atomics/Counter/Fat.hs, dist/build/test/test-tmp/Data/Atomics/Counter/Fat.dyn_o )
[ 4 of 26] Compiling Control.Concurrent.Chan.Unagi.NoBlocking.Types ( src/Control/Concurrent/Chan/Unagi/NoBlocking/Types.hs, dist/build/test/test-tmp/Control/Concurrent/Chan/Unagi/NoBlocking/Types.dyn_o )
[ 5 of 26] Compiling Control.Concurrent.Chan.Unagi.Constants ( src/Control/Concurrent/Chan/Unagi/Constants.hs, dist/build/test/test-tmp/Control/Concurrent/Chan/Unagi/Constants.dyn_o )
[ 6 of 26] Compiling Control.Concurrent.Chan.Unagi.Internal ( src/Control/Concurrent/Chan/Unagi/Internal.hs, dist/build/test/test-tmp/Control/Concurrent/Chan/Unagi/Internal.dyn_o )
[ 7 of 26] Compiling Control.Concurrent.Chan.Unagi.NoBlocking.Internal ( src/Control/Concurrent/Chan/Unagi/NoBlocking/Internal.hs, dist/build/test/test-tmp/Control/Concurrent/Chan/Unagi/NoBlocking/Internal.dyn_o )
[ 8 of 26] Compiling Control.Concurrent.Chan.Unagi.NoBlocking ( src/Control/Concurrent/Chan/Unagi/NoBlocking.hs, dist/build/test/test-tmp/Control/Concurrent/Chan/Unagi/NoBlocking.dyn_o )
[ 9 of 26] Compiling UnagiNoBlocking  ( tests/UnagiNoBlocking.hs, dist/build/test/test-tmp/UnagiNoBlocking.dyn_o )
[10 of 26] Compiling Control.Concurrent.Chan.Unagi.Unboxed.Internal ( src/Control/Concurrent/Chan/Unagi/Unboxed/Internal.hs, dist/build/test/test-tmp/Control/Concurrent/Chan/Unagi/Unboxed/Internal.dyn_o )
[11 of 26] Compiling Control.Concurrent.Chan.Unagi.NoBlocking.Unboxed.Internal ( src/Control/Concurrent/Chan/Unagi/NoBlocking/Unboxed/Internal.hs, dist/build/test/test-tmp/Control/Concurrent/Chan/Unagi/NoBlocking/Unboxed/Internal.dyn_o )
[12 of 26] Compiling Control.Concurrent.Chan.Unagi.Unboxed ( src/Control/Concurrent/Chan/Unagi/Unboxed.hs, dist/build/test/test-tmp/Control/Concurrent/Chan/Unagi/Unboxed.dyn_o )
[13 of 26] Compiling Control.Concurrent.Chan.Unagi.NoBlocking.Unboxed ( src/Control/Concurrent/Chan/Unagi/NoBlocking/Unboxed.hs, dist/build/test/test-tmp/Control/Concurrent/Chan/Unagi/NoBlocking/Unboxed.dyn_o )
[14 of 26] Compiling UnagiNoBlockingUnboxed ( tests/UnagiNoBlockingUnboxed.hs, dist/build/test/test-tmp/UnagiNoBlockingUnboxed.dyn_o )
[15 of 26] Compiling UnagiUnboxed     ( tests/UnagiUnboxed.hs, dist/build/test/test-tmp/UnagiUnboxed.dyn_o )
[16 of 26] Compiling Control.Concurrent.Chan.Unagi.Bounded.Internal ( src/Control/Concurrent/Chan/Unagi/Bounded/Internal.hs, dist/build/test/test-tmp/Control/Concurrent/Chan/Unagi/Bounded/Internal.dyn_o )
[17 of 26] Compiling Control.Concurrent.Chan.Unagi.Bounded ( src/Control/Concurrent/Chan/Unagi/Bounded.hs, dist/build/test/test-tmp/Control/Concurrent/Chan/Unagi/Bounded.dyn_o )
[18 of 26] Compiling UnagiBounded     ( tests/UnagiBounded.hs, dist/build/test/test-tmp/UnagiBounded.dyn_o )
[19 of 26] Compiling Control.Concurrent.Chan.Unagi ( src/Control/Concurrent/Chan/Unagi.hs, dist/build/test/test-tmp/Control/Concurrent/Chan/Unagi.dyn_o )
[20 of 26] Compiling Implementations  ( tests/Implementations.hs, dist/build/test/test-tmp/Implementations.dyn_o )
[21 of 26] Compiling Deadlocks        ( tests/Deadlocks.hs, dist/build/test/test-tmp/Deadlocks.dyn_o )
[22 of 26] Compiling DupChan          ( tests/DupChan.hs, dist/build/test/test-tmp/DupChan.dyn_o )
[23 of 26] Compiling Smoke            ( tests/Smoke.hs, dist/build/test/test-tmp/Smoke.dyn_o )

tests/Smoke.hs:175:14: warning: [-Wdeprecations]
    In the use of ‘isEmptyChan’
    (imported from Control.Concurrent.Chan):
    Deprecated: "if you need this operation, use Control.Concurrent.STM.TChan instead.  See <http://ghc.haskell.org/trac/ghc/ticket/4154> for details"
[24 of 26] Compiling Unagi            ( tests/Unagi.hs, dist/build/test/test-tmp/Unagi.dyn_o )
[25 of 26] Compiling Atomics          ( tests/Atomics.hs, dist/build/test/test-tmp/Atomics.dyn_o )
[26 of 26] Compiling Main             ( tests/Main.hs, dist/build/test/test-tmp/Main.dyn_o )
Linking dist/build/test/test ...
running tests
Running 1 test suites...
Test suite test: RUNNING...
Assertions: On
Testing atomic-primops:
    counter smoke test... OK
    counter overflow... OK
    counter is atomic... test: Counter broken: expecting 10000000 got 9999984
CallStack (from HasCallStack):
  error, called at tests/Atomics.hs:150:9 in main:Atomics
Test suite test: FAIL
Test suite logged to: dist/test/unagi-chan-0.4.0.0-test.log
0 of 1 test suites (0 of 1 test cases) passed.
builder for '/nix/store/9df6kxl68z3ij9hdsdis8p5f2l3wfwxd-unagi-chan-0.4.0.0.drv' failed with exit code 1

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.