CharBuffer по сравнению с символом []

26
задан Daniel Rikowski 10 January 2011 в 17:00
поделиться

7 ответов

Нет, нет действительно никакой причины предпочесть CharBuffer в этом случае.

В целом, тем не менее, CharBufferByteBuffer) может действительно упростить API и поощрить корректную обработку. При разработке общедоступного API это определенно достойно рассмотрения ориентированный на буфер API.

17
ответ дан erickson 28 November 2019 в 07:37
поделиться

Я хотел мини-сравнить этого сравнения.

Ниже класс, который я записал.

вещь, я не могу полагать что CharBuffer, выполненный так плохо. Что я понял превратно?

РЕДАКТИРОВАНИЕ: Начиная с 11-го комментария ниже я отредактировал код и выходное время, лучшая производительность повсюду вокруг, но все еще значительная разница во времена. Я также попробовал out2.append ((CharBuffer)buff.flip ()) опция, упомянутая в комментариях, но это было намного медленнее, чем опция записи, используемая в коде ниже.

Результаты: (время в мс)
символ []: 3411
CharBuffer: 5653

public class CharBufferScratchBox
{
    public static void main(String[] args) throws Exception
    {
        // Some Setup Stuff
        String smallString =
                "1111111111222222222233333333334444444444555555555566666666667777777777888888888899999999990000000000";

        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < 1000; i++)
        {
            stringBuilder.append(smallString);
        }
        String string = stringBuilder.toString();
        int DEFAULT_BUFFER_SIZE = 1000;
        int ITTERATIONS = 10000;

        // char[]
        StringReader in1 = null;
        StringWriter out1 = null;
        Date start = new Date();
        for (int i = 0; i < ITTERATIONS; i++)
        {
            in1 = new StringReader(string);
            out1 = new StringWriter(string.length());

            char[] buf = new char[DEFAULT_BUFFER_SIZE];
            int n;
            while ((n = in1.read(buf)) >= 0)
            {
                out1.write(
                        buf,
                        0,
                        n);
            }
        }
        Date done = new Date();
        System.out.println("char[]    : " + (done.getTime() - start.getTime()));

        // CharBuffer
        StringReader in2 = null;
        StringWriter out2 = null;
        start = new Date();
        CharBuffer buff = CharBuffer.allocate(DEFAULT_BUFFER_SIZE);
        for (int i = 0; i < ITTERATIONS; i++)
        {
            in2 = new StringReader(string);
            out2 = new StringWriter(string.length());
            int n;
            while ((n = in2.read(buff)) >= 0)
            {
                out2.write(
                        buff.array(),
                        0,
                        n);
                buff.clear();
            }
        }
        done = new Date();
        System.out.println("CharBuffer: " + (done.getTime() - start.getTime()));
    }
}
7
ответ дан Ron Tuffin 28 November 2019 в 07:37
поделиться

Если это - единственная вещь, Вы делаете с буфером, то массив является, вероятно, лучшим выбором в этом экземпляре.

CharBuffer имеет много дополнительного хрома на нем, но ни один из него не релевантен в этом случае - и только замедлит вещи вниз часть.

можно всегда осуществить рефакторинг позже, если необходимо сделать вещи более сложными.

4
ответ дан Bill Michell 28 November 2019 в 07:37
поделиться

Различие, на практике, на самом деле < 10%, не 30%, поскольку другие сообщают.

, Чтобы читать и записать файлу 24 5 МБ времена, мои числа, взятые с помощью Профилировщика. Они были в среднем:

char[] = 4139 ms
CharBuffer = 4466 ms
ByteBuffer = 938 (direct) ms

Отдельные тесты пару раз способствовали CharBuffer.

я также пытался заменить Основанный на файле IO IO В оперативной памяти, и производительность была подобна. При попытке передать от одного собственного потока до другого, то Вы - более обеспеченное использование "прямого" ByteBuffer.

меньше чем с 10%-м различием в производительности, на практике, я одобрил бы CharBuffer. Это - синтаксис, более ясно, существуют менее посторонние переменные, и можно сделать более непосредственное управление на нем (т.е. что-либо, что просит CharSequence).

Сравнительный тест ниже..., это немного неправильно, поскольку BufferedReader выделяется в методе тестирования, а не снаружи... однако, пример ниже позволяет Вам изолировать время IO и устранять факторы как строка или поток байтов, изменяющий размеры его буфера внутренней памяти, и т.д.

public static void main(String[] args) throws Exception {
    File f = getBytes(5000000);
    System.out.println(f.getAbsolutePath());
    try {
        System.gc();
        List<Main> impls = new java.util.ArrayList<Main>();
        impls.add(new CharArrayImpl());
        //impls.add(new CharArrayNoBuffImpl());
        impls.add(new CharBufferImpl());
        //impls.add(new CharBufferNoBuffImpl());
        impls.add(new ByteBufferDirectImpl());
        //impls.add(new CharBufferDirectImpl());
        for (int i = 0; i < 25; i++) {
            for (Main impl : impls) {
                test(f, impl);
            }
            System.out.println("-----");
            if(i==0)
                continue; //reset profiler
        }
        System.gc();
        System.out.println("Finished");
        return;
    } finally {
        f.delete();
    }
}
static int BUFFER_SIZE = 1000;

static File getBytes(int size) throws IOException {
    File f = File.createTempFile("input", ".txt");
    FileWriter writer = new FileWriter(f);
    Random r = new Random();
    for (int i = 0; i < size; i++) {
        writer.write(Integer.toString(5));
    }
    writer.close();
    return f;
}

static void test(File f, Main impl) throws IOException {
    InputStream in = new FileInputStream(f);
    File fout = File.createTempFile("output", ".txt");
    try {
        OutputStream out = new FileOutputStream(fout, false);
        try {
            long start = System.currentTimeMillis();
            impl.runTest(in, out);
            long end = System.currentTimeMillis();
            System.out.println(impl.getClass().getName() + " = " + (end - start) + "ms");
        } finally {
            out.close();
        }
    } finally {
        fout.delete();
        in.close();
    }
}

public abstract void runTest(InputStream ins, OutputStream outs) throws IOException;

public static class CharArrayImpl extends Main {

    char[] buff = new char[BUFFER_SIZE];

    public void runTest(InputStream ins, OutputStream outs) throws IOException {
        Reader in = new BufferedReader(new InputStreamReader(ins));
        Writer out = new BufferedWriter(new OutputStreamWriter(outs));
        int n;
        while ((n = in.read(buff)) >= 0) {
            out.write(buff, 0, n);
        }
    }
}

public static class CharBufferImpl extends Main {

    CharBuffer buff = CharBuffer.allocate(BUFFER_SIZE);

    public void runTest(InputStream ins, OutputStream outs) throws IOException {
        Reader in = new BufferedReader(new InputStreamReader(ins));
        Writer out = new BufferedWriter(new OutputStreamWriter(outs));
        int n;
        while ((n = in.read(buff)) >= 0) {
            buff.flip();
            out.append(buff);
            buff.clear();
        }
    }
}

public static class ByteBufferDirectImpl extends Main {

    ByteBuffer buff = ByteBuffer.allocateDirect(BUFFER_SIZE * 2);

    public void runTest(InputStream ins, OutputStream outs) throws IOException {
        ReadableByteChannel in = Channels.newChannel(ins);
        WritableByteChannel out = Channels.newChannel(outs);
        int n;
        while ((n = in.read(buff)) >= 0) {
            buff.flip();
            out.write(buff);
            buff.clear();
        }
    }
}
3
ответ дан James Schek 28 November 2019 в 07:37
поделиться

Я думаю, что CharBuffer и ByteBuffer (а также любой другой xBuffer) были предназначены для возможности многократного использования, таким образом, Вы можете buf.clear () их вместо того, чтобы пройти перераспределение каждый раз

, Если Вы не снова используете их, Вы не используете их полный потенциал, и это добавит дополнительные издержки. Однако, если Вы - планирование масштабирования этой функции, это могло бы быть хорошей идеей сохранить их там

2
ответ дан Eric 28 November 2019 в 07:37
поделиться

Версия CharBuffer немного менее сложна (один меньше переменной), инкапсулирует обработку размера буфера и использует стандартный API. Обычно я предпочитал бы это.

Однако существует все еще одно серьезное основание предпочесть версию массива, в некоторых случаях по крайней мере. CharBuffer был только представлен в Java 1.4 поэтому, если Вы развертываетесь к более ранней версии, Вы не можете использование Charbuffer (если Вы role-your-own/use бэкпорт).

P.S., Если Вы используете бэкпорт, не забывают удалять его, как только Вы ловите до версии, содержащей "реальный" версия бэкпортированного кода.

1
ответ дан Michael Rutherfurd 28 November 2019 в 07:37
поделиться

Необходимо избежать CharBuffer в недавних версиях Java, существует ошибка в #subsequence(). Вы не можете получить подпоследовательность от второй половины буфера, так как реализация путает capacity и remaining. Я наблюдал ошибку в Java 6-0-11 и 6-0-12.

1
ответ дан akuhn 28 November 2019 в 07:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: