【问题标题】:Which one performance better when I use jedis , set(byte[], byte[]) or set(String, String)?当我使用 jedis 、 set(byte[], byte[]) 或 set(String, String) 时,哪一项性能更好?
【发布时间】:2013-05-20 08:06:03
【问题描述】:

在我的笔记本电脑上,直接设置String 总是比设置byte[] 更好,即使在我使用Jedis 测试时使用Serialization mechanism。我很困惑,如果在调用 jedis set(String, String) 时应该序列化 String?如果Serialization mechanism 发生了,这不是我在下面SerializeUtil 中写的默认机制吗? 我的代码如下:

   public void testRedis() {

        long startTime = System.currentTimeMillis();
        for (int i = 0; i < count; i++) {
            StringBuilder sb = new StringBuilder(str);
            sb.append(i);
            jedis.set(sb.toString(), value);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("default: " + (endTime - startTime));

        startTime = System.currentTimeMillis();
        for (int i = 0; i < count; i++) {
            StringBuilder sb = new StringBuilder(str);
            sb.append(i);
            jedis.set(sb.toString().getBytes(), value.getBytes());
        }
        endTime = System.currentTimeMillis();
        System.out.println("byte: " + (endTime - startTime));

        startTime = System.currentTimeMillis();
        for (int i = 0; i < count; i++) {
            StringBuilder sb = new StringBuilder(str);
            sb.append(i);
            jedis.set(SerializeUtil.serDefaultString(sb.toString()), SerializeUtil.serDefaultString(value));
        }
        endTime = System.currentTimeMillis();
        System.out.println("default ser: " + (endTime - startTime));

        startTime = System.currentTimeMillis();
        for (int i = 0; i < count; i++) {
            StringBuilder sb = new StringBuilder(str);
            sb.append(i);
            jedis.set(SerializeUtil.serUTFString(sb.toString()), SerializeUtil.serUTFString(value));
        }
        endTime = System.currentTimeMillis();
        System.out.println("utf ser: " + (endTime - startTime));
    }

也许需要SerializeUtil

public static byte[] serDefaultString(String data) {

        byte[] result = null;

        ObjectOutputStream oos = null;
        ByteArrayOutputStream byteArray = new ByteArrayOutputStream();
        try {
            oos = new ObjectOutputStream(byteArray);
            try {
                oos.writeObject(data);
                oos.flush();
                result = byteArray.toByteArray();
            } finally {
                oos.close();
            }
        } catch(IOException e) {
            e.printStackTrace();
        }

        return result;
    }

public static byte[] serUTFString(String data) {

        byte[] result = null;
        ObjectOutputStream oos = null;
        ByteArrayOutputStream byteArray = new ByteArrayOutputStream();
        try {
            oos = new ObjectOutputStream(byteArray);
            try {
                oos.writeUTF(data);
                oos.flush();
                result = byteArray.toByteArray();
            } finally {
                oos.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return result;
    }

谁能告诉我为什么?

String 操作+ 替换为StringBuilder,现在set(String, String) 仍然比其他方法更快。

另一个问题,在使用set(byte[], byte[]) 时是否有必要将serialize 字符串转换为字节或只调用String.getBytes[]

【问题讨论】:

  • 谢谢,正在研究,很有帮助!
  • 您可以将 Kryo 用于 byte[] 格式化例程...我在笔记本电脑上使用 1000 个并行线程对其进行了测试,并且在单个事务中可能比字符串读/写快 3 倍。

标签: java string performance serialization redis


【解决方案1】:

set( byte[], byte[] ) 效率更高,因为当您使用 String 时,它们会在 Jedis 内部转换为 byte[],然后再编码到通信缓冲区中。

现在,问题是标准库中没有任何廉价的 byte[] 格式化例程,就像使用 String 一样。使用序列化类来格式化缓冲区太昂贵了。您需要的是 byte[] 的 StringBuilder(即带有格式化选项的 ByteBuilder 类)。

类似这样的: https://code.google.com/p/coding4play/source/browse/trunk/Server/src/gameserver/util/ByteBuilder.java?r=63

【讨论】:

  • 我在我的 SerializeUtil 中进行序列化,因为我自己将 String 传输到 byte[] 是不是让事情变得更好?
  • 是的,但是这个增益被 ByteArrayOutputStream 比隐式 StringBuilder 效率低得多的事实抵消了,后者在应用 + 格式化字符串时使用。
猜你喜欢
  • 2017-09-14
  • 1970-01-01
  • 1970-01-01
  • 2013-02-15
  • 2023-03-18
  • 2012-06-05
  • 2018-10-31
  • 1970-01-01
  • 2019-08-26
相关资源
最近更新 更多