Improve performance in FlacTagWriter.write

Issue #15 wontfix
IJabz repo owner created an issue

From https://java.net/jira/browse/JAUDIOTAGGER-465

I've been taking a look at improving performance of FlacTagWriter.write() . I found that, instead of continually writing to rafTemp, if I wrote to a List<Byte> and then wrote in one call to rafTemp, that halved the time it took to write the file.

Example (I can't seem to attach anymore):

//Jump over Id3 (if exists) Flac and StreamInfoBlock raf.seek(flacStream.getStartOfFlacInFile() + FlacStreamReader.FLAC_STREAM_IDENTIFIER_LENGTH);

        final List<Byte> bytes = new ArrayList<Byte>();
        //Write StreamInfo, we always write this first even if wasn't first in original spec
        addToByteList(bytes, blockInfo.streamInfoBlock.getHeader().getBytesWithoutIsLastBlockFlag());
        addToByteList(bytes, blockInfo.streamInfoBlock.getData().getBytes());

        //Write Application Blocks
        for (MetadataBlock aMetadataBlockApplication : blockInfo.metadataBlockApplication)
        {
            addToByteList(bytes, aMetadataBlockApplication.getHeader().getBytesWithoutIsLastBlockFlag());
            addToByteList(bytes, aMetadataBlockApplication.getData().getBytes());
        }

        //Write Seek Table Blocks
        for (MetadataBlock aMetadataBlockSeekTable : blockInfo.metadataBlockSeekTable)
        {
            addToByteList(bytes, aMetadataBlockSeekTable.getHeader().getBytesWithoutIsLastBlockFlag());
            addToByteList(bytes, aMetadataBlockSeekTable.getData().getBytes());
        }

        //Write Cue sheet Blocks
        for (MetadataBlock aMetadataBlockCueSheet : blockInfo.metadataBlockCueSheet)
        {
            addToByteList(bytes, aMetadataBlockCueSheet.getHeader().getBytesWithoutIsLastBlockFlag());
            addToByteList(bytes, aMetadataBlockCueSheet.getData().getBytes());
        }

        //Write tag (and padding)
        raf.write(toByteArray(bytes));
        raf.getChannel().write(tc.convert(tag, availableRoom - neededRoom));

private static void addToByteList(List<Byte> list, byte[] byteArray) { for (byte b : byteArray) list.add(b); }

private static byte[] toByteArray(List<Byte> list) {
    byte[] ret = new byte[list.size()];
    for(int i = 0;i < ret.length;i++) ret[i] = list.get(i);
    return ret;
}

Tell me about it. AFAIAA the only thing you can do is pre-initialise the size of the List/array. Limitation of the core Java API... but at least this is occurring in memory rather than in writes to disk.

Could benchmark using Arrays.asList and addAll() and compare I suppose...

Or the MetadataBlock API could be changed.

p.s. I also wondered whether those methods should be moved to your Utils classes.

Comments (1)

  1. IJabz reporter

    This is a bit out of date now since I have now moved FlacWriter to AudioFileReader2 using FileChannels and ByteBuffers instead of RandomAccessFile and byte arrays. But I have identifiedf a way to improve performance of flac writing and will create a new issue.

  2. Log in to comment