2023-05-26:golang关于垃圾回收和析构的选择题,代码如下:
package main
import (
"fmt"
"runtime"
"time"
)
type ListNode struct {
Val int
Next *ListNode
}
func main0() {
a := &ListNode{Val: 1}
b := &ListNode{Val: 2}
runtime.SetFinalizer(a, func(obj *ListNode) {
fmt.Printf("a被回收--")
})
runtime.SetFinalizer(b, func(obj *ListNode) {
fmt.Printf("b被回收--")
})
a.Next = b
b.Next = a
}
func main() {
main0()
time.Sleep(1 * time.Second)
runtime.GC()
time.Sleep(1 * time.Second)
runtime.GC()
time.Sleep(1 * time.Second)
runtime.GC()
time.Sleep(1 * time.Second)
runtime.GC()
time.Sleep(1 * time.Second)
runtime.GC()
fmt.Print("结束")
}
代码的运行结果是什么?并说明原因。注意析构是无序的。
A. 结束
B. a被回收--b被回收--结束
C. b被回收--a被回收--结束
D. B和C都有可能
golang的垃圾回收算法跟java一样,都是根可达算法。代码中main0函数里a和b是互相引用,但是a和b没有外部引用。因此a和b会被当成垃圾被回收掉。而析构函数的调用不是有序的,所以B和C都有可能,答案选D。让我们看看答案是什么,如下:
看运行结果,答案不是选D,而是选A。这肯定会出乎很多人意料,golang的垃圾回收算法是根可达算法难不成是假的,大家公认的八股文难道是错的?有这个疑问是好事,但不能全盘否定。让我们看看析构函数的源码吧。代码在 src/runtime/mfinal.go
中,如下:
// SetFinalizer sets the finalizer associated with obj to the provided
// finalizer function. When the garbage collector finds an unreachable block
// with an associated finalizer, it clears the association and runs
// finalizer(obj) in a separate goroutine. This makes obj reachable again,
// but now without an associated finalizer. Assuming that SetFinalizer
// is not called again, the next time the garbage collector sees
// that obj is unreachable, it will free obj.
//
// SetFinalizer(obj, nil) clears any finalizer associated with obj.
//
// The argument obj must be a pointer to an object allocated by calling
// new, by taking the address of a composite literal, or by taking the
// address of a local variable.
// The argument finalizer must be a function that takes a single argument
// to which obj's type can be assigned, and can have arbitrary ignored return
// values. If either of these is not true, SetFinalizer may abort the
// program.
//
// Finalizers are run in dependency order: if A points at B, both have
// finalizers, and they are otherwise unreachable, only the finalizer
// for A runs; once A is freed, the finalizer for B can run.
// If a cyclic structure includes a block with a finalizer, that
// cycle is not guaranteed to be garbage collected and the finalizer
// is not guaranteed to run, because there is no ordering that
// respects the dependencies.
//
// The finalizer is scheduled to run at some arbitrary time after the
// program can no longer reach the object to which obj points.
// There is no guarantee that finalizers will run before a program exits,
// so typically they are useful only for releasing non-memory resources
// associated with an object during a long-running program.
// For example, an os.File object could use a finalizer to close the
// associated operating system file descriptor when a program discards
// an os.File without calling Close, but it would be a mistake
// to depend on a finalizer to flush an in-memory I/O buffer such as a
// bufio.Writer, because the buffer would not be flushed at program exit.
//
// It is not guaranteed that a finalizer will run if the size of *obj is
// zero bytes, because it may share same address with other zero-size
// objects in memory. See http://go.dev/ref/spec#Size_and_alignment_guarantees.
//
// It is not guaranteed that a finalizer will run for objects allocated
// in initializers for package-level variables. Such objects may be
// linker-allocated, not heap-allocated.
//
// Note that because finalizers may execute arbitrarily far into the future
// after an object is no longer referenced, the runtime is allowed to perform
// a space-saving optimization that batches objects together in a single
// allocation slot. The finalizer for an unreferenced object in such an
// allocation may never run if it always exists in the same batch as a
// referenced object. Typically, this batching only happens for tiny
// (on the order of 16 bytes or less) and pointer-free objects.
//
// A finalizer may run as soon as an object becomes unreachable.
// In order to use finalizers correctly, the program must ensure that
// the object is reachable until it is no longer required.
// Objects stored in global variables, or that can be found by tracing
// pointers from a global variable, are reachable. For other objects,
// pass the object to a call of the KeepAlive function to mark the
// last point in the function where the object must be reachable.
//
// For example, if p points to a struct, such as os.File, that contains
// a file descriptor d, and p has a finalizer that closes that file
// descriptor, and if the last use of p in a function is a call to
// syscall.Write(p.d, buf, size), then p may be unreachable as soon as
// the program enters syscall.Write. The finalizer may run at that moment,
// closing p.d, causing syscall.Write to fail because it is writing to
// a closed file descriptor (or, worse, to an entirely different
// file descriptor opened by a different goroutine). To avoid this problem,
// call KeepAlive(p) after the call to syscall.Write.
//
// A single goroutine runs all finalizers for a program, sequentially.
// If a finalizer must run for a long time, it should do so by starting
// a new goroutine.
//
// In the terminology of the Go memory model, a call
// SetFinalizer(x, f) “synchronizes before” the finalization call f(x).
// However, there is no guarantee that KeepAlive(x) or any other use of x
// “synchronizes before” f(x), so in general a finalizer should use a mutex
// or other synchronization mechanism if it needs to access mutable state in x.
// For example, consider a finalizer that inspects a mutable field in x
// that is modified from time to time in the main program before x
// becomes unreachable and the finalizer is invoked.
// The modifications in the main program and the inspection in the finalizer
// need to use appropriate synchronization, such as mutexes or atomic updates,
// to avoid read-write races.
func SetFinalizer(obj any, finalizer any) {
if debug.sbrk != 0 {
// debug.sbrk never frees memory, so no finalizers run
// (and we don't have the data structures to record them).
return
}
e := efaceOf(&obj)
etyp := e._type
if etyp == nil {
throw("runtime.SetFinalizer: first argument is nil")
}
if etyp.kind&kindMask != kindPtr {
throw("runtime.SetFinalizer: first argument is " + etyp.string() + ", not pointer")
}
ot := (*ptrtype)(unsafe.Pointer(etyp))
if ot.elem == nil {
throw("nil elem type!")
}
if inUserArenaChunk(uintptr(e.data)) {
// Arena-allocated objects are not eligible for finalizers.
throw("runtime.SetFinalizer: first argument was allocated into an arena")
}
// find the containing object
base, _, _ := findObject(uintptr(e.data), 0, 0)
if base == 0 {
// 0-length objects are okay.
if e.data == unsafe.Pointer(&zerobase) {
return
}
// Global initializers might be linker-allocated.
// var Foo = &Object{}
// func main() {
// runtime.SetFinalizer(Foo, nil)
// }
// The relevant segments are: noptrdata, data, bss, noptrbss.
// We cannot assume they are in any order or even contiguous,
// due to external linking.
for datap := &firstmoduledata; datap != nil; datap = datap.next {
if datap.noptrdata <= uintptr(e.data) && uintptr(e.data) < datap.enoptrdata ||
datap.data <= uintptr(e.data) && uintptr(e.data) < datap.edata ||
datap.bss <= uintptr(e.data) && uintptr(e.data) < datap.ebss ||
datap.noptrbss <= uintptr(e.data) && uintptr(e.data) < datap.enoptrbss {
return
}
}
throw("runtime.SetFinalizer: pointer not in allocated block")
}
if uintptr(e.data) != base {
// As an implementation detail we allow to set finalizers for an inner byte
// of an object if it could come from tiny alloc (see mallocgc for details).
if ot.elem == nil || ot.elem.ptrdata != 0 || ot.elem.size >= maxTinySize {
throw("runtime.SetFinalizer: pointer not at beginning of allocated block")
}
}
f := efaceOf(&finalizer)
ftyp := f._type
if ftyp == nil {
// switch to system stack and remove finalizer
systemstack(func() {
removefinalizer(e.data)
})
return
}
if ftyp.kind&kindMask != kindFunc {
throw("runtime.SetFinalizer: second argument is " + ftyp.string() + ", not a function")
}
ft := (*functype)(unsafe.Pointer(ftyp))
if ft.dotdotdot() {
throw("runtime.SetFinalizer: cannot pass " + etyp.string() + " to finalizer " + ftyp.string() + " because dotdotdot")
}
if ft.inCount != 1 {
throw("runtime.SetFinalizer: cannot pass " + etyp.string() + " to finalizer " + ftyp.string())
}
fint := ft.in()[0]
switch {
case fint == etyp:
// ok - same type
goto okarg
case fint.kind&kindMask == kindPtr:
if (fint.uncommon() == nil || etyp.uncommon() == nil) && (*ptrtype)(unsafe.Pointer(fint)).elem == ot.elem {
// ok - not same type, but both pointers,
// one or the other is unnamed, and same element type, so assignable.
goto okarg
}
case fint.kind&kindMask == kindInterface:
ityp := (*interfacetype)(unsafe.Pointer(fint))
if len(ityp.mhdr) == 0 {
// ok - satisfies empty interface
goto okarg
}
if iface := assertE2I2(ityp, *efaceOf(&obj)); iface.tab != nil {
goto okarg
}
}
throw("runtime.SetFinalizer: cannot pass " + etyp.string() + " to finalizer " + ftyp.string())
okarg:
// compute size needed for return parameters
nret := uintptr(0)
for _, t := range ft.out() {
nret = alignUp(nret, uintptr(t.align)) + uintptr(t.size)
}
nret = alignUp(nret, goarch.PtrSize)
// make sure we have a finalizer goroutine
createfing()
systemstack(func() {
if !addfinalizer(e.data, (*funcval)(f.data), nret, fint, ot) {
throw("runtime.SetFinalizer: finalizer already set")
}
})
}
看代码,看不出什么。其端倪在注释中。注意如下注释:
// Finalizers are run in dependency order: if A points at B, both have
// finalizers, and they are otherwise unreachable, only the finalizer
// for A runs; once A is freed, the finalizer for B can run.
// If a cyclic structure includes a block with a finalizer, that
// cycle is not guaranteed to be garbage collected and the finalizer
// is not guaranteed to run, because there is no ordering that
// respects the dependencies.
这段英文翻译成中文如下:
Finalizers(终结器)按照依赖顺序运行:如果 A 指向 B,两者都有终结器,并且它们除此之外不可达,则仅运行 A 的终结器;一旦 A 被释放,可以运行 B 的终结器。如果一个循环结构包含一个具有终结器的块,则该循环体不能保证被垃圾回收并且终结器不能保证运行,因为没有符合依赖关系的排序方式。
这意思很明显了,析构函数会检查当前对象A是否有外部对象指向当前对象A。如果有外部对象指向当前对象A时,A的析构是无法执行的;如果有外部对象指向当前对象A时,A的析构才能执行。
代码中的a和b是循环依赖,当析构判断a和b时,都会有外部对象指向a和b,析构函数无法执行。析构无法执行,内存也无法回收。因此答案选A。
去掉析构函数后,a和b肯定会被释放的。不用析构函数去证明,那如何证明呢?用以下代码就可以证明,代码如下:
package main
import (
"fmt"
"runtime"
"time"
)
type ListNode struct {
Val [1024 * 1024]bool
Next *ListNode
}
func printAlloc() {
var m runtime.MemStats
runtime.ReadMemStats(&m)
fmt.Printf("%d KB\n", m.Alloc/1024)
}
func main0() {
printAlloc()
a := &ListNode{Val: [1024 * 1024]bool{true}}
b := &ListNode{Val: [1024 * 1024]bool{false}}
a.Next = b
b.Next = a
// runtime.SetFinalizer(a, func(obj *ListNode) {
// fmt.Printf("a被删除--")
// })
printAlloc()
}
func main() {
fmt.Print("开始")
main0()
time.Sleep(1 * time.Second)
runtime.GC()
time.Sleep(1 * time.Second)
runtime.GC()
time.Sleep(1 * time.Second)
runtime.GC()
time.Sleep(1 * time.Second)
runtime.GC()
time.Sleep(1 * time.Second)
runtime.GC()
fmt.Print("结束")
printAlloc()
}
根据运行结果,内存大小明显变小,说明a和b已经被回收了。
让我们再看看有析构函数的情况,运行结果是咋样的,如下:
package main
import (
"fmt"
"runtime"
"time"
)
type ListNode struct {
Val [1024 * 1024]bool
Next *ListNode
}
func printAlloc() {
var m runtime.MemStats
runtime.ReadMemStats(&m)
fmt.Printf("%d KB\n", m.Alloc/1024)
}
func main0() {
printAlloc()
a := &ListNode{Val: [1024 * 1024]bool{true}}
b := &ListNode{Val: [1024 * 1024]bool{false}}
a.Next = b
b.Next = a
runtime.SetFinalizer(a, func(obj *ListNode) {
fmt.Printf("a被删除--")
})
printAlloc()
}
func main() {
fmt.Print("开始")
main0()
time.Sleep(1 * time.Second)
runtime.GC()
time.Sleep(1 * time.Second)
runtime.GC()
time.Sleep(1 * time.Second)
runtime.GC()
time.Sleep(1 * time.Second)
runtime.GC()
time.Sleep(1 * time.Second)
runtime.GC()
fmt.Print("结束")
printAlloc()
}
根据运行结果,有析构函数的情况下,a和b确实是无法被回收。
1.不要怀疑八股文的正确性,golang的垃圾回收确实是根可达算法。
2.不要用析构函数去测试无用对象被回收的情况,上面的例子也看到了,两对象的循环引用,析构函数的测试结果就是错误的。只能根据内存变化,看无用对象是否被回收。
3.在写代码的时候,能手动设置引用为nil,最好手动设置,这样能更好的避免内存泄漏。
公众号:福大大架构师每日一题大家好,又见面了,我是你们的朋友全栈君。1清华大学的RealAI团队15分钟解锁19款手机刚刚,清华大学的一条重大发现,利用人脸识别技术的漏洞,“15分钟解锁19个陌生智能国产手机”的事件,引发无数网友关注。据悉,清华大学的RealAI团队共选取了20款手机,其中1款是国外的,另外19款都是我们国产的智能手机,均来自排名前五的国产手机品牌,每一品牌下选取了3-4款不同价位的手机型号,覆盖低端机到旗舰机。1)测试步骤如下:第一步,清华大学的测试人员,把19部国产手机,人脸识别全部绑定为旁边的“1号同学”; 第二步,让旁边的同学、同事,拿起他的手机,进行人脸识别。请注意,这里直接识别非绑定人员的面部是无法打开的; 第三步:将1号同学的照片,特别是眼睛部位图案打印并裁剪出来,贴到我们平时戴的眼镜上面。然后,奇迹发生了,解锁成功了! 据了解,研究团队选取了20款手机进行测试,除了一台iPhone11外,其余安卓机型均在15分钟内破解。这19款手机覆盖排名前五的国产手机品牌的低端机到旗舰机型。其中一款是某品牌在去年12月发布的最新款旗舰机。从被破解的程度上看,攻击这些手机的难度几乎没有任何区别,
害,川川进军ubuntu,安装谷歌浏览器也是很头疼,真是一把心酸史! 问题很多,比如无法访问归档,所请求的操作需要超级用户权限,这些问题很奇怪,其实是别的操作造成的,下面我就理清了安装的详细步骤 步骤一: 在Ubuntu系统中打开现有的火狐浏览器,输入Chrome浏览器的网址:https://www.google.cn/chrome/ 根据提示下载就ok,这一步没啥好说的 步骤二: 问题1:无法访问归档,真是很神奇 解决方案:cd进入下载安装后的google-chrme目录,找到如下的安装包 问题2:我下载后就去文件夹找,在下载里面没看到这个文件,到底在哪呢? 于是我就到浏览器下载哪里点击图表进去,在tem下面,总感觉还是很不舒服,我就把这个文件复制粘贴到下载里面去(主要是便于我根据百度里面的教程继续下去) 复制粘贴会吧?这就是不说了。再看:这个文件是被锁住了的看到没有,看图标就很明显是吧,看图操作:右击选择提取到此处 然后文件就是这样的了:(没有锁这个标志了吧) 步骤三:文件现在没问题了,于是我们要在ubuntu上面安装 进入目录:cd下载复制然后呢? 安装依赖包:sudo
【Python基础】时间和日期模块Python中的time和datetime用法整理。 一、Python中时间的四种类型时间戳float时间元组struct_time时间字符串string时间对象datetime,date,time二、time模块#导入包 importtime复制1.时间类型以时间戳(秒)形式,返回当前时间time.time() #输出:1552884340.400742复制以时间元组形式struct_time,返回本地时间time.localtime() #输出:time.struct_time(tm_year=2019,tm_mon=3,tm_mday=18,tm_hour=12,tm_min=47,tm_sec=18,tm_wday=0,tm_yday=77,tm_isdst=0)复制以字符串形式,返回格式化的时间time.strftime("%Y-%m-%d%H:%M:%S",time.localtime()) #输出:'2019-03-1812:48:50'复制格式化指定时间戳,输出字符串time.strftime(&
深度强化学习实验室来源:AI科技评论,编译|bluemin 作者:DeepRL探索VS利用,这是强化学习中至关重要的话题。我们希望强化学习中的智能体尽快找到最佳策略。然而,在没有充分探索的情况下就盲目地选择某个策略会带来一定的问题,因为这会导致模型陷入局部最优甚至完全不收敛。目前的强化学习算法朝着回报值最大化的方向优化,而探索仍然更像是一个开放性话题。本文讨论几种常见的深度强化学习探索策略。由于这个话题非常庞大,本文并不能涵盖所有的内容。1经典探索策略首先介绍几种经典的探索算法,这些算法在多臂老虎机问题或简单的表格型强化学习中颇具成效。-贪婪:智能体以较小的概率进行随机探索,在大多数情况以概率选择当前的最优动作。置信区间上界(UCB):智能体选择当前最优的动作来最大化置信区间上界,其中是到时间t为止与动作a有关的平均奖励函数,是与已执行动作a的次数成反比的函数。玻尔兹曼探索策略:智能体根据学习到的由温度参数调节的Q值,从玻尔兹曼分布(softmax函数)中选择动作。汤普森采样:智能体将追踪记录的最优动作概率作为先验分布,然后从这些分布中采样。当神经网络用于函数逼近时,以下策略可以在深度
作为领先的内容提供商和社交媒体,Tumblr吸引了3.71亿的月访问量、2.8亿个博客和5330万个每日帖子。Tumblr的流行为广告客户提供了通过赞助帖子推广产品的大好机会。然而,由于Tumblr并不要求用户在注册时提供性别和年龄等信息,因此针对特定人群投放广告是一项具有挑战性的任务。因此,为了促进广告定位,使用丰富的内容如帖子、图片和社会联系来预测用户的人口结构是很重要的。在本文中,我们提出了年龄和性别预测(基于图像的深度学习模型),该模型考虑了用户活动和内容特征。对于基于图像的模型,我们提出了网络嵌入和标签传播两种方法来生成连接特征,并直接推断使用用户的人口学。对于深度学习模型,我们利用卷积神经网络(CNN)和多层感知器(MLP)来预测用户的年龄和性别。在真实的Tumblr日常数据集上的实验结果表明,我们的方法明显优于基线模型,在年龄上的准确率提高了81%,在性别上的准确率提高了5%。原文题目:MachineLearning:Large-scaleGender/AgePredictionofTumblrUsersTumblr,asaleadingcontentprovideran
I.背景及需求为了看看我的博客是不是我一个人的单机游戏,所以就想着统计一下总的访问量,每日的访问人数,哪些博文又是大家感兴趣的,点击得多的;因此就萌发了自己撸一个pv/uv统计的服务,当然我这个也不需要特别完善高大上,能满足我自己的基本需要就可以了希望统计站点(域名)总访问次数希望统计站点总的访问人数,当前访问者在访问人数中的排名(即这个ip是所有访问ip中的第多少位访问的这个站点)每个子页面都有访问次数,访问总人数,当前ip访问的排名统计同一个ip,同一天内访问同一个子页面,pv次数只加1次;隔天之后,再次访问pv+1II.方案设计前面的背景和需求,可以说大致说明了我们要做个什么东西,以及需要注意哪些事项,再进行方案设计的过程中,则需要对需求进行详细拆解1.术语说明前面提到了pv,uv,在我们的实际实现中,会发现这个服务中对于pv,uv的定义和标准定义并不是完全一致的,下面进行说明a.pvpageviste,每个页面的访问次数,在本服务中,我们的pv指的是总量,即从开始接入时,到现在总的访问次数但是这里有个限制:一个合法的ip,一天之内pv统计次数只能+1次根据ip进行区分,因此需要
作者|王久一 编辑|王久一导读:此文章介绍Linux常用指令中的运行级别,以及我们忘记root密码时的解决方案。毕竟实际开发中我们用的都是命令行,所以掌握常用的指令对于Linux系统使用者是非常重要的。 运行级别运行级别就是操作系统当前正在运行的功能级别。级别是从0到6,具有不同的功能。这些级别定义在/ect/inittab文件中,也可以打开此文件查看和修改当前的运行级别(最末尾)。这个文件是init程序寻找的主要文件,最先运行的服务是那些放在/etc/rc.d目录下的文件。运行级别:0关机1单用户2不完全多用户,无网络服务3多用户,有网络服务4未分配5图形界面6重启切换运行级别:init[0123456]如:我们在图形界面下打开终端输入:init3,通过init来切换到了多用户无网络服务的级别,并且没有图形界面只有命令行,再输入init5,回到了图形界面。问题如果我们忘记了root密码,怎么找回?思路:进入单用户模式,单用户模式下修改root密码。因为进入单用户模式,root不需要输入密码就可以登陆。1.启动CentOS2.进入到下方时,按Enter键3.进入下方界面,输入e编辑命令
前几天读完了《世界观》这本书,它把人的世界观类比成各种信念的拼图,感觉人生之旅也是一种拼图,心灵成长的拼图。“零基础学编程”这个系列的文章已经写完37篇了,学编程也像是一幅庞大的拼图,需要在学习过程中不断地完善。 一开始面对一个未知的世界,可能感觉无处下手,但只要起步了,你就在不断地探索这块庞大的知识拼图,核心的学习方法就是英文、搜索、实践、教练反馈、总结等,随着学习的深入,不断地加入程序语法、编程算法、数据结构、数据库、硬件知识等拼图,再在解决实际问题的过程中不断地创建各个拼图之间的连接,才能学会编程。我建议刚学编程的朋友,要找张大纸把这些知识点记录整理下来,等你积累到100张、500张、1000张拼图时,也就变成编程高手了。在写这个系列文章时,开始几篇让你快速上手,对编程不再恐惧,建立信心;有几篇文章针对复利数据表问题展开;有几篇讲述了有趣的小海龟做图让你有直观的感受;有些是发邮件、生成二维码、数据分析等实用的小程序;中间则穿插着讲解略显枯燥的语法知识点。同一个编程问题,解决的手段很多,随着掌握的知识点、模块库越来越多,会出现更方便、更有效率的解决方案,但所有这些知识点都是连接在一
自上周被微信小程序刷屏之后,这周大家都在谈微信小程序能够带来哪些红利的话题,其实我想从程序员的角度来谈谈,带给我们程序员来的红利,或许是我们程序员创业或者赚钱的机遇。其实我从《作为移动开发程序员,你是否患有微信应用号“恐惧症”?》文章中已经说过了,微信小程序可能是原生的机遇,在程序员面对微信小程序的恐惧中说其实也是我们程序员创业的春天或者挣外快的一个机遇。我们想想,像微信服务号是面对企业的一种宣传,对企业有利,而微信公众号是自媒体人的天下,打开了自媒体人的春天,自媒体时代到来了,对于爱写作的人来说真的是迎来了money时代。而微信小程序,可能带着我们程序员一起飞。为什么这么说呢?且听我慢慢给你分析技术角度从技术角度来讲,我们程序员有着先天的优势,可以很快的进入开发微信小程序,比其他一些不懂技术的创业者或者企业有着自带发动机的速度,可以称为第一批吃螃蟹的人。而他们呢?只能靠外包,当然如果你从现在也开始学习开发微信小程序,也可以接他们外包,还能赚外快。回到做我们程序员自己心中的微信小程序的点子上来,我们可以很快的进入开发,实现自己的想法,把小程序开发完,第一时间上线,这样的优势,可以让我们
MongoDB是非关系型数据库的典型代表,DB-EnginesRanking数据显示,近年来,MongoDB在NoSQL领域一直独占鳌头。MongoDB是为快速开发互联网应用 而设计的数据库系统,其数据模型和持久化策略就是为了构建高读/写的性能,并且可以方面的弹性拓展。目前公司使用到的MongoDB的主要场景有库存中心(原料出入库、商品出入库、商品上下架变动、与其它系统平台的交互报文等)、物流配送(订单的物流信息、配送信息、地理位置信息等)、日志中心(系统应用和APP的log信息、调用依赖信息等)、商品中心(商品数据、推送信息等)、运维管理平台(收集记录的变更信息等)等。随着MongoDB的普及和使用量的快速增长,为了规范使用,便于管理和获取更高的性能,整理此文档。我们从数据库设计规范、集合设计规范、文档设计规范、连接规范、操作规范等5个方面进行阐述和要求。 1.数据库设计规范 (1)数据库名约定为小写。 (2)数据库名称不能包含除’_’以外的特殊字符,例如:/\.“$。 (3)数据库名称最多为64个字符。 (4)数据库上线需经过DBA评审。 2.集合设计规范 (1)集合名称
1、最新版 中文破解版v7.2下载:链接:https://pan.baidu.com/s/1u-njt1SieNKydV-jcSQcpQ提取码:993j 中文破解版v7.2激活:https://www.macappbox.com/a/1042.html 2、低版本适用Mac10.13及其以上版本的OmniGraffleforMac7.11.3中文破解版 下载:https://downloads.omnigroup.com/software/MacOSX/10.13/OmniGraffle-7.11.3.dmg 或者根据https://downloads.omnigroup.com/software/MacOSX/进去找一个版本 激活:链接:https://pan.baidu.com/s/1s3J8D-lMK9nqTTkIv0s1FQ提取码:3jrf 业精于勤荒于嬉行成于思毁于随
ImageLoader在github上的地址:https://github.com/nostra13/Android-Universal-Image-Loader 配置: 1.在app的buildgradle中添加以来: compile'com.nostra13.universalimageloader:universal-image-loader:1.9.5'复制 例如: dependencies{implementationfileTree(include:['*.jar'],dir:'libs')implementation'com.android.support:appcompat-v7:26.1.0'implementation'com.android.support.constraint:constraint-layout:1.0.2'implementation'com.android.support:support-v4:26.1.0'implementation'com.android.support:recyclerview-v7:26.1.0'test
提供了很多的验证的方式,目前没有测试完全通过,有些不确定怎么玩。 先看官方文档 Verify-Verifythatthecomponent'svalueisequaltotheargument. VerifyNot-Verifythatthecomponent'svalueisNOTequaltotheargument. VerifyRegex-Verifythatthecomponent'svaluematchestheRegularExpressionprovidedintheargument. VerifyNotRegex-Verifythatthecomponent'svaluedoesNOTmatchtheRegularExpressionprovidedintheargument. VerifyWildcard-Verifythatthecomponent'svaluematchessomewildcardexpressionprovidedintheargument. VerifyNotWildcard-Verifythatthecomponent'svaluedoes
2015年5月8号,今天OA上提出离职申请了,晚上还是加班到了挺晚的,有个牙刷的项目没搞完,不过焊接机的项目算是结束了,我很开心能做完成现在的焊接机版本,接下去就是稍微做下微调了,希望不要出什么大问题才是。然后牙刷的项目,晚上也是为了这个事加班到了快10点,希望这两天能完成这件事吧,到现在还是没底,不知道到底能不能完成了。加油吧~! 这几天好烦。下班回到宿舍都是在看电视,电影、动漫什么的,想花点时间找找网上的面试题做做,或者想总结下现在工作,但是~今天的日记也是我勉强逼自己过来写的。哎,不知道在这里写点什么。心情不好。写不出来。只想好好休息。 睡了。晚安,希望明天一切顺利。 加油!
一、说明 Python3----网上很多文章都是用Python2,RobotFramework的部分文档没更新也直接写着不支持Python3(如RIDEdoesnotyetsupportPython3),但事实上RobotFramework下的所有项目的最新版本都是支持Python3.6+了的,反倒是Python2以后不久可能就不支持了(如RIDE1.7.4THISISTHELASTRELEASESUPPORTINGPYTHON2.7)。 RobotFramework----RobotFramework是一个开源的自动化框架。更本质一点就是可以把你编写好的函数导出来,然后像写存储过程一样写代码,达到降低难度的目的。比如你在python文件中写好了一个函数login_system(username,password),然后RobotFramework就可以导出为LoginSystem,别人写脚本时就可以写成LoginSystemusernamepassword。 RIDE----RIDE是使用wxPython库编写的RobotFramework的图形界面。RobotFramework的使
1、github创建了git仓库并建立了README文件; 2、本地仓库添加了github上的git仓库作为远程仓库,起名origin; $gitremoteaddoriginhttps://github.com/tielemao/TielemaoMarkdown 3、问题来了,本地仓库在想做同步远程仓库到本地为之后本地仓库推送到远程仓库做准备时报错了,错误如下: fatal:refusingtomergeunrelatedhistories(拒绝合并不相关的历史) gitpush-foriginjin--no-verify 忽略数据检测 解决 1、主要原因还是在于本地仓库和远程仓库实际上是独立的两个仓库。 假如我之前是直接clone的方式在本地建立起远程github仓库的克隆本地仓库就不会有这问题了。 发现可以在pull命令后紧接着使用--allow-unrelated-history选项来解决问题(该选项可以合并两个独立启动仓库的历史)。 $gitpu
异构 O.Marfoq,G.Neglia,L.Kameni,andR.Vidal,“PersonalizedFederatedLearningthroughLocalMemorization,”arXiv:2111.09360[cs,stat],Mar.2022,Accessed:Mar.19,2022.[Online].Available:http://arxiv.org/abs/2111.09360 这篇蔚蓝海岸大学埃森哲技术研究院的文章同样在研究PFL,而且大有顶会论文的趋势。该团队对于PFL的理解为在对每个用户训练得到单独模型的同时,还要利用其他用户的知识。因此,这篇文章的思路依然是对相似用户进行聚类。那么聚类标准是什么呢?每个用户对输入的表示(embedding)。之前我一直觉得embedding的训练比较难,其实就是每个用户分类层的前一层的输出。比如CNN的最优一个卷积层,RNN的最后一个隐藏状态。这样聚类没有触及到最优的分类,因此避免了隐私的泄露,但是又利用了用户对数据进行表征的网络,还是比较巧妙。 然后根据聚类结果对他们的网络进行融合,在两个用户聚类的时候,依然是典型的
JackSon学习笔记 Jackson框架是基于Java平台的一套数据处理工具,被称为“最好的JavaJson解析器”。Jackson框架包含了3个核心库:streaming,databind,annotations.Jackson还包含了其它数据处理类库,此外不作说明。Jackson版本:1.x(目前版本从1.1~1.9)与2.x。1.x与2.x从包的命名上可以看出来,1.x的类库中,包命名以:org.codehaus.jackson.xxx开头,而2.x类库中包命令:com.fastxml.jackson.xxx开头 JacksonHomePage:https://github.com/FasterXML/jacksonJacksonWiki:http://wiki.fasterxml.com/JacksonHomeJacksondoc:https://github.com/FasterXML/jackson-docs
配置文件 如果想保留eslint的语法检测,那就把不符合自己习惯的规则去掉吧。 配置文件在项目根目录里,文件名以.eslintrc.*为名。 module.exports={ root:true, parser:'babel-eslint', parserOptions:{ //设置"script"(默认)或"module"如果你的代码是在ECMAScript中的模块。 sourceType:'module' }, env:{ browser:true, }, //https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style extends:'standard', //requiredtolint*.vuefiles plugins:[ 'html' ], //addyourcustomruleshere 'rules':{ //allowparen-lessarrowfunctions 'arrow-parens':0, //allowasync-await 'generator-s
1.模拟linnux登录shell #/bin/bashecho-n"login:"readnameecho-n"password:"readpasswdif[$name="cht"-a$passwd="abc"];thenecho"thehostandpasswordisright!"elseecho"inputiserror!"fi 2.比较两个数大小 #/bin/bashecho"pleaseentertwonumber"readareadbiftest$a-eq$bthenecho"NO.1=NO.2"eliftest$a-gt$bthenecho"NO.1>NO.2"elseecho"NO.1<NO.2" 3.查找/root/目录下是否存在该文件 #/bin/bashecho"enterafilename:"readaiftest -e/root/$athenecho"thefileisexist!"elseecho"thefileisnotexist!"fi 4.for循环的使用 #/bin/bashclearfornumin12345678910d