I did these with nodes only - a few procedural brick textures for brick texture control and coordinate control, as well as some noises to break up straightness, brick mortar widths and smoothness, some bump nodes, and a big single image lookup texture for lookup.
Effect is greatly exaggerated in the latter one.
I don’t think I added any low frequency bump as your slab looks quite flat.
Unfortunately it gets really messy really fast wrt node complexity:
but at least it is faster than microdisplacement. For large surface coverage adaptive microdisplacement is waaaaay to costly for me (like 40-60 GB memory for a simple scene).
For static displacement you should only add geometry where it is needed. Like manually subdivide several times along the edges, and leave a lot coarser detail toward the middle. But yeah, I tend to avoid it if I can.
The problem with complex nodes is the shader build times.