You could use a Forward+ renderer and cull lights in a compute shader to get a list of lights for each screen-space tile.
Sounds good, but i'm planning to support openGL 3.3, which doesn't support compute shaders.
Either way, I found the reason it is acting so slow. I'm iterating over an std::vector<boost::weak_ptr<RenderingComponent>>, and locking each one for every light for checking for collision detection. I'm gonna have to move away from shared ptrs since they are too slow, however I am having difficulty finding a way to iterate through all rendering components without knowing if they are dead or not.
I may try using a memory pool of rendering component ptrs and update every frame, checking each game object to see if it has a rendering component in it's component map, but idk, probs won't be as slow as locking weak ptrs, but still sounds slow.. I didn't think this issue would pop up again.