Line of Sight - Collision test too slow

In my game I got my usual collision handler:

base.cTrav = CollisionTraverser()
elf.collisionHandler = CollisionHandlerQueue()

That’s handling collisions of projectiles with ships. Now when ships attacks they test the line of sight to the target first. I do that via a collision test with a CollisionSegment. That works in general. It was too slow when I hooked it up to said base.cTrav, with FPS somewhere in the <10 range with 4 fighters attacking. So I created a second handler:

self.sightTrav = CollisionTraverser()
		self.sightHandler = CollisionHandlerQueue()

and the code for the line of sight test:

def sightTarget(self, weapname, ID): # weapname - name of weapon (string), ID - ID of firing ship
	if mccodebin.isTurret(weapname):
		origH = self.ShipModel.getH()
		self.ShipModel.lookAt(mcglobals.env.ShipObjects[ID].ShipModel)			
		gunpoint = render.getRelativePoint(self.ShipModel, Point3(0,self.GunDist,0))
		traveldist = mccodebin.getWeapRange(weapname)*1.25
		endpos = render.getRelativePoint(self.ShipModel, Point3(0,traveldist,0))
		source.setH(origH)
	else:
		gunpoint = render.getRelativePoint(self.ShipModel, Point3(0,self.GunDist,0))
		traveldist = mccodebin.getWeapRange(weapname)
		endpos = render.getRelativePoint(self.ShipModel, Point3(0,traveldist,0))
		
	SightCNode = render.attachNewNode(CollisionNode('SightCNode'))
	SightCNode.node().addSolid(CollisionSegment(gunpoint, endpos)) # ! (ax, ay, az, bx, by, bz)
	SightCNode.node().setFromCollideMask(BitMask32(1000))
	SightCNode.node().setIntoCollideMask(BitMask32.allOff())
	SightCNode.setTag("sourceid", str(self.ID))
	SightCNode.node().modifySolid(0).setPointA(gunpoint)
	SightCNode.node().modifySolid(0).setPointB(endpos)
	mcglobals.env.sightTrav.addCollider(SightCNode, mcglobals.env.sightHandler)
#	base.cTrav.addCollider(SightCNode, mcglobals.env.collisionHandler) # !
		
	mcglobals.env.sightTrav.traverse(render)
#	base.cTrav.traverse(render) # !
	SightCNode.removeNode()
	
	if mcglobals.env.sightHandler.getNumEntries() > 0:
#	if mcglobals.env.collisionHandler.getNumEntries() > 0: # !
	### weird. never collided with firing ship's collision node itself,
	### hence no check for it's own ID
		mcglobals.env.sightHandler.sortEntries()
		entry = mcglobals.env.sightHandler.getEntry(0)
#		mcglobals.env.collisionHandler.sortEntries() # !
#		entry = mcglobals.env.collisionHandler.getEntry(0) # !
		fromnode = entry.getFromNodePath()
		fromshipid = int(fromnode.getTag("sourceid"))
		intonode = entry.getIntoNodePath()
		intoshipid = int(intonode.getTag("shipid"))
		if intoshipid == ID:
			return True
		else:
			return False
		#return intoshipid
	else:
		return False

And as I hoped adding things to a different Queue/Traverser did speed things up. But still not enough. How could I further gain FPS? Do I for example have to traverse the whole render? Why can’t I just feed the SightCNode?
Another way would be to not request this every frame (as it is now) but only once a second or whatever. But that would complicate my code I guess, because the sightTarget() function is currently part of the general AI that is calculated every frame.
Switch to CollisionHandlerEvent?

Here’s a screenshot:

EDIT:
I do gain some FPS by adding

mcglobals.env.sightTrav.removeCollider(SightCNode)

before

SightCNode.removeNode()

but we are not there yet.

In my own game I have a time limit, say 0.25 seconds, which I use to determine when a certain character’s vision is “out of date”. I only update the vision of one character per frame, unless a character’s vision gets past double the time limit (0.5 seconds) then I will update that character as well. This helps keep the frame rate smooth since the tests are spread out over many frames.
I store the results in a dictionary so they can be looked up later.
Unless your game is extremely fast paced you should be able to get away with testing 5-10 times per second or even less.