First, know that the std::list is a bad choice for this kind of thing, in particular on reading. The reason is that std::list elements are not guaranteed to be contiguous, make going from element to element very slower because of cache misses (and the lack of predictable memory access behaviour).
I would be you, the first thing I would try would be to replace the std::list by a std::vector, with a call to reserve before starting pushing elements back, to reserve a lot of memory from the start and avoid allocations.
If you use C++11, use the emplace_back() function instead of push_back() to definitively avoid unnecessary copies of the element object.
The vector have a contigous memory which will guarantee fast access on reading the session, and will be more memory efficient because elements are always close: there is no fragmentation of memory.
If that is not enough, consider using something like SQLite. It don't replace in-memory access, but you might use pair of std::array of your records as double buffer in which you put the next batch of records to read that you extract progressively from the sqlite file. To write, just do inserts. Both reading and writing can be done in a separate thread while your application continues running or is processing the records in replay.
The reason this setup might help is that it would make any size of session not (or almost not) impact the application that plays it, because in memory there would be only a part of the whole session readable, making runtime not grow on memory, making things fast. In this case you'll be limited only by the speed access to the disk, which is why I suggest using a (concurrently) double buffer reading of the records. Anyway sqlite is made to be very fast.