Loading textures using PBOs - best strategies


I’ve been experimenting a bit with loading textures via PBOs and I’m a bit confused as to what’s most reasonable approach here.

What I’m doing at the moment - every time there’s request to copy data into texture mip level - is:
(1) get PBO from pool and map it
(2) copy data into PBO mapped memory (on a separate thread)
(3) unmap PBO and return it to pool

The above steps are nothing very interesting. What’s interesting is what happens when you get PBO from the pool or when you return it to pool. What I’m doing now is whenever there’s request for PBO of given “requested-size”, I check if there’s already PBO of roughly matching size in a pool (size <= “requested-size” AND “requested-size” <= size * 2). If found, that’s what I’m using. If not, I’m creating new PBO. If some fixed memory limit for all PBOs (let’s say 128 MB) is exceeded, I’m destroying unused PBOs in the pool to free up some memory (selecting PBOs using Least-Recently-Used order to minimize blocking - hence some of these PBOs may still await processing on GPU and thus will block).

Does the above make sense at all?
In particular, should I care so much about minimizing number of PBO creation / resizing operations (i.e. calls to glBufferData())? In other words - is there significant cost associated with PBO creation?
Or would it be better - every time I need PBO - to create new PBO of exact matching data size?
Is there better ways to manage PBO pools or some GPU specific considerations?