【问题标题】:Existing solution to "smart" initial capacity for StringBuilderStringBuilder 的“智能”初始容量的现有解决方案
【发布时间】:2012-12-21 09:06:42
【问题描述】:

我有一段记录和跟踪相关的代码,它经常在整个代码中调用,尤其是在打开跟踪时。 StringBuilder 用于构建字符串。字符串具有合理的最大长度,我想大约是数百个字符。

问题:是否有现有的图书馆可以做这样的事情:

// in reality, StringBuilder is final,
// would have to create delegated version instead,
// which is quite a big class because of all the append() overloads
public class SmarterBuilder extends StringBuilder {         

    private final AtomicInteger capRef;

    SmarterBuilder(AtomicInteger capRef) {
        int len = capRef.get(); 
        // optionally save memory with expense of worst-case resizes:
        // len = len * 3 / 4;
        super(len);
        this.capRef = capRef;
    }

    public syncCap() {
        // call when string is fully built
        int cap;
        do {
            cap = capRef.get();
            if (cap >= length()) break;
        } while (!capRef.compareAndSet(cap, length());
    }
}

为了利用这一点,我的日志相关类将有一个共享的capRef 变量,其范围合适。

(额外问题:我很好奇,是否可以在不循环的情况下执行 syncCap()?)

动机:我知道 StringBuilder 的默认长度总是太少。我可以(并且目前确实)输入 100 的临时初始容量值,这会导致在某些情况下调整大小,但并非总是如此。但是,我不喜欢源代码中的幻数,而这个特性是“优化一次,每个项目都使用”的情况。

【问题讨论】:

    标签: java stringbuilder


    【解决方案1】:

    确保您进行性能测量,以确保您确实从额外的工作中获得了一些好处。

    作为类似 StringBuilder 的类的替代方案,请考虑使用 StringBuilderFactory。它可以提供两种静态方法,一种用于获取 StringBuilder,另一种用于在您完成构建字符串时调用。您可以将 StringBuilder 作为参数传递给它,它会记录长度。 getStringBuilder 方法将使用其他方法记录的统计信息来选择初始大小。

    有两种方法可以避免 syncCap 中的循环:

    1. 同步。
    2. 忽略失败。

    在这种情况下忽略故障的理由是您只需要对实际长度进行随机抽样。如果另一个线程同时更新,您将获得字符串长度的最新视图。

    【讨论】:

    • 我最终创建了一个简单的内部工厂类,其中包含 get() 和 update() 方法以及针对该特定情况的正确假设。
    【解决方案2】:

    您可以将每个字符串的字符串长度存储在一个统计数组中。运行您的应用程序,并在关闭时获取字符串长度的 90% 四分位数(对所有 str 长度值进行排序,并在数组 pos = sortedStrings.size() * 0,9

    处获取长度值

    这样您就创建了一个初始字符串构建器大小,其中 90% 的字符串都适合。

    更新
    该值可以是硬编码的(就像 java 对 ArrayList 中的值 10 所做的那样),或者从配置文件中读取,或者在测试阶段自动计算。但是四分位数计算不是免费的,所以最好运行项目一段时间,在 SmartBuilder 中即时测量 90% 的四分位数,不时输出 90% 的四分位数,然后更改属性文件以使用该值.

    这样您就可以为每个项目获得最佳结果。
    或者,如果您更进一步:让您的智能 Builder 不时在配置文件中更新该值。 但这一切都不值得付出努力,您只会对具有数百万条目的数据这样做,例如数字路线图等。

    【讨论】:

    • 如果我没看错,您的意思是说这是为源代码硬编码获得良好价值的一种方式?是的,但我正在寻找一种自动执行此操作的方法。优化在宏观方案中是如此之小,花时间优化几个硬编码值(在同一项目的不同部分,不同项目中)是没有意义的,尤其是当最优值可能随着下一次代码更改而改变时.优化必须是“免费的”(或者至少非常便宜,比如在代码中添加一个额外的 AtomicInteger)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-14
    • 1970-01-01
    • 1970-01-01
    • 2011-04-03
    • 1970-01-01
    • 2018-05-08
    • 1970-01-01
    相关资源
    最近更新 更多