5

我有一段记录和跟踪相关的代码,它经常在整个代码中调用,尤其是在打开跟踪时。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 的临时初始容量值,这会导致在某些情况下调整大小,但并非总是如此。但是,我不喜欢源代码中的幻数,而这个特性是“优化一次,在每个项目中使用”的情况。

4

2 回答 2

1

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

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

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

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

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

于 2012-12-21T09:40:40.010 回答
0

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

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

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

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

于 2012-12-21T09:28:40.167 回答