计算机与 Internet

什么时候能用 log 对象的静态引用

这是一篇2011年1月9日开始至今没有完成的翻译,十多年了,今天我在整理草稿时发现它还躺在这里,然后我尝试点击查看英文原文试图完成它时,原来的英文原文地址已经不存在了,然后就去搜索标题试图找到英文原文,发现已经有朋友翻译过它了:什么时候使用静态的Log对象。那这篇就不继续了。


英文原文:When Static References to Log objects can be used When Static References to Log objects can be used

有两个非常常见的使用日志的模式:

public class Foo {
 private Log log = LogFactory.getLog(Foo.class);
 ....
}

public class Foo {
 private static Log log = LogFactory.getLog(Foo.class);
 ....
}

静态限定符的使用在某些情况下是有益的。然而,在其它一些情况下,它却确确实实是一个糟糕的主意,并且可能会有意想不到的后果。本页面描述了各个方案在什么情况下是合适的。

静态的问题

技术上,使用静态的结果是很明显的:在这个类的所有实例间共享这个仅有的 Log 引用。这很明显节省了内存;不管创建多少个实例都只需要一个引用(4 或者 8 个字节)。并且 CPU 角度也非常有效率;查找 Log 实例只需要在这个类第一次被引用的时候做一次。

当编写一个独立的应用程序代码时,使用静态是个好主意。

然而,当相关 java 代码是一个可能部署在某种容器(比如 J2EE 服务器)里的类库时,那么问题就来了。容器创建一个 java ClassLoader 对象的分级结构,比如每个“应用”所部署的容器有自己的 ClassLoader 但又有一些共享的 ClassLoader 作为所有部署着的“应用”的祖先,是很常见的事。这种情况下,当一个持有了 Log 实例的静态引用的类被部署在“应用程序”级(比如在一个 servlet 或 j2ee 容器的“webapp”级),这还没有问题;如果多个应用部署了这个有问题的类,那么他们每个都有这个类的一份副本,并且和其它应用没有交互。

然而考虑到这样一种情况,当一个使用了“private static Log log = …”的类被一个 ClassLoader 部署为多个看上去像独立的“应用”的祖先。这种情况下,log 成员仅被初始化一次,因为只有一个这个类的副本。这个初始化(典型地)发生在任何代码第一次试图实例化或调用一个静态方法时。当这个类的初始化发生时,这个 log 成员应该设置成什么?有以下选择:

引用属于“容器”层配置的 Log 对象,而不和任何“应用”关联。

引用在层次结构上和当前应用相关的应用里配置的 Log 对象

引用一个“代理”对象,每次调用 log 方法时都去找出当前应用,并委派给其下的 Log 对象

第一个选择是说日志不能配置在每个应用层。无论日志配置如何设置都会将每个应用的日志设成和容器里配置的一样,所有的从这些应用里的输出都会合并到一块。这是一个大问题。

第二个选择是说 Log 对象将配置成和第一个被调用的应用里配置的。容器里的其它应用将把它们的输出发送到第一个应用配置的目标里。显而易见,这是一个大问题。

第三个选择允许每个应用都有各自的日志配置,并正确地过滤和输出需要的日志信息。可是付出的性能损失非常大,这不是一个可以接受的解决方案。

注意,我们还没有讨论到“Thread Context ClassLoaders”或者其它的技术要点。这个问题不详述了,只给出一个概念性的结论:当 Log 对象是在多个应用间共享时,是不可能做到各个应用各配各的的,并且有性能问题。

这个问题真正的根源是数据(通过类的静态成员)在所谓独立的“应用”间共享。如果没有类是在应用间“共享”的,那么问题就不存在了。然而,它似乎(我个人的经验)容器提供商继续鼓励使用共享类,并且应用程序开发人员继续在使用它。

另一个解决方法是:在任何可能部署到共享 classpath 的代码里避免使用 Log 对象的“静态”引用。

SLF4J 有这个问题吗?

有。SLF4J 也正受着上述问题的困扰,并且有着相同的建议:在可能部署到共享 classpath 的代码中避免使用 log 对象的静态引用。

这里有几个可能的场景。首先我们需要定义一个术语“TCCL 感知”。日志类库是“TCCL 感知”的,当它初始化代码时使用 Thread Context ClassLoader 来定位配置文件,而不是类库自身里的类的 ClassLoader。举个例子,在它的标准形式里,log4j 是不能“TCCL 感知”的。不过它可以通过下面描述的一个“Contextural RepositorySelector”来做到“TCCL 感知”:

http://www.qos.ch/logging/sc.jsp

现在来看看一些可能的场景:

假设 SLF4J 是部署在一个共享的层,有一个使用了静态 Logger 引用的类在共享的 classpath 里,也有一个使用了静态 logger 的类在应用程序 classpath 里。当日志类库不是 TCCL 感知的,那么就仅读取在“共享” classpath 里的日志配置,所有部署着的应用程序都输出调试信息到全局配置里了。输出是正确的,但是就不能仅为一个应用开启调试日志了,并且从所有的应用程序里来的所有输出都是混在一起的。当日志类库是 TCCL 感知的,那么就可以针对各个应用程序配置自己的日志了。另外,来自这些类的输出都输出在应用程序层,这是正确的。然而,那些部署在共享层的类将有它们自己的 Log 对象的初始化,使用第一个调用该类的应用程序的配置;当其它应用程序调用相同的类时其日志输出将跑到第一个应用程序里去了。不好。

如果 SLF4J 同时部署在共享和应用程序层,并且首先先加载了一个父层的,那么行为和上面的一样。但是如果先加载的是应用层的,如果日志类库是 TCCL 感知的那么结果还可以承受。然而如果是先加载的应用层的,并且日志类库不是 TCCL 感知的,那么结果就是这样:从共享类里的输出仅能配置在全局,所有应用层的输出都跑到一起去了。

不幸的是,在大多数情况下,类库代码的作者不能指定类库用户说代码必须部署在哪一层,必须使用怎样的加载顺序,或者应该用什么行为的日志类库。因此有必要和 commons-loggings 一样避免使用 SLF4J logger 的静态引用。

无论如何,不当使用 SLF4J 所导致的问题确实要比 commons-logging 少。原因如下:

当前 TCCL 感知的日志类库并不多,并且目前部署在共享 classpath 里的类库相对较少地使用了 SLF4J。

commons-logging 本身是 TCCL 感知的,允许应用层的日志类库配置是非 TCCL 感知的;实际上,使用 commons-logging 时每个日志类库都可以 TCCL 感知。commons-logging 也经常被很多部署在共享 classloader 的类库所使用。

请注意,这段不是想要批评 SLF4J。如前所述,这个问题是因为应用程序间使用共享静态日志引用的隔离问题造成的冲突,并且何况在这些场景下 SLF4J 和 commons-logging 一样面临着这个尴尬。

翻译未完成。要阅读完整版本,请看这篇翻译:什么时候使用静态的Log对象

广告
标准
计算机与 Internet

HDD read/write speed test result

Disk:
  HGST
  1TB 7200RPM
  5V 800mA
  HDD: 7K1000-1000
  Type TS7SAF100
  SATA 6.0Gb/s

with ORICO TYPE-C USB 3.1 Transparent 2.5 inch Hard Drive Enclosure  [2139C3-R1.1]

$ dd if=/dev/random of=./tmp.data bs=1024k count=65536
65536+0 records in
65536+0 records out
68719476736 bytes transferred in 948.964624 secs (72415214 bytes/sec)

$ dd if=./tmp.data of=/dev/null bs=1024k
65536+0 records in
65536+0 records out
68719476736 bytes transferred in 712.999277 secs (96380851 bytes/sec)

Read speed: 96.380851 Megabyte per second
Write speed: 72.415214 Megabyte per second

#HDD #dd

标准
计算机与 Internet

SSD read/write speed test result

File System:	Case-sensitive APFS
Physical Drive:
  Device Name:	APPLE SSD AP8192N
  Media Name:	AppleAPFSMedia
  Medium Type:	SSD
  Protocol:	PCI-Express
  Internal:	Yes
  Partition Map Type:	Unknown
  S.M.A.R.T. Status:	Verified

$ dd if=/dev/random of=/tmp/tmp.data bs=1024k count=262144
262144+0 records in
262144+0 records out
274877906944 bytes transferred in 764.036416 secs (359770688 bytes/sec)

$ dd if=/tmp/tmp.data of=/dev/null bs=1024k
262144+0 records in
262144+0 records out
274877906944 bytes transferred in 99.768125 secs (2755167619 bytes/sec)

Read speed: 2.755167619 Gigabyte per second
Write speed: 359.770688 Megabyte per second

#SSD #dd

标准
计算机与 Internet

MacBook Pro 16,1 Ubench

Hardware Overview:

Model Name: MacBook Pro
Model Identifier: MacBookPro16,1
Processor Name: 8-Core Intel Core i9
Processor Speed: 2.4 GHz
Number of Processors: 1
Total Number of Cores: 8
L2 Cache (per Core): 256 KB
L3 Cache: 16 MB
Hyper-Threading Technology: Enabled
Memory: 64 GB
Boot ROM Version: 1037.147.4.0.0 (iBridge: 17.16.16610.0.0,0)
Activation Lock Status: Disabled

Unix Benchmark Utility v.0.3
Copyright (C) July, 1999 PhysTech, Inc.
Author: Sergei Viznyuk
http://www.phystech.com/download/ubench.html
Darwin 19.6.0 Darwin Kernel Version 19.6.0: Thu Jun 18 20:49:00 PDT 2020; root:xnu-6153.141.1~1/RELEASE_X86_64 x86_64
Ubench CPU: 5887318
Ubench MEM: 1754351
——————–
Ubench AVG: 3820834

标准
计算机与 Internet

DigitalOcean Compute-optimized SFO2 2 vCPUs 4GB Memory 25GB Disk ubench

Unix Benchmark Utility v.0.3
Copyright (C) July, 1999 PhysTech, Inc.
Author: Sergei Viznyuk
http://www.phystech.com/download/ubench.html
FreeBSD 12.1-RELEASE-p2 FreeBSD 12.1-RELEASE-p2 GENERIC amd64
Ubench CPU: 864680
Ubench MEM: 741036
——————–
Ubench AVG: 802858

标准
计算机与 Internet

DigitalOcean Standard SFO1 1 vCPUs 3GB Memory 50GB Disk ubench

Unix Benchmark Utility v.0.3
Copyright (C) July, 1999 PhysTech, Inc.
Author: Sergei Viznyuk
http://www.phystech.com/download/ubench.html
FreeBSD 12.1-RELEASE-p2 FreeBSD 12.1-RELEASE-p2 GENERIC amd64
Ubench CPU: 317769
Ubench MEM: 361761
——————–
Ubench AVG: 339765

#digitalocean, #ubench

标准
计算机与 Internet

DigitalOcean Standard SFO1 1 vCPUs 2GB Memory 50GB Disk ubench

Unix Benchmark Utility v.0.3
Copyright (C) July, 1999 PhysTech, Inc.
Author: Sergei Viznyuk
http://www.phystech.com/download/ubench.html
FreeBSD 12.1-RELEASE-p2 FreeBSD 12.1-RELEASE-p2 GENERIC amd64
Ubench CPU: 280240
Ubench MEM: 248686
——————–
Ubench AVG: 264463

标准
计算机与 Internet

DigitalOcean Standard SFO1 2 vCPUs 4GB Memory 80GB Disk ubench

Unix Benchmark Utility v.0.3
Copyright (C) July, 1999 PhysTech, Inc.
Author: Sergei Viznyuk
http://www.phystech.com/download/ubench.html
FreeBSD 12.1-RELEASE-p2 FreeBSD 12.1-RELEASE-p2 GENERIC amd64
Ubench CPU: 486249
Ubench MEM: 478180
——————–
Ubench AVG: 482214

#digitalocean, #ubench

标准
社会

《人的宗教》书摘

缘起

基于对宗教的不理解,而产生了对宗教文化学习的兴趣。

阅读这本书花了太多的毅力,古老的宗教中所描述的价值观和世界观与我自身所理解的价值观和世界观的冲突,让我中途多次想放弃,用“啃完”绝不为过。

什么时候打开这本书的,已经不记得了,只能看到它是2019年7月21日加入书库的,11月19日加了第一个书签,前天才读完它,所以应该可以认为我是用了半年时间才啃完了它。

下面是我在阅读的过程中,在书中所加的书签的位置的文字。
它们不具有连贯性,也不具有任何系统性。
它们有些是我认为需要再查阅资料深入阅读的,有些是在阅读的当时触动了我的内心的,有些是我已经不记得当时的我为什么要做这个书签了的。

宗教

宗教的六个特征:权威、仪式、玄想、传统、恩宠(信仰)以及奥秘。

佛教相关

南亚国家,包括至今仍然信仰原始佛教的斯里兰卡、缅甸、泰国和柬埔寨,都很严格地采纳了佛陀在这方面的政治信息。
然而中国人是不会在这个题目上让异族人士来教训的。因此中国摈除佛陀的政治提倡,而取其具有宇宙意味的心理——精神的成分。

“身是菩提树,
心如明镜台。
时时勤拂拭,
莫使染尘埃。”

“菩提本无树;
明镜亦非台。
本来无一物,
何处染尘埃?”

“我们不问禅的未来,却可留意到它对日本文化生活的影响是多么的巨大。虽然它最大的影响是弥漫在生活态度上,日本文化的四个成分却持久地打上了它的烙印。在水墨风景画中,禅宗和尚紧依着土地过着他们简朴的生活,在技巧和感觉的深度上已可与他们的中国老师们相抗衡了。在庭园艺术上,禅宗寺庙将之提升到了无比的完美境地。插花技术开始时是献花给佛陀,但是后来发展成了一种艺术,直到最后变成了每一位有教养的日本女孩训练的一部分。最后,就是著名的茶道,朴实美丽的摆设,几件旧瓷器,缓慢而优雅的仪式,以及一种配合着全然的平静的精神,集中体现了禅宗最好的特性和谐、尊敬、清晰和安详。”

“佛教徒把手掌合并,象征克服二元性。”

儒家相关

“你可用刺刀做任何事,却不能坐在上面。”

道家相关

“道家冥想的身体姿势和专注技术总是令人联想到“修的瑜伽”。”

伊斯兰教相关

“这个宗教的正确名称是伊斯兰(Islam),从字根s-l-m演变而来,主要的意思是“和平”,不过还有“屈从”或“顺从”的第二层意思,它的全部意义是“当一个人的生命顺从了神,和平就会降临”。世界上只有两个宗教是以其试图去修成的特性来命名的:一个是佛教,以佛为觉醒之意,另一个即是伊斯兰教;在后者,所要修成的是生命对神的完全顺服。遵循伊斯兰的人就称之为穆斯林(Muslims)。”

“神创造了世界,之后就创造了人。创造的第一个人是亚当。亚当的后代到了诺亚,他生了一个儿子名叫Shem(闪)。这就是Semite(闪族)这个字的由来;从字面上来看Semite是Shem的后裔。正如犹太人一样,阿拉伯人认为他们自己是Semite人。Shem的后裔传到亚伯拉罕(Abraham),到目前为止,我们仍然是在犹太教和基督教的传统中。
的确,正是亚伯拉罕在这个最重要的试探中的顺从——是否愿意牺牲他的儿子以撒?——为伊斯兰提供了它的名字。亚伯拉罕娶了撒拉。撒拉没有生子,因此亚伯拉罕为了延续后代,娶了夏甲做他的第二位妻子。夏甲为他生了一个儿子叫以实玛利(Ishmael),而此时撒拉怀孕了,也生了一个儿子,名叫以撒。然后撒拉就要求亚伯拉罕把以实玛利和夏甲赶出部族。此时我们来到《古兰经》与《圣经》描述之间的第一分歧点。按照《古兰经》,以实玛利就去了麦加。他的后代在阿拉伯地区繁生起来,成了穆斯林;而以撒的后代留在巴勒斯坦,是希伯来人,变成了犹太教徒。”

犹太教相关

如果我们想要更深刻地了解犹太教,我们已经到了必须停止进一步考察犹太人的观念,而要来看看犹太人实践的时候了。我们必须考察犹太人的仪式和戒律,因为一般都同意犹太教比较起来,不是一个思想正统,而是一个行为正统;犹太人得以结合起来,是通过他们的所作所为,远胜于通过他们的所思。一个证明是,犹太人从来没有颁布任何信教者必须接受的官方教条;另一方面,戒律例如男性的阉割礼,却是明确的。这种对实践的重视给予犹太教某种东方的味道;在西方,受到希腊对抽象理性爱好的影响,则重视神学和教条。在东方,则通过仪式和叙事来探讨宗教。差异是在抽象与具体之间。到底是柏拉图还是陀斯妥耶夫斯基更接近真实呢?爱到底是通过语言还是通过拥抱能够表达得更好呢?

关于仪式

“从狭隘理性的或功利的观点来看,仪式是无聊的,从任何角度来看它都觉得是浪费。”

“但是,虽然它有极大的专横性以及看似浪费,仪式在生命中所扮演的角色却不是任何别的东西可以填补的,这个角色并不只局限在宗教之内。比方,它可以让我们舒缓地度过紧张的局面和焦虑的时刻。有时候焦虑是温和的——在与人见面的时候,比方,我被介绍给一位陌生人,不知道他或她会如何反应,我不知道怎么做。我该说什么呢?我该怎么做呢?仪式掩盖了我的不安和别扭。它告诉我把手伸出去说“你好”或“很高兴见到你”。这样做的结果就在混乱中带来了形式。它应付了我需要了解如何举止的时刻。别扭过去了。我已恢复了我的平衡,而且准备尝试作比较自由的举止了。”

“死亡是尖锐的例子。被悲剧性的丧失亲友之痛所打击,如果我们只靠自己来想办法度过这个考验,我们会完全崩溃。这就是何以死亡要有葬礼和纪念仪式、守灵和坐湿婆,乃是最仪式化的跨越礼。”

“当我们受打击或者极端地欢乐时,不仅想要与他人同在,所用的方式还要使得交流的结果超过个别行为的总和——这样才能消减我们的孤独。这种行为并不仅仅限于人类。在泰国北部,当太阳最初照射树梢之际,长臂猿族集体用降半音的音阶哼唱着,手牵着手,在顶端的树枝猝降而过。”

“仪式——以准备好的歌谱来安排这一场合,在一个孤独令人不能忍受的时候,来疏导我们的行为和感受。在这过程中就柔化了受到的打击”

“在快乐的时候它能够加强快乐的经验,而把欢乐提升成为喜庆。这方面的例子是生日、结婚之喜,以及最简单的一顿家庭晚餐。在这一日最好的一餐饭中,或许这是一家人在一日中第一次轻松地聚在一起,饭前的祷告可以比赛跑的起点更重要。它能使这个场合神圣化。与沉重的负担相反,它神圣化了日常的欢乐。”

基督教相关

“基督徒之所以不受狮子的恐吓,甚至在进入斗兽场还歌唱着的原因,乃是因为耶稣的劝导“不必怕,因为我与你们同在”,对他们产生了作用。”

“信仰。信仰,在新教的概念中,并不单是指“相信”,亦即一种接受认为确定的知识却并没有建立在证据之上。”

原初宗教相关

“一位调查者与黑麋族(Black Elk)住了两年后报导说,依黑麋族人的主张,认为打猎“是”——黑麋族人没有说“代表”,报导者强调——生命所追求的最终真理;这项追求需要预备性的祈祷和献祭的洁礼。“辛勤追踪的行踪是所追逐的目标的信号和通知,最后与追踪对象的接触或认同就是真理的实现,是生命的最终目标。”

(这里让我想到敖鲁古雅使鹿鄂温克族生态移民的困境。)

最后的考察

““了解”能导致“爱”。反过来亦然,“爱”导致“了解”;两者是交互为用的。”

标准