script src="https://lib.sinaapp.com/js/jquery/2.0.2/jquery-2.0.2.min.js"></script> <script> var allp =$("div p"); for(var i=0;i<allp.length;i++){ allp[i].attr("class","i+2"); console.log (allp[i].attr("class")); } </script> 结果控制台报错: 提示allp[i].attr()不是一个方法,而attr()是jq对象的方法,这个报错等于说allp[ 1.2 问题解决: 1)转化为jq对象 for(var i=0;i<allp.length;i++){ $(allp[i]).attr("class",i+2); 综上,正确代码为 var allp=$("div p"); allp.attr("class",function(i,n){ return Number(n)+1;
,因此当这个函数执行完成之后就有 m0.p = allp[0] allp[0].m = &m0 到此m0, g0, 和m需要的p完全关联在一起了。 if nprocs > int32(len(allp)) { //初始化时 len(allp) == 0 // Synchronize with retake, which could lock(&allpLock) if nprocs <= int32(cap(allp)) { allp = allp[:nprocs] } else copy(nallp, allp[:cap(allp)]) allp = nallp } unlock(&allpLock) } p, nprocs) 循环创建并初始化nprocs个p结构体对象并依次保存在allp切片之中 把m0和allp[0]绑定在一起,即m0.p = allp[0], allp[0].m = m0 把除了allp
2核2G云服务器首年95元,GPU云服务器低至9.93元/天,还有更多云产品低至0.1折…
该函数主要有以下步骤: 计算当前真正p的数量nprocs,初始化保存所有p的全局变量allp,allp为一个切片,它里面保存的对象为*p类型,利用make初始化allp. 将m0和allp[0]互相绑定,并将allp[0]状态设置为_Prunning 将allp[1:nprocs]中的p放入到全局变量sched的pidle空闲队列中 上述步骤描述的是最基本的情况,即没有通过 ) if nprocs <= int32(cap(allp)) { // 调整allp的len为nprocs, allp的cap不变 allp = allp[:nprocs] } else copy(nallp, allp[:cap(allp)]) // 将allp替换为新创建的切片nallp allp = nallp } unlock(&allpLock) } allp[0](与m0绑定的p)之外的所有的p放入到空闲链表中 for i := nprocs - 1; i >= 0; i-- { p := allp[i] // 如果当前的p是allp[0
uintptr // 保存所有的 g allgs []*g // 保存所有的 m allm *m // 保存所有的 p,_MaxGomaxprocs = 1024 allp 因此程序刚启动时 allgs,allm 和allp 都不包含任何 g,m 和 p。 还是引用阿波张公号文章里的总结,写得太好了,很简洁,很难再优化了: 使用 make([]p, nprocs) 初始化全局变量 allp,即 allp = make([]p, nprocs) 循环创建并初始化 nprocs 个 p 结构体对象并依次保存在 allp 切片之中 把 m0 和 allp[0] 绑定在一起,即 m0.p = allp[0],allp[0].m = m0 把除了 allp[0] 最后我们将 allp 和 allm 都添加到图上: ?
)) { lock(&allpLock) if nprocs <= int32(cap(allp)) { allp = allp[:nprocs] } else { nallp := make([]*p, nprocs) copy(nallp, allp[:cap(allp)]) allp = nallp } unlock(&allpLock) } () // 不能释放 p 本身,因为他可能在 m 进入系统调用时被引用 } // 释放完 P 之后重置allp的长度 if int32(len(allp)) ! P 状态设置为 _Pdead; 通过截断改变全局变量 allp 的长度保证与期望处理器数量相等; 遍历 allp 检查 P 的是否处于空闲状态,是的话放入到空闲列表中; P.init func (pp 需要注意的是,遍历 allp 时是从随机位置上的 P 开始,防止每次遍历时使用同样的顺序访问allp中的元素; 所有的可能性都尝试过了,在准备休眠 M 之前,还要进行额外的检查; 首先检查此时是否是 GC
We don't need to snapshot the contents because // everything up to cap(allp) is immutable. allpSnapshot := allp // return P and block lock(&sched.lock) ...... 但这里为了保证公平性,遍历allp时并不是固定的从allp[0]即第一个p开始,而是从随机位置上的p开始,而且遍历的顺序也随机化了,并不是现在访问了第i个p下一次就访问第i+1个p,而是使用了一种伪随机的方式遍历 allp中的每个p,防止每次遍历时使用同样的顺序访问allp中的元素。 如果第一次随机选择的offset = 6,coprime = 3(3与8互质,满足算法要求)的话,则从allp切片中偷取的下标顺序为6, 1, 4, 7, 2, 5, 0, 3,计算过程: 6,(6+3
切片中的处理器数量少于期望数量,对 allp 扩容 if nprocs > int32(len(allp)) { // 加锁 lock(&allpLock) if nprocs < = int32(cap(allp)) { // 如果要达到的 P 个数 nprocs 小于当前全局 P 切片到容量 allp = allp[:nprocs] // 在当前全局 P 切片上截取前 [:cap(allp)]) allp = nallp // 新的 nallp 切片赋值给旧的 allp } ...... _g_.m.p.ptr().m = 0 } _g_.m.p = 0 // 将处理器 allp[0] 绑定到当前 M p := allp[0] p.m (allp)) !
调用 handoffp 让出处理器的使用权; 抢占当前处理器 func retake(now int64) uint32 { n := 0 lock(&allpLock) // 遍历 allp 数组 for i := 0; i < len(allp); i++ { _p_ := allp[i] if _p_ == nil { continue } pd := &_p 调用 handoffp 让出处理器的使用权 func retake(now int64) uint32 { n := 0 lock(&allpLock) // 遍历 allp 数组 for i := 0; i < len(allp); i++ { _p_ := allp[i] if _p_ == nil { continue } pd := &_p_.sysmontick runtime/proc.go: preemptall func preemptall() bool { res := false // 遍历所有的 P for _, _p_ := range allp
方法和获取书名方法一样: # 作者,由于信息在一个p标签内部,# 我们获取到标签直接get_text()方法获得文本内容allp = soup.find_all('p', class_='pl')authors = [p.get_text() for p in allp] 运行结果: ['[美] 卡勒德·胡赛尼 / 李继宏 / 上海人民出版社 / 2006-5 / 29.00元', '[法] 圣埃克苏佩里 soup.find_all('div', class_='pl2') names = [a.find('a')['title'] for a in alldiv] # 作者 allp = soup.find_all('p', class_='pl') authors = [p.get_text() for p in allp] # 评分 starspan
soup.find_all('div', class_='pl2') names = [a.find('a')['title'] for a in alldiv] # 作者 allp = soup.find_all('p', class_='pl') authors = [p.get_text() for p in allp] # 评分
调用 handoffp 让出处理器的使用权; 抢占当前处理器 func retake(now int64) uint32 { n := 0 lock(&allpLock) // 遍历 allp 数组 for i := 0; i < len(allp); i++ { _p_ := allp[i] if _p_ == nil { continue } pd := &_p sysmon_preempt] 调用 handoffp 让出处理器的使用权 func retake(now int64) uint32 { n := 0 lock(&allpLock) // 遍历 allp 数组 for i := 0; i < len(allp); i++ { _p_ := allp[i] if _p_ == nil { continue } pd := &_p runtime/proc.go: preemptall func preemptall() bool { res := false // 遍历所有的 P for _, _p_ := range allp
forcePreemptNS = 10 * 1000 * 1000 // 10ms func retake(now int64) uint32 { n := 0 // Prevent allp lock(&allpLock) // We can't use a range loop over allp because we may // temporarily drop the Hence, we need to re-fetch // allp each time around the loop. for i := 0; i < len(allp); i++ { //遍历所有的P _p_ := allp[i] if _p_ == nil { // This can happen if procresize has grown // allp but not yet created new Ps.
stealRunNextG := i > 2 // first look for ready queues with more than 1 g if gp := runqsteal(_p_, allp once again // 休眠之前再检查一下所有的 p,看一下是否有工作要做 for i := 0; i < int(gomaxprocs); i++ { _p_ := allp 毕竟前三次的失败经验证明,工作太不好“偷”了,民不聊生啊,只能做得绝一点了, stealRunNextG 控制是否要打 runnext 的主意: stealRunNextG := i > 2 确定好准备偷的对象 allp [enum.position() 之后,调用 runqsteal(_p_,allp[enum.position()],stealRunNextG) 函数执行。
func retake(now int64) uint32 { n := 0 // 防止 allp 数组发生变化,除非我们已经 STW,此锁将完全没有人竞争 lock(&allpLock) for i := 0; i < len(allp); i++ { _p_ := allp[i] ... for i := 0; i < len(allp); i++ { _p_ := allp[i] ...
for _, p := range &allp { if p == nil || p.status == _Pdead { break } // try to retake all P's in Psyscall status for i := 0; i < int(gomaxprocs); i++ { p := allp = 0)" } else { for i := 0; i < int(gomaxprocs); i++ { p := allp[i] c.fractionalMarkWorkersNeeded = 0 } // 重置P中的辅助GC所用的时间统计 // Clear per-P state for _, p := range &allp
还是通过刚才的 stopTheWorldWithSema 源码发现有一个 allp 变量,看起来有所有的 p 的信息。 经搜索 go 运行时有一些全局变量保存了所有的 p 和 m 等信息,如下 于是在 dlv 内原地执行 p allp 将这个切片全部打印出来,然后挨个查看 status,如下(忽略无用的 p) 果然找到了唯一一个
} ...... } 重要的全局变量 allgs []*g // 保存所有的g allm *m // 所有的m构成的一个链表,包括下面的m0 allp []*p // 保存所有的p,len(allp) == gomaxprocs ncpu int32 // 系统中cpu核的数量,程序启动时由runtime 所以程序刚启动时allgs,allm和allp都不包含任何g,m和p。 最后,如果你觉得本文对你有帮助的话,麻烦帮忙点一下文末右下角的 在看 或转发到朋友圈,非常感谢!
for i := 0; i < len(allp); i++ { //遍历所有p,然后根据p的状态进行抢占 _p_ := allp[i] if _p_ == nil { // This can happen if procresize has grown // allp but not yet created new Ps
stealRunNextG := i > 2 // first look for ready queues with more than 1 g if gp := runqsteal(_p_, allp
这里还有个所有P的管理结构 var allp [_MaxGomaxprocs + 1]*p type schedt struct { pidle puintptr // P npidle
扫码关注腾讯云开发者
领取腾讯云代金券