Creating a texture has multiple stages:
1. Loading from file (you're using Image for that in a worker thread)
2. Creating the internal GPU API handle/resource. This could cause a mini-stutter (that can add up). If the texture is a power of 2, it will be placed in a texture array. So if the texture array had already been created and has free available space, then this cost won't be paid.
3. Some preprocessing stuff. In certain cases Image::generateMipmaps or PixelUtil::convertForNormalMapping may end up getting called while inside HlmsTextureManager::createOrRetrieve. If you want to avoid stutter, make sure these are not getting called (i.e. mipmaps were already set, and format was already ideal for normal mapping).
4. Uploading from Image to the GPU RAM. This could take time (not much, but adds up).
5. Sometimes a shader needs to be recompiled. If it's cached, it's not a problem, but if it's new, it will add stutter. To minimize this issue if textures are loaded in the same order every time, it will maximize the cache efficiency (so that they always arrive in the same pool of texture arrays); if you can't do this, then it's just a matter of time until the cache has seen all variants.
There's little you can do for point 2, however you should monitor your
texture batching efficiency.
You can do a lot for step 3.
There's not much you can do for step 4 (in Ogre 2.2 this also happens in a background thread, but in 2.1 it happens in the main thread)
As for step 5, that depends on your design.
If you're using D3D11, another issue that causes stutter is that texture uploads call 3D11RenderSystem::_clearStateAndFlushCommandBuffer because on NVIDIA drivers it is prone to OoM (Out of Memory situations), particularly 32-bit builds. But if you remove that call and it still works fine for you on NVIDIA cards, then you may see a boost in texture loading time.
Cheers
Matias