我正在研究实现一个简单的开源对象时态数据库的最佳数据结构,目前我非常喜欢使用持久性红黑树来实现它.
我使用持久数据结构的主要原因首先是最小化锁的使用,因此数据库可以尽可能并行.此外,实现ACID事务更容易,甚至能够抽象数据库以在某种集群上并行工作.这种方法的好处在于它几乎可以免费实现时态数据库.这是非常好的,特别适用于网络和数据分析(例如趋势).
所有这些都非常酷,但我对在磁盘上使用持久数据结构的整体性能有点怀疑.即使今天有一些非常快的磁盘可用,并且所有写入都可以异步完成,所以响应总是立竿见影,我不想在错误的前提下构建所有应用程序,只是意识到它并不是真的好这样做的方式.
这是我的思路: - 由于所有写入都是异步完成的,并且使用持久数据结构将不会使先前(当前有效)结构无效,因此写入时间实际上不是瓶颈.- 有一些关于此类结构的文献正是针对磁盘使用的.但在我看来,这些技术将增加更多的读取开销,以实现更快的写入.但我认为恰恰相反是可取的.这些技术中的许多确实最终会使用多版本树,但它们并不是严格不可变的,这对于证明持久开销非常重要. - 我知道在向数据库附加值时仍然需要进行某种锁定,而且如果不是要维护所有版本,我也知道应该有一个好的垃圾收集逻辑(否则文件大小肯定会大幅上升) .还可以考虑增量压缩系统. - 在所有搜索树结构中,我真的认为红黑是最接近我需要的,因为它们提供最少的旋转次数.
但是在此过程中存在一些可能的缺陷: - 异步写入 - 可能会影响需要实时数据的应用程序.但我不认为Web应用程序就是这种情况,大部分时间都是如此.此外,当需要实时数据时,可以设计另一种解决方案,例如需要以更实时的方式工作的特定数据的登记/结账系统. - 它们也可能导致一些提交冲突,但我没有想到它何时会发生的好例子.如果两个线程使用相同的数据,那么正常的RDBMS中也会发生冲突,对吧? - 拥有像这样的不可变接口的开销将呈指数级增长,一切都注定要很快失败,所以这一切都是个坏主意.
有什么想法吗?
谢谢!
编辑:似乎存在对持久性数据结构的误解:http: //en.wikipedia.org/wiki/Persistent_data_structure
database binary-tree functional-programming immutability data-structures
在我看来,.NET存在极端缺乏安全,不可变的集合类型,特别是BCL,但我还没有看到很多工作在外面完成.有没有人有任何指向(优选)生产质量,快速,不可变的.NET集合库.快速列表类型是必不可少的.我还没准备好切换到F#.
*编辑:注意搜索者,很快就会进入BCL: .NET不可变集合
我的代码充满了收藏 - 我想这不是一件不寻常的事情.但是,各种集合类型的使用并不明显,也不是微不足道的.通常,我想使用暴露"最佳"API的类型,并且语法噪音最小.(请参阅返回值数组时的最佳做法,使用列表数组 -可比较问题的最佳做法).有一些指南建议在API中使用哪些类型,但这些在普通(非API)代码中是不切实际的.
例如:
new ReadOnlyCollection<Tuple<string,int>>(
new List<Tuple<string,int>> {
Tuple.Create("abc",3),
Tuple.Create("def",37)
}
)
Run Code Online (Sandbox Code Playgroud)
List这是一个非常常见的数据结构,但以这种方式创建它们会涉及相当多的语法噪音 - 而且它可能很容易变得更糟(例如字典).事实证明,许多列表永远不会改变,或者至少从未扩展.当然会ReadOnlyCollection引入更多的语法噪音,它甚至没有表达我的意思; 毕竟ReadOnlyCollection可以包装一个变异的集合.有时我在内部使用数组并返回一个IEnumerable表示意图.但是大多数这些方法都具有非常低的信噪比; 这对理解代码至关重要.
对于不是公共API 的99%的代码,没有必要遵循框架指南:但是,我仍然需要一个可理解的代码和一个传达意图的类型.
那么,处理使用小型集合传递价值的沼泽标准任务的最佳实践方法是什么? 阵列应该List尽可能优先吗?还有别的吗?什么是最好的方式 - 清洁,可读,合理有效 - 传递这样的小集合?特别是,对于未阅读此问题并且不想阅读大量API文档但仍然了解其意图的未来维护者而言,代码应该是显而易见的.最大限度地减少代码混乱也是非常重要的- 所以这样的事情充其量是可疑的.具有小表面的主要API的罗嗦类型没有错,但不是大型代码库中的一般做法.ReadOnlyCollection
在没有大量代码混乱(例如显式类型参数)的情况下传递值列表的最佳方法是什么,但仍能清楚地传达意图?
编辑:澄清这是关于制作简短明了的代码,而不是关于公共API的.
是否正确无法更改不可变对象的值?
我有两个关于readonly我想要理解的场景:
如果我有一个集合并将其标记为readonly,如下所示.我还能打电话_items.Add吗?
private readonly ICollection<MyItem> _items;
Run Code Online (Sandbox Code Playgroud)并且对于以下变量,如果稍后我调用_metadata.Change哪个将更改Metadata实例中的一个成员变量的内部值.是_metadata仍然不变?
private readonly Metadata _metadata;
Run Code Online (Sandbox Code Playgroud)对于上面的两个变量,我完全理解我不能在初始化器和构造器之外直接为它们分配新值.
由于这是当前的一个热门话题,我无法理解某些概念.请原谅我,如果我听起来很愚蠢,但当我尝试创建不可变对象的大部分帖子时,我发现了以下几点
现在我无法理解为什么我们需要以下几点
我在这里添加我的课程和测试用例:
public final class ImmutableUser {
private final UUID id;
private final String firstName;
private final String lastName;
public ImmutableUser(UUID id, String firstName, String lastName) {
super();
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
}
/**
* @return the id
*/
public UUID getId() {
return id;
}
/**
* @return the firstName
*/
public String getFirstName() {
return firstName;
}
/** …Run Code Online (Sandbox Code Playgroud) 可以创建这样的DeepReadonly类型:
type DeepReadonly<T> = {
readonly [P in keyof T]: DeepReadonly<T[P]>;
};
interface A {
B: { C: number; };
D: { E: number; }[];
}
const myDeepReadonlyObject: DeepReadonly<A> = {
B: { C: 1 },
D: [ { E: 2 } ],
}
myDeepReadonlyObject.B = { C: 2 }; // error :)
myDeepReadonlyObject.B.C = 2; // error :)
Run Code Online (Sandbox Code Playgroud)
这很棒.这两个B和B.C是只读的.当我尝试修改D但是...
// I'd like this to be an error
myDeepReadonlyObject.D[0] = { E: …Run Code Online (Sandbox Code Playgroud) 我正在学习DDD,并且遇到了"值 - 对象"应该是不可变的声明.我知道这意味着对象状态在创建后不应该更改.这对我来说是一种新的思维方式,但在许多情况下它是有道理的.
好的,所以我开始创建不可变的值对象.
但是现在我想创建这个包含8个不同数值的值对象.如果我创建一个具有8个数字参数的构造函数,我觉得它不会很容易使用,或者更确切地说 - 传递数字时很容易出错.这不是一个好的设计.
所以问题是:是否还有其他方法可以使我的不可变对象变得更好..,在C#中可以用来克服构造函数中的长参数列表的任何魔法?我很想听听你的想法..
更新:在任何人提到它之前,这里讨论了一个想法: C#中的不可变对象模式 - 你怎么看?
有兴趣听取其他建议或意见.
我有以下课程:
class MySet(set):
def __init__(self, arg=None):
if isinstance(arg, basestring):
arg = arg.split()
set.__init__(self, arg)
Run Code Online (Sandbox Code Playgroud)
这可以按预期工作(用字符串而不是字母初始化集合).但是,当我想对set的不可变版本执行相同操作时,该__init__方法似乎被忽略:
class MySet(frozenset):
def __init__(self, arg=None):
if isinstance(arg, basestring):
arg = arg.split()
frozenset.__init__(self, arg)
Run Code Online (Sandbox Code Playgroud)
我可以实现类似的东西__new__吗?
我目前正在学习Haskell,我很好奇以下内容:
如果我在Haskell中向一个列表中添加一个元素,Haskell会返回一个(完全?)新列表,并且不会操纵原始列表.
现在假设我有一个包含一百万个元素的列表,并在最后添加一个元素.Haskell"复制"整个列表(100万个元素)并将元素添加到该副本中吗?或者是否有一个整洁的"技巧"在幕后进行,以避免复制整个列表?
如果没有"技巧",复制大型列表的过程是不是像我想的那样昂贵?
来自https://hackage.haskell.org/package/vector-0.12.0.1/docs/Data-Vector.html#v:modify
对矢量应用破坏性操作.如果安全的话,操作将在适当的位置执行,否则将修改矢量的副本.
听起来它可能具有截然不同的性能特征,这取决于在适当的位置修改矢量是否被认为是"安全的".这激发了问题......
修改何时进行到位,何时复制向量?有没有办法通过使用类型系统来确保它将被修改到位?
performance haskell functional-programming vector immutability
immutability ×10
c# ×4
haskell ×2
.net ×1
append ×1
binary-tree ×1
database ×1
generics ×1
java ×1
list ×1
performance ×1
python ×1
readonly ×1
set ×1
typescript ×1
vector ×1