I need to process the data contained in a (relatively) large binary file.

The file has the following structure:

```
40 bytes of initialization,
4 bytes, 1 byte,
4 bytes, 1 byte,
...
lots of such 5-byte blocks
...

```

The number of 5-byte blocks (to which I'll refer to as 'timetags' in the following) may vary, but the total size of the file can be in the order of ~100 MBs.

In each 5-byte block the first 4 bytes encode a `uint32_t` (unsigned integer) 'timestamp', and the fifth byte is a number encoding a 'channel'.

My task is to find out whether there are contiguous sequences of 4 timetags, such that the corresponding timestamps are within a certain time window from each other, and if that is the case store the corresponding channels.

For example, if there is a sequence of timetags whose decoded data is

```
100, 2
300, 4
310, 5
340, 8,
369, 6,
413, 8

```

and my time window is `100`, then I store the list `[4,5,8,6]`.

In general the number of such fourfold coincidences will be extremely small with respect to the total number of timetags (e.g. for a ~100MB file I have ~10 such coincidences).
Also, the timestamps are generally in increasing order, but sometimes there is a sudden jump (when the timestamps becomes too big for the 4 bytes to encode) and the count starts over, and this has to be taken into account (see below for an example file).

I tried a variety of things to do this, but the best I achieved is a ~20s time to process a ~50MB file.
However, implementing the same code in C, I get a performance of ~0.2s for a ~100MB file.
While I understand that a C program is naturally faster than a python one, such a big performance gap really seems strange to me, so there must be something wrong with my python code.

[Here](https://dl.dropboxusercontent.com/u/110376555/timetags5byteShort.bin) is an example of the binary file to process (this is a reduced version of ~1MB).
It contains a single fourfold coincidence at the last four timetags.

Here is my best implementation:

```
#!/usr/bin/python3
import struct
import os

# ============ CONSTANTS TO (OPTIONALLY) SET =============
WINDOW_SIZE = 100
INPUT_FILE_NAME = 'datafile.bin'

with open(INPUT_FILE_NAME, 'rb') as input_file:

    # number of bytes found in every file produced when writing the binary file
    initial_offset = 40
    # number of bytes occupied by each timetag
    timetag_size = 5

    # each timetag is stored in 5 bytes. The first 4 bytes contain the
    # timestamp, with the first byte being the least significant one, and last
    # byte the most significant one

    # bytes_to_timestamp expects in input a list of 4 bytes encoding a
    # timestamp. The first byte is the least significant one.
    def bytes_to_timestamp(bytes):
        return(struct.unpack("L", bytes)[0])

    # timestamps_in_window expects two 4-byte inputs, and returns whether the
    # second one should be considered in coincidence with the first one
    def timestamps_in_window(triggering_timestamp_bytes, new_timestamp_bytes):
        return(
                0 <
                bytes_to_timestamp(new_timestamp_bytes) -
                bytes_to_timestamp(triggering_timestamp_bytes)
                < WINDOW_SIZE
            )

    file_size = os.path.getsize(INPUT_FILE_NAME)
    effective_file_size = file_size - initial_offset - file_size % timetag_size

    input_file.seek(initial_offset)
    data = input_file.read(effective_file_size)

    output_channels = []
    triggering_timestamp = data[0:4]
    channels = [data[4]]
    for timetag_idx in range(effective_file_size // timetag_size - 1):
        current_byte = (timetag_idx + 1)*timetag_size
        current_timestamp = data[current_byte:current_byte+4]
        current_channel = data[current_byte + 4]
        if timestamps_in_window(triggering_timestamp, current_timestamp):
            channels.append(current_channel)
        else:
            if len(channels) == 4:
                print('found a fourfold coincidence at ', end = '')
                for channel in channels:
                    print('{0: >5}'.format(channel), end = '')
                print('')
                output_channels.append(channels)
            channels = [current_channel]
            triggering_timestamp = current_timestamp
    if len(channels) == 4:
        print('found a fourfold coincidence at ', end = '')
        for channel in channels:
            print('{0: >5}'.format(channel), end = '')
        print('')
        output_channels.append(channels)

```

I also tried to implement this with `numpy.fromfile`, but I ended up with a **much** slower code, which you can check out in [this GitHub Gist](https://gist.github.com/glS512/3dd2cfcb1357b92f3703).

How can I make the code more efficient?