小编nad*_*vwr的帖子

使用上下文边界"消极地"以确保范围内不存在类型类实例

tl; dr:我如何做类似下面的编写代码:

def notFunctor[M[_] : Not[Functor]](m: M[_]) = s"$m is not a functor"
Run Code Online (Sandbox Code Playgroud)

' Not[Functor]',是这里的组成部分.
当'm'提供的不是Functor时,我希望它成功,否则编译器会失败.

解决:跳过问题的其余部分,然后直接回答下面的答案.


我粗略地说,我想要完成的是"负面证据".

伪代码看起来像这样:

// type class for obtaining serialization size in bytes.
trait SizeOf[A] { def sizeOf(a: A): Long }

// type class specialized for types whose size may vary between instances
trait VarSizeOf[A] extends SizeOf[A]

// type class specialized for types whose elements share the same size (e.g. Int)
trait FixedSizeOf[A] extends SizeOf[A] {
  def fixedSize: Long
  def sizeOf(a: A) …
Run Code Online (Sandbox Code Playgroud)

scala implicit typeclass higher-kinded-types scalaz

16
推荐指数
1
解决办法
1146
查看次数

64位OpenJDK 7/8中并发长写的值完整性保证

注意:此问题与volatile,AtomicLong或所描述的用例中的任何感知缺陷无关.

我试图证明或排除的财产如下:

鉴于以下内容:

  • 最近的64位OpenJDK 7/8(最好7位,但8位也很有帮助)
  • 多处理英特尔基础系统
  • 非易失性长原始变量
  • 多个不同步的mutator线程
  • 一个不同步的观察者线程

观察者是否始终保证会遇到由变异线程写的完整值,或者是撕裂危险的单词?

JLS:不确定

此属性对于32位基元和64位对象引用是存在的,但是对于long和double,JLS不保证:

17.7.非原子对double和long的处理:
出于Java编程语言内存模型的目的,对非易失性long或double值的单次写入被视为两个单独的写入:每个32位一半写入一次.这可能导致线程从一次写入看到64位值的前32位,而从另一次写入看到第二次32位的情况.

但是抱着你的马:

[...]为了效率,这种行为是特定于实现的; Java虚拟机的实现可以自由地以原子方式或分两部分执行对long和double值的写入.鼓励Java虚拟机的实现避免在可能的情况下拆分64位值.[...]

因此,JLS 允许 JVM实现拆分64位写入,并鼓励开发人员相应地进行调整,但也鼓励 JVM实现者坚持使用64位写入.我们还没有回答最新版本的HotSpot.

HotSpot JIT:谨慎乐观

由于单词撕裂最有可能发生在紧密循环和其他热点的范围内,我试图分析JIT编译的实际汇编输出.长话短说:需要进一步测试,但我只能在long上看到原子64位操作.

我使用了hdis,一个OpenJDK的反汇编插件.在我老化的OpenJDK 7u25版本中构建并安装了插件之后,我开始编写一个简短的程序:

public class Counter {
  static long counter = 0;
  public static void main(String[] _) {
    for (long i = (long)1e12; i < (long)1e12 + 1e5; i++)
      put(i);
    System.out.println(counter);
  }

  static void put(long v) {
    counter += v;
  }
}
Run Code Online (Sandbox Code Playgroud)

我确保始终使用大于MAX_INT(1e12到1e12 + 1e5)的值,并重复操作足够的次数(1e5)以触发JIT.

编译后,我用hdis执行Counter.main(),如下所示:

java -XX:+UnlockDiagnosticVMOptions \ 
     -XX:PrintAssemblyOptions=intel \
     -XX:CompileCommand=print,Counter.put …
Run Code Online (Sandbox Code Playgroud)

java concurrency jvm jvm-hotspot java-memory-model

9
推荐指数
2
解决办法
628
查看次数

在完整GC之前获得预先警告

对于不应暂停超过200毫秒的软实时系统的环境,我们正在寻找一种在完全GC即将发布之前预先发出警告的方法.我们意识到我们可能无法避免它,但我们想在系统停止之前故障转移到另一个节点.

我们已经能够提出一个方案,在即将完成的GC之前提供预警,这可能导致系统停滞几秒钟(我们需要避免).

我们能够提出的依赖于CMS免费列表统计:-XX:PrintFLSStatistics=1.这会在每个GC周期(包括年轻GC)之后将空闲列表统计信息打印到GC日志中,因此信息可以短时间间隔获得,并且在高内存分配率的间隔期间更频繁地出现.它在性能方面可能会花费一点点,但我们的工作假设是我们可以负担得起.

日志的输出如下所示:

Statistics for BinaryTreeDictionary:
------------------------------------
Total Free Space: 382153298
Max   Chunk Size: 382064598
Number of Blocks: 28
Av.  Block  Size: 13648332
Tree      Height: 8
Run Code Online (Sandbox Code Playgroud)

特别是,最大空闲块大小为382064598个单词.使用64位字,这应该低于2915MB.这个数字一直在缓慢下降,速度大约为每小时1MB.

我们的理解是,只要最大空闲块大小大于年轻代(假设没有大量的对象分配),每个对象促销都应该成功.

最近,我们进行了为期数天的压力测试,并且已经看到CMS能够将最大块大小保持在旧区域总空间的94%以上.最大的免费块大小似乎以小于1MB /小时的速度递减,这应该没问题 - 据此我们不会很快就达到完全GC,并且服务器可能会因维护更多而停机经常比完整的GC可能发生.

在之前的测试中,当系统内存效率较低时,我们已经能够运行系统10小时.在第一个小时内,最大免费块大小减少到100MB,并且停留超过8小时.在运行的最后40分钟内,当一个完整的GC发生时,最大空闲块大小以稳定的速率向0降低 - 这非常令人鼓舞,因为对于那个工作负载,我们似乎能够提前40分钟警告(当块大小开始稳定下降为0时).

我的问题是:假设这一切都反映了长时间的峰值工作量(生产中任何给定时间点的工作量只会更低),这听起来像是一种有效的方法吗?您认为我们应该能够依靠GC日志中的最大空闲块大小统计量来确定可靠性的程度吗?

我们绝对愿意接受建议,但要求他们仅限于HotSpot上的解决方案(No Azul对我们来说,至少目前为止).此外,G1本身并不是解决方案,除非我们能够提出类似的指标,以便在Full GCs之前提前发出警告,或者任何明显超过我们SLA的GC(这些可能偶尔发生).

java performance garbage-collection real-time

8
推荐指数
1
解决办法
1966
查看次数