Skip to content
Daniel Molinero edited this page Feb 1, 2019 · 21 revisions

How does Toothpick perform compared to Dagger 2 ?

We provide a full benchmark of DI librairies, detailed in great length.

Can I dump the Toothpick tree ?

Yes, just call rootScope.toString() and print it.

What version of Java is supported ?

JDK 7+

Is Toothpick compatible with Kotlin?

Yes, it is! Simply use kapt instead of apt.

Can I inject generics like in Guice / Dagger

No, Toothpick only allows to inject classes and interfaces.

Will Toothpick soon support advanced DI techniques like assisted injections, sets, etc, etc, etc. ?

Probably not. Toothpick has been designed to remain simple. Simple to code, simple to maintain, simple to use. And we largely favor this over any feature. But, hey, it's an OSS project, take it where you want..

Why creating Toothpick ?

Since the inception of the JSR 330 by Crazy Bob & al, many DI libraries were created. We start the history of Toothpick were we saw it started from our point of view : on Android.

Mike Burton created RoboGuice in August 2009. At that time, the early days of Android, it was just great to enjoy Dependency Injection on Android. Though, the library had several problems that became more and more important as Android development was getting more and more mature:

  • Guice is slow, at least it didn't match any more the expected performance of Android apps.
  • Guice 4 uses guava which contains tens of thousands of methods that contribute to multidex issues and heavy apks
  • Guice uses reflection and reflection is especially slow on Android. Mostly because there is no JIT of reflection code as opposed to PC JVMs.
  • Guice stack traces are horrible to debug.
  • RoboGuice's scope was large, and made the library more difficult to maintain. It was doing DI, view injection, events, etc. And not all features were as great as others (especially events).

Jesse Wilson has created Dagger 1 in June 2012. Dagger bore radical change to DI : Guice and all other DI framework where doing a lot of things at runtime, Dagger does most of DI at compile time. In Dagger, reflection is fully replaced by annotation processing (an old idea of crazy bob).

Dagger 1 is a great progress conceptually for DI. But it also comes with a price tag:

  • dagger syntax is a bit bloated with annotations, java syntax is twisted to express what dagger requires to work. It's definitely harder than Guice to use
  • taking care of the injection tree at compile time requires a lot of efforts from developers
  • dagger syntax requires quite some boiler plate, we tend to forget it but it's not intuitive to write something like
@Provides @Singleton Heater provideHeater() {
    return new ElectricHeater();
  }

Developers do all the work even the simplest dependency creation.

Nevertheless, DI performances of Dagger 1 were far, far ahead of any other DI library.

Dagger 2 pushes Dagger 1 approach even further. It is a joint effort of many developers to make DI even faster, and to generate code that is easier to trace. Dagger 2 also makes the notion of scope much sharper than Dagger 1. But Dagger 2 also comes with a price to pay:

  • DI graph is completely static and there is no support for using it for testing, which is one of the main motivation behind DI.
  • Dagger 2 requires as much boiler plate
  • Dagger 2 introduces the notion of component which is new from a JSR 330 perspective
  • Dagger 2 forces to use constructor injection for dependencies, methods injection is more or less supported, a few things are strange like the middle-man component pass over trick.

On our side, we have been maintaining RoboGuice, trying to make it faster, understand exactly what was making it slow. We loved the simplicity and clarity of Guice, and wanted to keep it. And we made great progress:

  • RG 3 uses annotation processing and performed 35 % faster than RG 2
  • RG 4 uses even more optimisations and performed again 35% faster than RG 3

We have also investigated other techniques like byte code weaving, AST manipulations, etc. to make Guice faster. Though annotation processing helped, it has proved to be hard to change Guice, and we could only fork it, none of our PRs were accepted to make Guice faster. We perfectly understand this, Guice has its niche in DI where advanced features are required, and Dagger is there for the full speed use case.

So, we ended up creating Toothpick. And we like it a lot and are happy to publish it as an Open Source project:

  • Toothpick is fast, not as fast as Dagger 1 & 2 with large number of injections because it's runtime based, but much faster than Guice / RoboGuice. And even faster than the daggers in some cases.
  • Toothpick uses reflection in a minimal way. Exactly in the same way as butterknife or Dagger. Reflection is only used to load classes that is not very impacting on the Android JVM.
  • Toothpick aims to be as simple as Guice, it's syntax is a charm, it has few rules.
  • Toothpick exposes scopes clearly, which makes it very powerful at a conceptual level. It is very well suited to work with context aware frameworks like web frameworks or android,
  • Toothpick scopes make it easier to use advanced programming techniques like MVP on Android, or a set of shared objects in scopes that span over multiple activities,
  • Toothpick is thread safe and locks as little and as lately as possible,
  • Toothpick offers android support via Smoothie,
  • Toothpick offers advanced testing support via toothpick-testing
  • Toothpick stack traces are clear and simple. Generated code is simple too.

And yes, migrating an app that used RoboGuice to ToothPick is not that hard compared to switching to Dagger.

However, Toothpick is not a 'RoboGuice 5', or as much as it is a 'dagger 3'. We wanted to take the most interesting features of both and make a different compromise than Daggers. We wanted more simplicity, less boiler plate and more testing support, and a decent to fast speed.

Toothpick is the result of an odyssey of 3 years around dependency injection, it was initiated by Stephane Nicolas and Daniel Molinero Reguera, the version 1.0.0 was coded in 6 weeks, starting March 27th 2016, tests & docs included, with a port of a 35 K LOC app to test it. Thx to all who supported this effort, and for enduring so many DI talks :)

Where does the name Toothpick come from ?

Toothpick & smoothie are puns in different ways:

  • a toothpick is sharper than a dagger, and yes, we also find the name funny :)
  • Toothpick is definitely less square than dagger 2, see its simpler rules and concepts
  • it is made of wood, trees are made of wood, toothpick main feature is its scope tree
  • Toothpick exposes 2 dags (scope tree and injection graph), it is a dag square
  • Smoothie is the best of Guice, RoboGuice and Blender (the annotation processor of RoboGuice).
Clone this wiki locally