1

I don't have enough experience to understand how hard object instantiation and garbage collection really hit. So I tend to write code where I don't just spin up objects for the sake of it. However, now, where I work, hexagonal design is non negotiable, and at face value, I don't mind. It makes life rather early.

public whatever controller(External message) {
    var command = mapper.toCommand(message);
    var responseEntity = service.doStuff(command);
    return mapper.toMessage(responseEntity);
}

@LombokStuff
@SpringStuff
public ResponseEntity doStuff(DomainCommand command) {
    DomainAggregate aggr = repo.getRootAggr(command);
    // inject ports into aggregate here
    return aggr.doStuff();
}

This way you have your controller level that talks with external messages. Your service that does spring stuff. And your domain that only knows about the domain. Plus the ports, that also only speak the domain language.

Domain has no spring, no external communication, no knowledge of the DB. It just calls ports. Interfaces.

In our case we have commands (value objects for external messages), and domain objects.

Then you also have your ports, where you write an interface that only accepts and returns domain objects, but internally, it uses, let's say JPAs for a Postgres.

A full call looks like this

  • inbound message
  • create command object
  • query db for root aggregate
  • create JPA representation
  • create domain entity from said JPA
  • apply domain logic
  • create another JPA to save your domain object
  • create another domain object as a response
  • create a message object from your domain object to communicate externally

A trivial call generates at least this

  • 2 message objects
  • 1 command object
  • 2 JPAs
  • 1 Domain Object

Isn't this a huge performance hit? Because IRL, you'll probably have a root object with 10 other objects inside. Each message object and JPA object is just instantiating objects over objects.

I get it, it's clean, good separation of concerns, easy to migrate to new technologies. But the cost. How high is it?

3
  • Unless you are in seriously high performance 50-100 objects is trivial. Hotspot can handle 100s of thousands of objects per request without issue. Commented Apr 17, 2023 at 19:09
  • If you want to qualify it, roughly 500 cycles per live object per GC collection is a rough conservative estimate. For objects that live less than a GC collection period, the only real cost is in reducing the time between collections. Commented Apr 17, 2023 at 19:18
  • 1
    "Isn't this a huge performance hit?" What is this assertion based on? If I tell you have I have to carry 15 foppalops upstairs, and you respond "isn't that really difficult?", that statement inherently reveals what you think about the size or weight of a foppalop, i.e. that you don't think trivial like e.g. a grain of rice would be. So in the same vein, what leads you to state that 6 objects are a huge performance hit and not just the analogous grains of rice?
    – Flater
    Commented Apr 18, 2023 at 3:21

1 Answer 1

3

The cost of instantiating objects and performing garbage collection is low in modern programming languages and environments (particularly in the JVM, that is your concern). Additionally, there are often ways to optimize performance within the hexagonal architecture paradigm, such as using object pooling to reuse existing objects instead of constantly instantiating new ones.

Having said this, I would generally advise against premature optimization and recommend dealing with any performance issues if/when they arise. An exception to this is if you have specific performance requirements to abide by.

2
  • 2
    It's worth noting that in a non-realtime workloads, object pooling can often result in worse performance due to the cost of objects that are unused but technically alive on the GC combined with management overhead. (And reduced cache locality) Commented Apr 17, 2023 at 19:36
  • Perhaps a better but less general example is the struct of array pattern. Especially with its lack of composite value types, the struct of array pattern can significantly reduce the number of object allocations required at the cost of object encapsulation. Commented Apr 17, 2023 at 19:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.