Unorganized notes which might be useful during development.
These are the "regular" versions, e.g., 0.4.0 or 0.4.0-RC1.
- Commit every change.
- Make sure there are no untracked files in git.
- Push any new commits.
- Wait for CI to become green.
- Tag the release (e.g.,
git tag -s "v1.2.3"), but don't push the new tag. - Start
sbt, and:clean;staticAnalysis;++3.3.7;staticAnalysis(precompile seems to help publish faster)exit
- In a new
sbtshell:release(this step requires Sonatype credentials)
- If everything looks right, push the new tag (
git push --tags). - Create a "release" on github for the new tag.
These are "preview" versions, e.g., 0.4-39d987a or 0.4.3-2-39d987a.
- Commit every change.
- Make sure there are no untracked files in git.
- Push any new commits.
- In
sbt, callreleaseHash(requires Sonatype credentials).
A warning like this appears when running tests in stressLinchk:
OpenJDK 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended
According to https://stackoverflow.com/a/57957031, this is harmless.
Some types of exceptions must never be thrown, because they are (probably) undefined behavior on Scala.js:
ArrayIndexOutOfBoundsExceptionandStringIndexOutOfBoundsException: useIndexOutOfBoundsExceptioninstead. Indexing into an array (or string, though that's not typical) must check the index; seejsCheckIdx, which is a NOP in Scala, but checks the index (and throws if necessary) in Scala.js.NegativeArraySizeException: when allocating an array, care must be taken, so the length is non-negative; if it is, throw anAssertionErrorinstead.
The following types of exceptions are allowed, even though they are similarly UB in Scala.js.
(Nevertheless, they should not be thrown directly, as throw new ....) The users are recommended
to use the corresponding Scala.js linker settings, or otherwise avoid the situations which can
lead to these exceptions.
NullPointerException: users are directed to never passnullto library methods, or use theCompliantScala.js linker setting (nullas a payload is allowed). See the [README.md].
Further reading: https://www.scala-js.org/doc/semantics.html#undefined-behaviors
Older versions used to have (sometimes significantly) different API and internals. Some of the decisions to change them are documented here.
- The
choam-mcasmodule used to be public, and the MCAS algorithm was configurable. Now it is private, as (primarily due to the changes necessary to support opacity) it is not anymore a simple and clean MCAS library, but somewhat intertwined with higher-level (Rxn) concerns. The algorithm is not selectable now, as EMCAS is clearly the fastest (of the ones we tried). In fact, CASN was removed (SpinLockMcasremains, because it is so simple, that it's not a burden to maintain it, and might be useful for testing). Rxnused to have two type parameters (i.e.,Rxn[-A, +B]), and it formed an arrow (more specifically an ArrowChoice), besides forming a monad in its second type parameter. This was "inherited" from the Reagents paper. It was interesting, and sometimes useful, but rarely used in practice. In theory, using a static structure ofRxns combined with the arrow combinators could have a better performance than using monadic composition (which typically needs to allocate always newRxninstances). In practice though, benchmarking showed that these performance wins are very small in semi-realistic situations (typically 2-3%), and it is somewhat non-intuitive whether it's even worth using arrow combinators instead of the monadic ones (in some very similar situations the arrow ones are slower). Moreover, for performance optimization the "unsafe API" (dev.tauri.choam.unsafe) proved much more effective (10-15% performance improvement in the same situations). For this reason (and to simplify the API and implementation), the input type parameter ofRxnwas removed. (Note, that it still forms a monad.)
- EMCAS used to employ an IBR (interval-based reclamation) scheme to determine if a
descriptor is still in use by a helper. This was replaced by using the JVM GC for
this purpose (by using weakrefs). This solution proved to be faster (although it
was necessary to "reuse" weakrefs to avoid having too much of them, because that
slows down the GC; see
getReusableMarker/getReusableWeakRef). - The
Rxninterpreter used tomatchonInttags (JVMtableswitch). This was inspired by an old optimization in the Scala compiler for matching on sealed subclasses (see https://github.com/scala/scala/commit/b98eb1d74141a4159539d373e6216e799d6b6dcd). The Cats Effect runloop is doing something very similar, and ZIO also used to do something like this in version 1. This was removed fromRxn, and now it's a simplematchon asealedtype. This way it's easier to maintain (e.g., we get non-exhaustive match warnings), and some benchmarking showed that it might even be slightly faster this way. - An even older version of
Rxnwas based on calling continuations recursively (like in https://github.com/aturon/ChemistrySet). That was not stack-safe, so it was changed to a stack-safe interpreter. Refs used to have a 256-bit ID (4longs generated byThreadLocalRandom) out of fear of collisions (which would be catastrophic). Now they are generated deterministically (but pseudorandomly), so 64 bits (along) should be enough (seeṘefIdGen).
dev.tauri.choam.stats- enable/disable performance stats collection (available through JMX)
- specify a
Boolean(default:false)
dev.tauri.choam.internal.mcas.impl- override the MCAS impl
- specify the name of an
Mcasclass, e.g.,"Emcas"(default:"")